Asterisk - The Open Source Telephony Project  21.4.1
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 <markster@digium.com>
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 <markster@digium.com>
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"
124 #include "asterisk/features_config.h"
125 #include "asterisk/bridge.h"
126 #include "asterisk/stasis_channels.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  <function name="POLARITY" language="en_US">
181  <synopsis>
182  Set or get the polarity of a DAHDI channel.
183  </synopsis>
184  <syntax />
185  <description>
186  <para>The POLARITY function can be used to set the polarity of a DAHDI channel.</para>
187  <para>Applies only to FXS channels (using FXO signalling) with supporting hardware.</para>
188  <para>The polarity can be set to the following numeric or named values:</para>
189  <enumlist>
190  <enum name="0" />
191  <enum name="idle" />
192  <enum name="1" />
193  <enum name="reverse" />
194  </enumlist>
195  <para>However, when read, the function will always return 0 or 1.</para>
196  <example title="Set idle polarity">
197  same => n,Set(POLARITY()=0)
198  </example>
199  <example title="Set reverse polarity">
200  same => n,NoOp(Current Polarity: ${POLARITY()})
201  same => n,Set(POLARITY()=reverse)
202  same => n,NoOp(New Polarity: ${POLARITY()})
203  </example>
204  <example title="Reverse the polarity from whatever it is currently">
205  same => n,Set(POLARITY()=${IF($[ "${POLARITY()}" = "1" ]?0:1)})
206  </example>
207  </description>
208  </function>
209  <info name="CHANNEL" language="en_US" tech="DAHDI">
210  <enumlist>
211  <enum name="dahdi_channel">
212  <para>R/O DAHDI channel related to this channel.</para>
213  </enum>
214  <enum name="dahdi_span">
215  <para>R/O DAHDI span related to this channel.</para>
216  </enum>
217  <enum name="dahdi_group">
218  <para>R/O DAHDI logical group related to this channel.</para>
219  </enum>
220  <enum name="dahdi_type">
221  <para>R/O DAHDI channel type, one of:</para>
222  <enumlist>
223  <enum name="analog" />
224  <enum name="mfc/r2" />
225  <enum name="pri" />
226  <enum name="pseudo" />
227  <enum name="ss7" />
228  </enumlist>
229  </enum>
230  <enum name="keypad_digits">
231  <para>R/O PRI Keypad digits that came in with the SETUP message.</para>
232  </enum>
233  <enum name="reversecharge">
234  <para>R/O PRI Reverse Charging Indication, one of:</para>
235  <enumlist>
236  <enum name="-1"> <para>None</para></enum>
237  <enum name=" 1"> <para>Reverse Charging Requested</para></enum>
238  </enumlist>
239  </enum>
240  <enum name="no_media_path">
241  <para>R/O PRI Nonzero if the channel has no B channel.
242  The channel is either on hold or a call waiting call.</para>
243  </enum>
244  <enum name="buffers">
245  <para>W/O Change the channel's buffer policy (for the current call only)</para>
246  <para>This option takes two arguments:</para>
247  <para> Number of buffers,</para>
248  <para> Buffer policy being one of:</para>
249  <para> <literal>full</literal></para>
250  <para> <literal>immediate</literal></para>
251  <para> <literal>half</literal></para>
252  </enum>
253  <enum name="echocan_mode">
254  <para>W/O Change the configuration of the active echo
255  canceller on the channel (if any), for the current call
256  only.</para>
257  <para>Possible values are:</para>
258  <para> <literal>on</literal> Normal mode (the echo canceller is actually reinitialized)</para>
259  <para> <literal>off</literal> Disabled</para>
260  <para> <literal>fax</literal> FAX/data mode (NLP disabled if possible, otherwise
261  completely disabled)</para>
262  <para> <literal>voice</literal> Voice mode (returns from FAX mode, reverting the changes that were made)</para>
263  </enum>
264  <enum name="dialmode">
265  <para>R/W Pulse and tone dialing mode of the channel.</para>
266  <para>Disabling tone dialing using this option will not disable the DSP used for DTMF detection.
267  To do that, also set the <literal>digitdetect</literal> option. If digit detection is disabled,
268  DTMF will not be detected, regardless of the <literal>dialmode</literal> setting.
269  The <literal>digitdetect</literal> setting has no impact on pulse dialing detection.</para>
270  <para>If set, overrides the setting in <literal>chan_dahdi.conf</literal> for that channel.</para>
271  <enumlist>
272  <enum name="both" />
273  <enum name="pulse" />
274  <enum name="dtmf" />
275  <enum name="tone" />
276  <enum name="none" />
277  </enumlist>
278  </enum>
279  <enum name="waitfordialtone">
280  <para>W/O Duration in ms for which to wait for dial tone on the current call.</para>
281  <para>This setting is will temporarily override the <literal>waitfordialtone</literal>
282  setting in <literal>chan_dahdi.conf</literal> (typically if that setting is disabled).
283  You must call this in a pre-dial handler when making a call on an analog trunk
284  (e.g. FXS-signalled interface).</para>
285  <para>This allows, for example, being able to barge in on an in-use trunk,
286  if dialed specifically, but allows skipping the trunk when routing calls
287  if dial tone is not present on a channel.</para>
288  <para>This setting will only apply to the current (next) call made on the
289  DAHDI channel, and will not persist for future calls.</para>
290  <para>Please keep in mind that due to the way that chan_dahdi implements dial tone detection,
291  DTMF digits on an in-use channel will temporarily relay to any other channels attempting to use the channel for a call.
292  However, voice transmission will not leak.</para>
293  </enum>
294  </enumlist>
295  </info>
296  <info name="Dial_Resource" language="en_US" tech="DAHDI">
297  <para>DAHDI allows several modifiers to be specified as part of the resource.</para>
298  <para>The general syntax is :</para>
299  <para><literal>Dial(DAHDI/pseudo[/extension])</literal></para>
300  <para><literal>Dial(DAHDI/&lt;channel#&gt;[c|r&lt;cadence#&gt;|d][/extension])</literal></para>
301  <para><literal>Dial(DAHDI/(g|G|r|R)&lt;group#(0-63)&gt;[c|r&lt;cadence#&gt;|d][/extension])</literal></para>
302  <para>The following modifiers may be used before the channel number:</para>
303  <enumlist>
304  <enum name="g">
305  <para>Search forward, dialing on first available channel in group (lowest to highest).</para>
306  </enum>
307  <enum name="G">
308  <para>Search backward, dialing on first available channel in group (highest to lowest).</para>
309  </enum>
310  <enum name="r">
311  <para>Round robin search forward, picking up from where last left off (lowest to highest).</para>
312  </enum>
313  <enum name="R">
314  <para>Round robin search backward, picking up from where last left off (highest to lowest).</para>
315  </enum>
316  </enumlist>
317  <para>The following modifiers may be used after the channel number:</para>
318  <enumlist>
319  <enum name="c">
320  <para>Wait for DTMF digit <literal>#</literal> before providing answer supervision.</para>
321  <para>This can be useful on outbound calls via FXO ports, as otherwise
322  they would indicate answer immediately.</para>
323  </enum>
324  <enum name="d">
325  <para>Force bearer capability for ISDN/SS7 call to digital.</para>
326  </enum>
327  <enum name="i">
328  <para>ISDN span channel restriction.</para>
329  <para>Used by CC to ensure that the CC recall goes out the same span.
330  Also to make ISDN channel names dialable when the sequence number
331  is stripped off. (Used by DTMF attended transfer feature.)</para>
332  </enum>
333  <enum name="r">
334  <para>Specifies the distinctive ring cadence number to use immediately after
335  specifying this option. There are 4 default built-in cadences, and up to 24
336  total cadences may be configured.</para>
337  </enum>
338  </enumlist>
339  <example title="Dial 555-1212 on first available channel in group 1, searching from highest to lowest">
340  same => n,Dial(DAHDI/g1/5551212)
341  </example>
342  <example title="Ringing FXS channel 4 with ring cadence 2">
343  same => n,Dial(DAHDI/4r2)
344  </example>
345  <example title="Dial 555-1212 on channel 3 and require answer confirmation">
346  same => n,Dial(DAHDI/3c/5551212)
347  </example>
348  </info>
349  <manager name="DAHDITransfer" language="en_US">
350  <synopsis>
351  Transfer DAHDI Channel.
352  </synopsis>
353  <syntax>
354  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
355  <parameter name="DAHDIChannel" required="true">
356  <para>DAHDI channel number to transfer.</para>
357  </parameter>
358  </syntax>
359  <description>
360  <para>Simulate a flash hook event by the user connected to the channel.</para>
361  <note><para>Valid only for analog channels.</para></note>
362  </description>
363  </manager>
364  <manager name="DAHDIHangup" language="en_US">
365  <synopsis>
366  Hangup DAHDI Channel.
367  </synopsis>
368  <syntax>
369  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
370  <parameter name="DAHDIChannel" required="true">
371  <para>DAHDI channel number to hangup.</para>
372  </parameter>
373  </syntax>
374  <description>
375  <para>Simulate an on-hook event by the user connected to the channel.</para>
376  <note><para>Valid only for analog channels.</para></note>
377  </description>
378  </manager>
379  <manager name="DAHDIDialOffhook" language="en_US">
380  <synopsis>
381  Dial over DAHDI channel while offhook.
382  </synopsis>
383  <syntax>
384  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
385  <parameter name="DAHDIChannel" required="true">
386  <para>DAHDI channel number to dial digits.</para>
387  </parameter>
388  <parameter name="Number" required="true">
389  <para>Digits to dial.</para>
390  </parameter>
391  </syntax>
392  <description>
393  <para>Generate DTMF control frames to the bridged peer.</para>
394  </description>
395  </manager>
396  <manager name="DAHDIDNDon" language="en_US">
397  <synopsis>
398  Toggle DAHDI channel Do Not Disturb status ON.
399  </synopsis>
400  <syntax>
401  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
402  <parameter name="DAHDIChannel" required="true">
403  <para>DAHDI channel number to set DND on.</para>
404  </parameter>
405  </syntax>
406  <description>
407  <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> on".</para>
408  <note><para>Feature only supported by analog channels.</para></note>
409  </description>
410  </manager>
411  <manager name="DAHDIDNDoff" language="en_US">
412  <synopsis>
413  Toggle DAHDI channel Do Not Disturb status OFF.
414  </synopsis>
415  <syntax>
416  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
417  <parameter name="DAHDIChannel" required="true">
418  <para>DAHDI channel number to set DND off.</para>
419  </parameter>
420  </syntax>
421  <description>
422  <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> off".</para>
423  <note><para>Feature only supported by analog channels.</para></note>
424  </description>
425  </manager>
426  <manager name="DAHDIShowChannels" language="en_US">
427  <synopsis>
428  Show status of DAHDI channels.
429  </synopsis>
430  <syntax>
431  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
432  <parameter name="DAHDIChannel">
433  <para>Specify the specific channel number to show. Show all channels if zero or not present.</para>
434  </parameter>
435  </syntax>
436  <description>
437  <para>Similar to the CLI command "dahdi show channels".</para>
438  </description>
439  </manager>
440  <manager name="DAHDIShowStatus" language="en_US">
441  <synopsis>
442  Show status of DAHDI spans.
443  </synopsis>
444  <syntax/>
445  <description>
446  <para>Similar to the CLI command "dahdi show status".</para>
447  </description>
448  </manager>
449  <manager name="DAHDIRestart" language="en_US">
450  <synopsis>
451  Fully Restart DAHDI channels (terminates calls).
452  </synopsis>
453  <syntax>
454  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
455  </syntax>
456  <description>
457  <para>Equivalent to the CLI command "dahdi restart".</para>
458  </description>
459  </manager>
460  <manager name="PRIShowSpans" language="en_US">
461  <synopsis>
462  Show status of PRI spans.
463  </synopsis>
464  <syntax>
465  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
466  <parameter name="Span">
467  <para>Specify the specific span to show. Show all spans if zero or not present.</para>
468  </parameter>
469  </syntax>
470  <description>
471  <para>Similar to the CLI command "pri show spans".</para>
472  </description>
473  </manager>
474  <manager name="PRIDebugSet" language="en_US">
475  <synopsis>
476  Set PRI debug levels for a span
477  </synopsis>
478  <syntax>
479  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
480  <parameter name="Span" required="true">
481  <para>Which span to affect.</para>
482  </parameter>
483  <parameter name="Level" required="true">
484  <para>What debug level to set. May be a numerical value or a text value from the list below</para>
485  <enumlist>
486  <enum name="off" />
487  <enum name="on" />
488  <enum name="hex" />
489  <enum name="intense" />
490  </enumlist>
491  </parameter>
492  </syntax>
493  <description>
494  <para>Equivalent to the CLI command "pri set debug &lt;level&gt; span &lt;span&gt;".</para>
495  </description>
496  </manager>
497  <manager name="PRIDebugFileSet" language="en_US">
498  <synopsis>
499  Set the file used for PRI debug message output
500  </synopsis>
501  <syntax>
502  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
503  <parameter name="File" required="true">
504  <para>Path of file to write debug output.</para>
505  </parameter>
506  </syntax>
507  <description>
508  <para>Equivalent to the CLI command "pri set debug file &lt;output-file&gt;"</para>
509  </description>
510  </manager>
511  <manager name="PRIDebugFileUnset" language="en_US">
512  <synopsis>
513  Disables file output for PRI debug messages
514  </synopsis>
515  <syntax>
516  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
517  </syntax>
518  </manager>
519  <managerEvent language="en_US" name="AlarmClear">
520  <managerEventInstance class="EVENT_FLAG_SYSTEM">
521  <synopsis>Raised when an alarm is cleared on a DAHDI channel.</synopsis>
522  <syntax>
523  <parameter name="DAHDIChannel">
524  <para>The DAHDI channel on which the alarm was cleared.</para>
525  <note><para>This is not an Asterisk channel identifier.</para></note>
526  </parameter>
527  </syntax>
528  </managerEventInstance>
529  </managerEvent>
530  <managerEvent language="en_US" name="SpanAlarmClear">
531  <managerEventInstance class="EVENT_FLAG_SYSTEM">
532  <synopsis>Raised when an alarm is cleared on a DAHDI span.</synopsis>
533  <syntax>
534  <parameter name="Span">
535  <para>The span on which the alarm was cleared.</para>
536  </parameter>
537  </syntax>
538  </managerEventInstance>
539  </managerEvent>
540  <managerEvent language="en_US" name="DNDState">
541  <managerEventInstance class="EVENT_FLAG_SYSTEM">
542  <synopsis>Raised when the Do Not Disturb state is changed on a DAHDI channel.</synopsis>
543  <syntax>
544  <parameter name="DAHDIChannel">
545  <para>The DAHDI channel on which DND status changed.</para>
546  <note><para>This is not an Asterisk channel identifier.</para></note>
547  </parameter>
548  <parameter name="Status">
549  <enumlist>
550  <enum name="enabled"/>
551  <enum name="disabled"/>
552  </enumlist>
553  </parameter>
554  </syntax>
555  </managerEventInstance>
556  </managerEvent>
557  <managerEvent language="en_US" name="Alarm">
558  <managerEventInstance class="EVENT_FLAG_SYSTEM">
559  <synopsis>Raised when an alarm is set on a DAHDI channel.</synopsis>
560  <syntax>
561  <parameter name="DAHDIChannel">
562  <para>The channel on which the alarm occurred.</para>
563  <note><para>This is not an Asterisk channel identifier.</para></note>
564  </parameter>
565  <parameter name="Alarm">
566  <para>A textual description of the alarm that occurred.</para>
567  </parameter>
568  </syntax>
569  </managerEventInstance>
570  </managerEvent>
571  <managerEvent language="en_US" name="SpanAlarm">
572  <managerEventInstance class="EVENT_FLAG_SYSTEM">
573  <synopsis>Raised when an alarm is set on a DAHDI span.</synopsis>
574  <syntax>
575  <parameter name="Span">
576  <para>The span on which the alarm occurred.</para>
577  </parameter>
578  <parameter name="Alarm">
579  <para>A textual description of the alarm that occurred.</para>
580  </parameter>
581  </syntax>
582  </managerEventInstance>
583  </managerEvent>
584  <managerEvent language="en_US" name="DAHDIChannel">
585  <managerEventInstance class="EVENT_FLAG_CALL">
586  <synopsis>Raised when a DAHDI channel is created or an underlying technology is associated with a DAHDI channel.</synopsis>
587  <syntax>
588  <channel_snapshot/>
589  <parameter name="DAHDIGroup">
590  <para>The DAHDI logical group associated with this channel.</para>
591  </parameter>
592  <parameter name="DAHDISpan">
593  <para>The DAHDI span associated with this channel.</para>
594  </parameter>
595  <parameter name="DAHDIChannel">
596  <para>The DAHDI channel associated with this channel.</para>
597  </parameter>
598  </syntax>
599  </managerEventInstance>
600  </managerEvent>
601  ***/
602 
603 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
604 
605 static const char * const lbostr[] = {
606 "0 db (CSU)/0-133 feet (DSX-1)",
607 "133-266 feet (DSX-1)",
608 "266-399 feet (DSX-1)",
609 "399-533 feet (DSX-1)",
610 "533-655 feet (DSX-1)",
611 "-7.5db (CSU)",
612 "-15db (CSU)",
613 "-22.5db (CSU)"
614 };
615 
616 /*! Global jitterbuffer configuration - by default, jb is disabled
617  * \note Values shown here match the defaults shown in chan_dahdi.conf.sample */
619 {
620  .flags = 0,
621  .max_size = 200,
622  .resync_threshold = 1000,
623  .impl = "fixed",
624  .target_extra = 40,
625 };
626 static struct ast_jb_conf global_jbconf;
627 
628 /*!
629  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
630  * the user hangs up to reset the state machine so ring works properly.
631  * This is used to be able to support kewlstart by putting the zhone in
632  * groundstart mode since their forward disconnect supervision is entirely
633  * broken even though their documentation says it isn't and their support
634  * is entirely unwilling to provide any assistance with their channel banks
635  * even though their web site says they support their products for life.
636  */
637 /* #define ZHONE_HACK */
638 
639 /*! \brief Typically, how many rings before we should send Caller*ID */
640 #define DEFAULT_CIDRINGS 1
641 
642 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? ast_format_alaw : ast_format_ulaw)
643 
644 
645 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
646 #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))
647 
648 static const char tdesc[] = "DAHDI Telephony"
649 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
650  " w/"
651  #if defined(HAVE_PRI)
652  "PRI"
653  #endif /* defined(HAVE_PRI) */
654  #if defined(HAVE_SS7)
655  #if defined(HAVE_PRI)
656  " & "
657  #endif /* defined(HAVE_PRI) */
658  "SS7"
659  #endif /* defined(HAVE_SS7) */
660  #if defined(HAVE_OPENR2)
661  #if defined(HAVE_PRI) || defined(HAVE_SS7)
662  " & "
663  #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
664  "MFC/R2"
665  #endif /* defined(HAVE_OPENR2) */
666 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2) */
667 ;
668 
669 static const char config[] = "chan_dahdi.conf";
670 
671 #ifdef LOTS_OF_SPANS
672 #define NUM_SPANS DAHDI_MAX_SPANS
673 #else
674 #define NUM_SPANS 32
675 #endif
676 
677 #define CHAN_PSEUDO -2
678 
679 #define CALLPROGRESS_PROGRESS 1
680 #define CALLPROGRESS_FAX_OUTGOING 2
681 #define CALLPROGRESS_FAX_INCOMING 4
682 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
683 
684 #define NUM_CADENCE_MAX 25
685 static int num_cadence = 4;
686 static int user_has_defined_cadences = 0;
687 
688 static int has_pseudo;
689 
690 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
691  { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
692  { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
693  { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
694  { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
695 };
696 
697 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
698  * is 1, the second pause is 2 and so on.
699  */
700 
701 static int cidrings[NUM_CADENCE_MAX] = {
702  2, /*!< Right after first long ring */
703  4, /*!< Right after long part */
704  3, /*!< After third chirp */
705  2, /*!< Second spell */
706 };
707 
708 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
709 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
710 
711 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
712  (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
713 
714 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
715 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
716 
717 static char defaultcic[64] = "";
718 static char defaultozz[64] = "";
719 
720 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
721 static char mwimonitornotify[PATH_MAX] = "";
722 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
723 static int mwisend_rpas = 0;
724 #endif
725 
726 static char progzone[10] = "";
727 
728 static int usedistinctiveringdetection = 0;
729 static int distinctiveringaftercid = 0;
730 
731 static int numbufs = 4;
732 
733 static int mwilevel = 512;
734 static int dtmfcid_level = 256;
735 
736 #define REPORT_CHANNEL_ALARMS 1
737 #define REPORT_SPAN_ALARMS 2
738 static int report_alarms = REPORT_CHANNEL_ALARMS;
739 
740 #ifdef HAVE_PRI
741 static int pridebugfd = -1;
742 static char pridebugfilename[1024] = "";
743 #endif
744 
745 /*! \brief Protect the interface list (of dahdi_pvt's) */
746 AST_MUTEX_DEFINE_STATIC(iflock);
747 
748 
749 static int ifcount = 0;
750 
751 #ifdef HAVE_PRI
752 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
753 #endif
754 
755 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
756  when it's doing something critical. */
757 AST_MUTEX_DEFINE_STATIC(monlock);
758 
759 /*! \brief This is the thread for the monitor which checks for input on the channels
760  which are not currently in use. */
761 static pthread_t monitor_thread = AST_PTHREADT_NULL;
762 static ast_cond_t ss_thread_complete;
763 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
764 AST_MUTEX_DEFINE_STATIC(restart_lock);
765 static int ss_thread_count = 0;
766 static int num_restart_pending = 0;
767 
768 static int restart_monitor(void);
769 
770 static int dahdi_sendtext(struct ast_channel *c, const char *text);
771 
772 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
773 static inline int dahdi_get_event(int fd)
774 {
775  int j;
776  if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
777  return -1;
778  return j;
779 }
780 
781 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
782 static inline int dahdi_wait_event(int fd)
783 {
784  int i, j = 0;
785  i = DAHDI_IOMUX_SIGEVENT;
786  if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
787  return -1;
788  if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
789  return -1;
790  return j;
791 }
792 
793 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
794 #define READ_SIZE 160
795 
796 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
797 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
798 
799 #define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE) /*!< 300 ms */
800 #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
801 #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE) /*!< 100 ms */
802 #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE) /*!< 500 ms */
803 #define MIN_MS_SINCE_FLASH ((2000) ) /*!< 2000 ms */
804 #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE) /*!< 8,000 ms */
805 #define DEFAULT_DIALTONE_DETECT_TIMEOUT ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
806 
807 /*!
808  * \brief Configured ring timeout base.
809  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
810  */
812 
813 #if defined(HAVE_SS7)
814 
815 struct dahdi_ss7 {
816  struct sig_ss7_linkset ss7;
817 };
818 
819 static struct dahdi_ss7 linksets[NUM_SPANS];
820 
821 static int cur_ss7type = -1;
822 static int cur_slc = -1;
823 static int cur_linkset = -1;
824 static int cur_pointcode = -1;
825 static int cur_cicbeginswith = -1;
826 static int cur_adjpointcode = -1;
827 static int cur_networkindicator = -1;
828 static int cur_defaultdpc = -1;
829 #endif /* defined(HAVE_SS7) */
830 
831 #ifdef HAVE_OPENR2
832 struct dahdi_mfcr2_conf {
833  openr2_variant_t variant;
834  int mfback_timeout;
835  int metering_pulse_timeout;
836  int max_ani;
837  int max_dnis;
838 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
839  int dtmf_time_on;
840  int dtmf_time_off;
841 #endif
842 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
843  int dtmf_end_timeout;
844 #endif
845  signed int get_ani_first:2;
846 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
847  signed int skip_category_request:2;
848 #endif
849  unsigned int call_files:1;
850  unsigned int allow_collect_calls:1;
851  unsigned int charge_calls:1;
852  unsigned int accept_on_offer:1;
853  unsigned int forced_release:1;
854  unsigned int double_answer:1;
855  signed int immediate_accept:2;
856 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
857  signed int dtmf_dialing:2;
858  signed int dtmf_detection:2;
859 #endif
860  char logdir[OR2_MAX_PATH];
861  char r2proto_file[OR2_MAX_PATH];
862  openr2_log_level_t loglevel;
863  openr2_calling_party_category_t category;
864 };
865 
866 /* MFC-R2 pseudo-link structure */
867 struct dahdi_mfcr2 {
868  int index; /*!< Unique index for CLI */
869  pthread_t r2master; /*!< Thread of master */
870  openr2_context_t *protocol_context; /*!< OpenR2 context handle */
871  struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS]; /*!< Member channel pvt structs */
872  int numchans; /*!< Number of channels in this R2 block */
873  int live_chans; /*!< Number of unremoved channels in this R2 block */
874  int nodev; /*!< Link disconnected? */
875  struct dahdi_mfcr2_conf conf; /*!< Configuration used to setup this pseudo-link */
876 };
877 
878 struct r2link_entry {
879  struct dahdi_mfcr2 mfcr2;
880  AST_LIST_ENTRY(r2link_entry) list;
881 };
882 static AST_LIST_HEAD_STATIC(r2links, r2link_entry);
883 static struct r2links nodev_r2links = AST_LIST_HEAD_INIT_VALUE;
884 
885 
886 /* how many r2links have been malloc'd */
887 static int r2links_count = 0;
888 
889 #endif /* HAVE_OPENR2 */
890 
891 #ifdef HAVE_PRI
892 
893 struct dahdi_pri {
894  int dchannels[SIG_PRI_NUM_DCHANS]; /*!< What channel are the dchannels on */
895  int mastertrunkgroup; /*!< What trunk group is our master */
896  int prilogicalspan; /*!< Logical span number within trunk group */
897  struct sig_pri_span pri;
898 };
899 
900 static struct dahdi_pri pris[NUM_SPANS];
901 
902 #if defined(HAVE_PRI_CCSS)
903 /*! DAHDI PRI CCSS agent and monitor type name. */
904 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
905 #endif /* defined(HAVE_PRI_CCSS) */
906 
907 #else
908 /*! Shut up the compiler */
909 struct dahdi_pri;
910 #endif
911 
912 /* Polarity states */
913 #define POLARITY_IDLE 0
914 #define POLARITY_REV 1
915 
916 const char * const subnames[] = {
917  "Real",
918  "Callwait",
919  "Threeway"
920 };
921 
922 static struct dahdi_pvt *iflist = NULL; /*!< Main interface list start */
923 static struct dahdi_pvt *ifend = NULL; /*!< Main interface list end */
924 
925 #if defined(HAVE_PRI)
926 struct doomed_pri {
927  struct sig_pri_span *pri;
929 };
931 
932 static void pri_destroy_span(struct sig_pri_span *pri);
933 
934 static struct dahdi_parms_pseudo {
935  int buf_no; /*!< Number of buffers */
936  int buf_policy; /*!< Buffer policy */
937  int faxbuf_no; /*!< Number of Fax buffers */
938  int faxbuf_policy; /*!< Fax buffer policy */
939 } dahdi_pseudo_parms;
940 #endif /* defined(HAVE_PRI) */
941 
942 /*! \brief Channel configuration from chan_dahdi.conf .
943  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
944  * Generally there is a field here for every possible configuration item.
945  *
946  * The state of fields is saved along the parsing and whenever a 'channel'
947  * statement is reached, the current dahdi_chan_conf is used to configure the
948  * channel (struct dahdi_pvt)
949  *
950  * \see dahdi_chan_init for the default values.
951  */
953  struct dahdi_pvt chan;
954 #ifdef HAVE_PRI
955  struct dahdi_pri pri;
956 #endif
957 
958 #if defined(HAVE_SS7)
959  struct dahdi_ss7 ss7;
960 #endif /* defined(HAVE_SS7) */
961 
962 #ifdef HAVE_OPENR2
963  struct dahdi_mfcr2_conf mfcr2;
964 #endif
965  struct dahdi_params timing;
966  int is_sig_auto; /*!< Use channel signalling from DAHDI? */
967  /*! Continue configuration even if a channel is not there. */
969 
970  /*!
971  * \brief The serial port to listen for SMDI data on
972  * \note Set from the "smdiport" string read in from chan_dahdi.conf
973  */
974  char smdi_port[SMDI_MAX_FILENAME_LEN];
975 
976  /*!
977  * \brief Don't create channels below this number
978  * \note by default is 0 (no limit)
979  */
981 
982  /*!
983  * \brief Don't create channels above this number (infinity by default)
984  * \note by default is 0 (special value that means "no limit").
985  */
987 };
988 
989 /*! returns a new dahdi_chan_conf with default values (by-value) */
991 {
992  /* recall that if a field is not included here it is initialized
993  * to 0 or equivalent
994  */
995  struct dahdi_chan_conf conf = {
996 #ifdef HAVE_PRI
997  .pri.pri = {
998  .nsf = PRI_NSF_NONE,
999  .switchtype = PRI_SWITCH_NI2,
1000  .dialplan = PRI_UNKNOWN + 1,
1001  .localdialplan = PRI_NATIONAL_ISDN + 1,
1002  .nodetype = PRI_CPE,
1003  .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
1004 
1005 #if defined(HAVE_PRI_CCSS)
1006  .cc_ptmp_recall_mode = 1,/* specificRecall */
1007  .cc_qsig_signaling_link_req = 1,/* retain */
1008  .cc_qsig_signaling_link_rsp = 1,/* retain */
1009 #endif /* defined(HAVE_PRI_CCSS) */
1010 
1011  .minunused = 2,
1012  .idleext = "",
1013  .idledial = "",
1014  .internationalprefix = "",
1015  .nationalprefix = "",
1016  .localprefix = "",
1017  .privateprefix = "",
1018  .unknownprefix = "",
1019  .colp_send = SIG_PRI_COLP_UPDATE,
1020  .resetinterval = -1,
1021  },
1022 #endif
1023 #if defined(HAVE_SS7)
1024  .ss7.ss7 = {
1025  .called_nai = SS7_NAI_NATIONAL,
1026  .calling_nai = SS7_NAI_NATIONAL,
1027  .internationalprefix = "",
1028  .nationalprefix = "",
1029  .subscriberprefix = "",
1030  .unknownprefix = "",
1031  .networkroutedprefix = ""
1032  },
1033 #endif /* defined(HAVE_SS7) */
1034 #ifdef HAVE_OPENR2
1035  .mfcr2 = {
1036  .variant = OR2_VAR_ITU,
1037  .mfback_timeout = -1,
1038  .metering_pulse_timeout = -1,
1039  .max_ani = 10,
1040  .max_dnis = 4,
1041  .get_ani_first = -1,
1042 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
1043  .skip_category_request = -1,
1044 #endif
1045  .call_files = 0,
1046  .allow_collect_calls = 0,
1047  .charge_calls = 1,
1048  .accept_on_offer = 1,
1049  .forced_release = 0,
1050  .double_answer = 0,
1051  .immediate_accept = -1,
1052 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
1053  .dtmf_dialing = -1,
1054  .dtmf_detection = -1,
1055  .dtmf_time_on = OR2_DEFAULT_DTMF_ON,
1056  .dtmf_time_off = OR2_DEFAULT_DTMF_OFF,
1057 #endif
1058 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
1059  .dtmf_end_timeout = -1,
1060 #endif
1061  .logdir = "",
1062  .r2proto_file = "",
1063  .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
1064  .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
1065  },
1066 #endif
1067  .chan = {
1068  .context = "default",
1069  .immediatering = 1,
1070  .cid_num = "",
1071  .cid_name = "",
1072  .cid_tag = "",
1073  .mohinterpret = "default",
1074  .mohsuggest = "",
1075  .parkinglot = "",
1076  .transfertobusy = 1,
1077  .dialmode = 0,
1078 
1079  .ani_info_digits = 2,
1080  .ani_wink_time = 1000,
1081  .ani_timeout = 10000,
1082 
1083  .cid_signalling = CID_SIG_BELL,
1084  .cid_start = CID_START_RING,
1085  .dahditrcallerid = 0,
1086  .use_callerid = 1,
1087  .sig = -1,
1088  .outsigmod = -1,
1089 
1090  .cid_rxgain = +5.0,
1091 
1092  .tonezone = -1,
1093 
1094  .echocancel.head.tap_length = 1,
1095 
1096  .busycount = 3,
1097 
1098  .accountcode = "",
1099 
1100  .mailbox = "",
1101 
1102 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
1103  .mwisend_fsk = 1,
1104 #endif
1105  .polarityonanswerdelay = 600,
1106 
1107  .sendcalleridafter = DEFAULT_CIDRINGS,
1108 
1109  .buf_policy = DAHDI_POLICY_IMMEDIATE,
1110  .buf_no = numbufs,
1111  .usefaxbuffers = 0,
1112  .cc_params = ast_cc_config_params_init(),
1113  .firstdigit_timeout = ANALOG_FIRST_DIGIT_TIMEOUT,
1114  .interdigit_timeout = ANALOG_INTER_DIGIT_TIMEOUT,
1115  .matchdigit_timeout = ANALOG_MATCH_DIGIT_TIMEOUT,
1116  },
1117  .timing = {
1118  .prewinktime = -1,
1119  .preflashtime = -1,
1120  .winktime = -1,
1121  .flashtime = -1,
1122  .starttime = -1,
1123  .rxwinktime = -1,
1124  .rxflashtime = -1,
1125  .debouncetime = -1
1126  },
1127  .is_sig_auto = 1,
1128  .ignore_failed_channels = 1,
1129  .smdi_port = "/dev/ttyS0",
1130  };
1131 
1132  return conf;
1133 }
1134 
1135 
1136 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap,
1137  const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor,
1138  const char *data, int *cause);
1139 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
1140 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
1141 static int dahdi_sendtext(struct ast_channel *c, const char *text);
1142 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout);
1143 static int dahdi_hangup(struct ast_channel *ast);
1144 static int dahdi_answer(struct ast_channel *ast);
1145 static struct ast_frame *dahdi_read(struct ast_channel *ast);
1146 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
1147 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
1148 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
1149 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
1150 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
1151 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
1152 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
1153 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
1154 static int dahdi_devicestate(const char *data);
1155 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
1156 
1157 static struct ast_channel_tech dahdi_tech = {
1158  .type = "DAHDI",
1159  .description = tdesc,
1160  .requester = dahdi_request,
1161  .send_digit_begin = dahdi_digit_begin,
1162  .send_digit_end = dahdi_digit_end,
1163  .send_text = dahdi_sendtext,
1164  .call = dahdi_call,
1165  .hangup = dahdi_hangup,
1166  .answer = dahdi_answer,
1167  .read = dahdi_read,
1168  .write = dahdi_write,
1169  .exception = dahdi_exception,
1170  .indicate = dahdi_indicate,
1171  .fixup = dahdi_fixup,
1172  .setoption = dahdi_setoption,
1173  .queryoption = dahdi_queryoption,
1174  .func_channel_read = dahdi_func_read,
1175  .func_channel_write = dahdi_func_write,
1176  .devicestate = dahdi_devicestate,
1177  .cc_callback = dahdi_cc_callback,
1178 };
1179 
1180 #define GET_CHANNEL(p) ((p)->channel)
1181 
1182 static enum analog_sigtype dahdisig_to_analogsig(int sig)
1183 {
1184  switch (sig) {
1185  case SIG_FXOLS:
1186  return ANALOG_SIG_FXOLS;
1187  case SIG_FXOGS:
1188  return ANALOG_SIG_FXOGS;
1189  case SIG_FXOKS:
1190  return ANALOG_SIG_FXOKS;
1191  case SIG_FXSLS:
1192  return ANALOG_SIG_FXSLS;
1193  case SIG_FXSGS:
1194  return ANALOG_SIG_FXSGS;
1195  case SIG_FXSKS:
1196  return ANALOG_SIG_FXSKS;
1197  case SIG_EMWINK:
1198  return ANALOG_SIG_EMWINK;
1199  case SIG_EM:
1200  return ANALOG_SIG_EM;
1201  case SIG_EM_E1:
1202  return ANALOG_SIG_EM_E1;
1203  case SIG_FEATD:
1204  return ANALOG_SIG_FEATD;
1205  case SIG_FEATDMF:
1206  return ANALOG_SIG_FEATDMF;
1207  case SIG_E911:
1208  return SIG_E911;
1209  case SIG_FGC_CAMA:
1210  return ANALOG_SIG_FGC_CAMA;
1211  case SIG_FGC_CAMAMF:
1212  return ANALOG_SIG_FGC_CAMAMF;
1213  case SIG_FEATB:
1214  return ANALOG_SIG_FEATB;
1215  case SIG_SFWINK:
1216  return ANALOG_SIG_SFWINK;
1217  case SIG_SF:
1218  return ANALOG_SIG_SF;
1219  case SIG_SF_FEATD:
1220  return ANALOG_SIG_SF_FEATD;
1221  case SIG_SF_FEATDMF:
1222  return ANALOG_SIG_SF_FEATDMF;
1223  case SIG_FEATDMF_TA:
1224  return ANALOG_SIG_FEATDMF_TA;
1225  case SIG_SF_FEATB:
1226  return ANALOG_SIG_FEATB;
1227  default:
1228  return -1;
1229  }
1230 }
1231 
1232 
1233 static int analog_tone_to_dahditone(enum analog_tone tone)
1234 {
1235  switch (tone) {
1236  case ANALOG_TONE_RINGTONE:
1237  return DAHDI_TONE_RINGTONE;
1238  case ANALOG_TONE_STUTTER:
1239  return DAHDI_TONE_STUTTER;
1240  case ANALOG_TONE_CONGESTION:
1241  return DAHDI_TONE_CONGESTION;
1242  case ANALOG_TONE_DIALTONE:
1243  return DAHDI_TONE_DIALTONE;
1244  case ANALOG_TONE_DIALRECALL:
1245  return DAHDI_TONE_DIALRECALL;
1246  case ANALOG_TONE_INFO:
1247  return DAHDI_TONE_INFO;
1248  default:
1249  return -1;
1250  }
1251 }
1252 
1253 static int analogsub_to_dahdisub(enum analog_sub analogsub)
1254 {
1255  int index;
1256 
1257  switch (analogsub) {
1258  case ANALOG_SUB_REAL:
1259  index = SUB_REAL;
1260  break;
1261  case ANALOG_SUB_CALLWAIT:
1262  index = SUB_CALLWAIT;
1263  break;
1264  case ANALOG_SUB_THREEWAY:
1265  index = SUB_THREEWAY;
1266  break;
1267  default:
1268  ast_log(LOG_ERROR, "Unidentified sub!\n");
1269  index = SUB_REAL;
1270  }
1271 
1272  return index;
1273 }
1274 
1275 /*!
1276  * \internal
1277  * \brief release all members on the doomed pris list
1278  * \since 13.0
1279  *
1280  * Called priodically by the monitor threads to release spans marked for
1281  * removal.
1282  */
1283 static void release_doomed_pris(void)
1284 {
1285 #ifdef HAVE_PRI
1286  struct doomed_pri *entry;
1287 
1289  while ((entry = AST_LIST_REMOVE_HEAD(&doomed_pris, list))) {
1290  /* The span destruction must be done with this lock not held */
1292  ast_debug(4, "Destroying span %d from doomed queue.\n",
1293  entry->pri->span);
1294  pri_destroy_span(entry->pri);
1295  ast_free(entry);
1297  }
1299 #endif
1300 }
1301 
1302 #ifdef HAVE_PRI
1303 /*!
1304  * \brief Queue a span for destruction
1305  * \since 13.0
1306  *
1307  * \param pri the span to destroy
1308  *
1309  * Add a span to the list of spans to be destroyed later on
1310  * by the monitor thread. Allows destroying a span while holding its
1311  * lock.
1312  */
1313 static void pri_queue_for_destruction(struct sig_pri_span *pri)
1314 {
1315  struct doomed_pri *entry;
1316 
1318  AST_LIST_TRAVERSE(&doomed_pris, entry, list) {
1319  if (entry->pri == pri) {
1321  return;
1322  }
1323  }
1324  entry = ast_calloc(sizeof(struct doomed_pri), 1);
1325  if (!entry) {
1326  /* Nothing useful to do here. Panic? */
1327  ast_log(LOG_WARNING, "Failed allocating memory for a doomed_pri.\n");
1329  return;
1330  }
1331  entry->pri = pri;
1332  ast_debug(4, "Queue span %d for destruction.\n", pri->span);
1333  AST_LIST_INSERT_TAIL(&doomed_pris, entry, list);
1335 }
1336 #endif
1337 
1338 /*!
1339  * \internal
1340  * \brief Send a dial string to DAHDI.
1341  * \since 12.0.0
1342  *
1343  * \param pvt DAHDI private pointer
1344  * \param operation DAHDI dial operation to do to string
1345  * \param dial_str Dial string to send
1346  *
1347  * \retval 0 on success.
1348  * \retval non-zero on error.
1349  */
1350 static int dahdi_dial_str(struct dahdi_pvt *pvt, int operation, const char *dial_str)
1351 {
1352  int res;
1353  int offset;
1354  const char *pos;
1355  struct dahdi_dialoperation zo = {
1356  .op = operation,
1357  };
1358 
1359  /* Convert the W's to ww. */
1360  pos = dial_str;
1361  for (offset = 0; offset < sizeof(zo.dialstr) - 1; ++offset) {
1362  if (!*pos) {
1363  break;
1364  }
1365  if (*pos == 'W') {
1366  /* Convert 'W' to "ww" */
1367  ++pos;
1368  if (offset >= sizeof(zo.dialstr) - 3) {
1369  /* No room to expand */
1370  break;
1371  }
1372  zo.dialstr[offset] = 'w';
1373  ++offset;
1374  zo.dialstr[offset] = 'w';
1375  continue;
1376  }
1377  zo.dialstr[offset] = *pos++;
1378  }
1379  /* The zo initialization has already terminated the dialstr. */
1380 
1381  ast_debug(1, "Channel %d: Dial str '%s' expanded to '%s' sent to DAHDI_DIAL.\n",
1382  pvt->channel, dial_str, zo.dialstr);
1383  res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
1384  if (res) {
1385  ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
1386  pvt->channel, dial_str, strerror(errno));
1387  }
1388 
1389  return res;
1390 }
1391 
1392 static enum analog_event dahdievent_to_analogevent(int event);
1393 static int bump_gains(struct dahdi_pvt *p);
1394 static int dahdi_setlinear(int dfd, int linear);
1395 
1396 static int my_start_cid_detect(void *pvt, int cid_signalling)
1397 {
1398  struct dahdi_pvt *p = pvt;
1399  int index = SUB_REAL;
1400  p->cs = callerid_new(cid_signalling);
1401  if (!p->cs) {
1402  ast_log(LOG_ERROR, "Unable to alloc callerid\n");
1403  return -1;
1404  }
1405  bump_gains(p);
1406  dahdi_setlinear(p->subs[index].dfd, 0);
1407 
1408  return 0;
1409 }
1410 
1411 static int restore_gains(struct dahdi_pvt *p);
1412 
1413 static int my_stop_cid_detect(void *pvt)
1414 {
1415  struct dahdi_pvt *p = pvt;
1416  int index = SUB_REAL;
1417 
1418  if (p->cs) {
1419  callerid_free(p->cs);
1420  }
1421 
1422  /* Restore linear mode after Caller*ID processing */
1423  dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
1424  restore_gains(p);
1425 
1426  return 0;
1427 }
1428 
1429 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
1430 {
1431  struct dahdi_pvt *p = pvt;
1432  struct analog_pvt *analog_p = p->sig_pvt;
1433  struct pollfd poller;
1434  char *name, *num;
1435  int index = SUB_REAL;
1436  int res;
1437  unsigned char buf[256];
1438  int flags;
1439  int redirecting;
1440 
1441  poller.fd = p->subs[SUB_REAL].dfd;
1442  poller.events = POLLPRI | POLLIN;
1443  poller.revents = 0;
1444 
1445  res = poll(&poller, 1, timeout);
1446 
1447  if (poller.revents & POLLPRI) {
1448  *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
1449  return 1;
1450  }
1451 
1452  if (poller.revents & POLLIN) {
1453  /*** NOTES ***/
1454  /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
1455  * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
1456  * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
1457  * a failure and die, and returning 2 means no event was received. */
1458  res = read(p->subs[index].dfd, buf, sizeof(buf));
1459  if (res < 0) {
1460  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
1461  return -1;
1462  }
1463 
1464  if (analog_p->ringt > 0) {
1465  if (!(--analog_p->ringt)) {
1466  /* only return if we timeout from a ring event */
1467  return -1;
1468  }
1469  }
1470 
1471  if (p->cid_signalling == CID_SIG_V23_JP) {
1472  res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
1473  } else {
1474  res = callerid_feed(p->cs, buf, res, AST_LAW(p));
1475  }
1476  if (res < 0) {
1477  /*
1478  * The previous diagnostic message output likely
1479  * explains why it failed.
1480  */
1481  ast_log(LOG_WARNING, "Failed to decode CallerID\n");
1482  return -1;
1483  }
1484 
1485  if (res == 1) {
1486  struct ast_channel *chan = analog_p->ss_astchan;
1487  callerid_get_with_redirecting(p->cs, &name, &num, &flags, &redirecting);
1488  if (name)
1489  ast_copy_string(namebuf, name, ANALOG_MAX_CID);
1490  if (num)
1491  ast_copy_string(numbuf, num, ANALOG_MAX_CID);
1492 
1493  if (flags & (CID_PRIVATE_NUMBER | CID_UNKNOWN_NUMBER)) {
1494  /* If we got a presentation, we must set it on the channel */
1495  struct ast_party_caller caller;
1496 
1497  ast_party_caller_set_init(&caller, ast_channel_caller(chan));
1498  caller.id.name.presentation = caller.id.number.presentation = (flags & CID_PRIVATE_NUMBER) ?
1499  AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED : AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_UNSCREENED;
1500  ast_party_caller_set(ast_channel_caller(chan), &caller, NULL);
1501  ast_party_caller_free(&caller);
1502  }
1503  if (redirecting) {
1504  /* There is a redirecting reason available in the Caller*ID received.
1505  * No idea what the redirecting number is, since the Caller*ID protocol
1506  * has no parameter for that, but at least we know WHY it was redirected. */
1507  ast_channel_redirecting(chan)->reason.code = redirecting;
1508  }
1509 
1510  if (flags & CID_QUALIFIER) {
1511  /* This is the inverse of how the qualifier is set in sig_analog */
1512  pbx_builtin_setvar_helper(chan, "CALL_QUALIFIER", "1");
1513  }
1514 
1515  ast_debug(1, "CallerID number: %s, name: %s, flags=%d, redirecting=%s\n", num, name, flags, ast_redirecting_reason_name(&ast_channel_redirecting(chan)->reason));
1516  return 0;
1517  }
1518  }
1519 
1520  *ev = ANALOG_EVENT_NONE;
1521  return 2;
1522 }
1523 
1524 static const char *event2str(int event);
1525 
1526 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
1527 {
1528  unsigned char buf[256];
1529  int distMatches;
1530  int curRingData[RING_PATTERNS];
1531  int receivedRingT;
1532  int counter1;
1533  int counter;
1534  int i;
1535  int res;
1536  int checkaftercid = 0;
1537  const char *matched_context;
1538  struct dahdi_pvt *p = pvt;
1539  struct analog_pvt *analog_p = p->sig_pvt;
1540 
1541  if (ringdata == NULL) {
1542  ringdata = curRingData;
1543  } else {
1544  checkaftercid = 1;
1545  }
1546 
1547  /* We must have a ring by now so lets try to listen for distinctive ringing */
1548  if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
1549  /* Clear the current ring data array so we don't have old data in it. */
1550  for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
1551  ringdata[receivedRingT] = 0;
1552  receivedRingT = 0;
1553 
1554  if (checkaftercid && distinctiveringaftercid) {
1555  ast_verb(3, "Detecting post-CID distinctive ring\n");
1556  }
1557 
1558  for (;;) {
1559  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
1560  res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i);
1561  if (res) {
1562  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
1563  ast_hangup(chan);
1564  return 1;
1565  }
1566  if (i & DAHDI_IOMUX_SIGEVENT) {
1567  res = dahdi_get_event(p->subs[idx].dfd);
1568  ast_debug(3, "Got event %d (%s)...\n", res, event2str(res));
1569  if (res == DAHDI_EVENT_NOALARM) {
1570  p->inalarm = 0;
1571  analog_p->inalarm = 0;
1572  } else if (res == DAHDI_EVENT_RINGOFFHOOK) {
1573  /* Let us detect distinctive ring */
1574  ringdata[receivedRingT] = analog_p->ringt;
1575 
1576  if (analog_p->ringt < analog_p->ringt_base / 2) {
1577  break;
1578  }
1579  /* Increment the ringT counter so we can match it against
1580  values in chan_dahdi.conf for distinctive ring */
1581  if (++receivedRingT == RING_PATTERNS) {
1582  break;
1583  }
1584  }
1585  } else if (i & DAHDI_IOMUX_READ) {
1586  res = read(p->subs[idx].dfd, buf, sizeof(buf));
1587  if (res < 0) {
1588  if (errno != ELAST) {
1589  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
1590  ast_hangup(chan);
1591  return 1;
1592  }
1593  break;
1594  }
1595  if (analog_p->ringt > 0) {
1596  if (!(--analog_p->ringt)) {
1597  break;
1598  }
1599  }
1600  }
1601  }
1602  }
1603 
1604  /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
1605  ast_verb(3, "Detected ring pattern: %d,%d,%d\n", ringdata[0], ringdata[1], ringdata[2]);
1606  matched_context = p->defcontext;
1607  for (counter = 0; counter < 3; counter++) {
1608  int range = p->drings.ringnum[counter].range;
1609 
1610  distMatches = 0;
1611  ast_verb(3, "Checking %d,%d,%d with +/- %d range\n",
1612  p->drings.ringnum[counter].ring[0],
1613  p->drings.ringnum[counter].ring[1],
1614  p->drings.ringnum[counter].ring[2],
1615  range);
1616  for (counter1 = 0; counter1 < 3; counter1++) {
1617  int ring = p->drings.ringnum[counter].ring[counter1];
1618 
1619  if (ring == -1) {
1620  ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
1621  ringdata[counter1]);
1622  distMatches++;
1623  } else if (ring - range <= ringdata[counter1] && ringdata[counter1] <= ring + range) {
1624  ast_verb(3, "Ring pattern %d is in range: %d to %d\n",
1625  ringdata[counter1], ring - range, ring + range);
1626  distMatches++;
1627  } else {
1628  /* The current dring pattern cannot match. */
1629  break;
1630  }
1631  }
1632 
1633  if (distMatches == 3) {
1634  /* The ring matches, set the context to whatever is for distinctive ring.. */
1635  matched_context = S_OR(p->drings.ringContext[counter].contextData, p->defcontext);
1636  ast_verb(3, "Matched Distinctive Ring context %s\n", matched_context);
1637  break;
1638  }
1639  }
1640 
1641  /* Set selected distinctive ring context if not already set. */
1642  if (strcmp(p->context, matched_context) != 0) {
1643  ast_copy_string(p->context, matched_context, sizeof(p->context));
1644  ast_channel_context_set(chan, matched_context);
1645  }
1646 
1647  return 0;
1648 }
1649 
1650 static int my_stop_callwait(void *pvt)
1651 {
1652  struct dahdi_pvt *p = pvt;
1653  p->callwaitingrepeat = 0;
1654  p->cidcwexpire = 0;
1655  p->cid_suppress_expire = 0;
1656 
1657  return 0;
1658 }
1659 
1660 static int send_callerid(struct dahdi_pvt *p);
1661 static int save_conference(struct dahdi_pvt *p);
1662 static int restore_conference(struct dahdi_pvt *p);
1663 
1664 static int my_callwait(void *pvt)
1665 {
1666  struct dahdi_pvt *p = pvt;
1667 
1669  if (p->cidspill) {
1670  ast_log(LOG_WARNING, "Spill already exists?!?\n");
1671  ast_free(p->cidspill);
1672  }
1673 
1674  /*
1675  * SAS: Subscriber Alert Signal, 440Hz for 300ms
1676  * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
1677  */
1678  if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
1679  return -1;
1680  save_conference(p);
1681  /* Silence */
1682  memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
1683  if (!p->callwaitrings && p->callwaitingcallerid) {
1684  ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
1685  p->callwaitcas = 1;
1686  p->cidlen = 2400 + 680 + READ_SIZE * 4;
1687  } else {
1688  ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
1689  p->callwaitcas = 0;
1690  p->cidlen = 2400 + READ_SIZE * 4;
1691  }
1692  p->cidpos = 0;
1693  send_callerid(p);
1694 
1695  return 0;
1696 }
1697 
1698 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
1699 {
1700  struct dahdi_pvt *p = pvt;
1701  struct analog_pvt *analog_p = p->sig_pvt;
1702 
1703  ast_debug(2, "Starting cid spill\n");
1704 
1705  if (p->cidspill) {
1706  ast_log(LOG_WARNING, "cidspill already exists??\n");
1707  ast_free(p->cidspill);
1708  }
1709 
1710  if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
1711  int pres = ast_party_id_presentation(&caller->id);
1712  if (cwcid == 0) {
1713  /* Some CPE support additional parameters for on-hook Caller*ID,
1714  * such as redirecting reason and call qualifier, so send those
1715  * if available.
1716  * I don't know of any CPE that supports this for Call Waiting (unfortunately),
1717  * so don't send those for call waiting as that will just lengthen the CID spill
1718  * for no good reason.
1719  */
1721  caller->id.name.str,
1722  caller->id.number.str,
1723  NULL,
1724  analog_p->redirecting_reason,
1725  pres,
1726  analog_p->call_qualifier,
1727  CID_TYPE_MDMF,
1728  AST_LAW(p));
1729  } else {
1730  ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
1731  caller->id.name.str, caller->id.number.str);
1732  p->callwaitcas = 0;
1733  p->cidcwexpire = 0;
1735  caller->id.name.str,
1736  caller->id.number.str,
1737  NULL,
1738  -1,
1739  pres,
1740  0,
1741  AST_LAW(p));
1742  p->cidlen += READ_SIZE * 4;
1743  }
1744  p->cidpos = 0;
1745  p->cid_suppress_expire = 0;
1746  send_callerid(p);
1747  }
1748  return 0;
1749 }
1750 
1751 static int my_dsp_reset_and_flush_digits(void *pvt)
1752 {
1753  struct dahdi_pvt *p = pvt;
1754  if (p->dsp)
1755  ast_dsp_digitreset(p->dsp);
1756 
1757  return 0;
1758 }
1759 
1760 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
1761 {
1762  struct dahdi_pvt *p = pvt;
1763 
1764  if (p->channel == CHAN_PSEUDO)
1765  ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
1766 
1767  if (mode == ANALOG_DIGITMODE_DTMF) {
1768  /* If we do hardware dtmf, no need for a DSP */
1769  if (p->hardwaredtmf) {
1770  if (p->dsp) {
1771  ast_dsp_free(p->dsp);
1772  p->dsp = NULL;
1773  }
1774  return 0;
1775  }
1776 
1777  if (!p->dsp) {
1778  p->dsp = ast_dsp_new();
1779  if (!p->dsp) {
1780  ast_log(LOG_ERROR, "Unable to allocate DSP\n");
1781  return -1;
1782  }
1783  }
1784 
1786  } else if (mode == ANALOG_DIGITMODE_MF) {
1787  if (!p->dsp) {
1788  p->dsp = ast_dsp_new();
1789  if (!p->dsp) {
1790  ast_log(LOG_ERROR, "Unable to allocate DSP\n");
1791  return -1;
1792  }
1793  }
1795  }
1796  return 0;
1797 }
1798 
1799 static int dahdi_wink(struct dahdi_pvt *p, int index);
1800 
1801 static int my_wink(void *pvt, enum analog_sub sub)
1802 {
1803  struct dahdi_pvt *p = pvt;
1804  int index = analogsub_to_dahdisub(sub);
1805  if (index != SUB_REAL) {
1806  ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
1807  }
1808  return dahdi_wink(p, index);
1809 }
1810 
1811 static void wakeup_sub(struct dahdi_pvt *p, int a);
1812 
1813 static int reset_conf(struct dahdi_pvt *p);
1814 
1815 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
1816 
1817 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
1818 {
1819  struct ast_frame *f = *dest;
1820  struct dahdi_pvt *p = pvt;
1821  int idx = analogsub_to_dahdisub(analog_index);
1822 
1823  ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
1824  f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
1825  (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
1826 
1827  if (f->subclass.integer == 'f') {
1828  if (f->frametype == AST_FRAME_DTMF_END) {
1829  /* Fax tone -- Handle and return NULL */
1830  if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
1831  /* If faxbuffers are configured, use them for the fax transmission */
1832  if (p->usefaxbuffers && !p->bufferoverrideinuse) {
1833  struct dahdi_bufferinfo bi = {
1834  .txbufpolicy = p->faxbuf_policy,
1835  .bufsize = p->bufsize,
1836  .numbufs = p->faxbuf_no
1837  };
1838  int res;
1839 
1840  if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
1841  ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
1842  } else {
1843  p->bufferoverrideinuse = 1;
1844  }
1845  }
1846  p->faxhandled = 1;
1847  if (p->dsp) {
1848  p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
1850  ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
1851  }
1852  if (strcmp(ast_channel_exten(ast), "fax")) {
1853  const char *target_context = ast_channel_context(ast);
1854 
1855  /*
1856  * We need to unlock 'ast' here because ast_exists_extension has the
1857  * potential to start autoservice on the channel. Such action is prone
1858  * to deadlock if the channel is locked.
1859  *
1860  * ast_async_goto() has its own restriction on not holding the
1861  * channel lock.
1862  */
1863  ast_mutex_unlock(&p->lock);
1864  ast_channel_unlock(ast);
1865  if (ast_exists_extension(ast, target_context, "fax", 1,
1866  S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
1867  ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
1868  /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
1869  pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
1870  if (ast_async_goto(ast, target_context, "fax", 1))
1871  ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
1872  } else {
1873  ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
1874  }
1875  ast_channel_lock(ast);
1876  ast_mutex_lock(&p->lock);
1877  } else {
1878  ast_debug(1, "Already in a fax extension, not redirecting\n");
1879  }
1880  } else {
1881  ast_debug(1, "Fax already handled\n");
1882  }
1883  dahdi_confmute(p, 0);
1884  }
1885  p->subs[idx].f.frametype = AST_FRAME_NULL;
1886  p->subs[idx].f.subclass.integer = 0;
1887  *dest = &p->subs[idx].f;
1888  }
1889 }
1890 
1891 static void my_lock_private(void *pvt)
1892 {
1893  struct dahdi_pvt *p = pvt;
1894  ast_mutex_lock(&p->lock);
1895 }
1896 
1897 static void my_unlock_private(void *pvt)
1898 {
1899  struct dahdi_pvt *p = pvt;
1900  ast_mutex_unlock(&p->lock);
1901 }
1902 
1903 static void my_deadlock_avoidance_private(void *pvt)
1904 {
1905  struct dahdi_pvt *p = pvt;
1906 
1907  DEADLOCK_AVOIDANCE(&p->lock);
1908 }
1909 
1910 static struct ast_manager_event_blob *dahdichannel_to_ami(struct stasis_message *msg)
1911 {
1912  RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
1913  struct ast_channel_blob *obj = stasis_message_data(msg);
1914  struct ast_json *group, *span, *channel;
1915 
1916  channel_string = ast_manager_build_channel_state_string(obj->snapshot);
1917  if (!channel_string) {
1918  return NULL;
1919  }
1920 
1921  group = ast_json_object_get(obj->blob, "group");
1922  span = ast_json_object_get(obj->blob, "span");
1923  channel = ast_json_object_get(obj->blob, "channel");
1924 
1925  return ast_manager_event_blob_create(EVENT_FLAG_CALL, "DAHDIChannel",
1926  "%s"
1927  "DAHDIGroup: %llu\r\n"
1928  "DAHDISpan: %u\r\n"
1929  "DAHDIChannel: %s\r\n",
1930  ast_str_buffer(channel_string),
1931  (ast_group_t)ast_json_integer_get(group),
1932  (unsigned int)ast_json_integer_get(span),
1933  ast_json_string_get(channel));
1934 }
1935 
1936 STASIS_MESSAGE_TYPE_DEFN_LOCAL(dahdichannel_type,
1937  .to_ami = dahdichannel_to_ami,
1938  );
1939 
1940 /*! \brief Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages */
1941 static void publish_dahdichannel(struct ast_channel *chan, ast_group_t group, int span, const char *dahdi_channel)
1942 {
1943  RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
1944 
1945  ast_assert(dahdi_channel != NULL);
1946 
1947  blob = ast_json_pack("{s: I, s: i, s: s}",
1948  "group", (ast_json_int_t)group,
1949  "span", span,
1950  "channel", dahdi_channel);
1951  if (!blob) {
1952  return;
1953  }
1954 
1955  ast_channel_lock(chan);
1956  ast_channel_publish_blob(chan, dahdichannel_type(), blob);
1957  ast_channel_unlock(chan);
1958 }
1959 
1960 /*!
1961  * \internal
1962  * \brief Post an AMI DAHDI channel association event.
1963  * \since 1.8
1964  *
1965  * \param p DAHDI private pointer
1966  * \param chan Channel associated with the private pointer
1967  */
1968 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
1969 {
1970  char ch_name[23];
1971 
1972  if (p->channel < CHAN_PSEUDO) {
1973  /* No B channel */
1974  snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
1975  } else if (p->channel == CHAN_PSEUDO) {
1976  /* Pseudo channel */
1977  strcpy(ch_name, "pseudo");
1978  } else {
1979  /* Real channel */
1980  snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
1981  }
1982  publish_dahdichannel(chan, p->group, p->span, ch_name);
1983 }
1984 
1985 #ifdef HAVE_PRI
1986 /*!
1987  * \internal
1988  * \brief Post an AMI DAHDI channel association event.
1989  * \since 1.8
1990  *
1991  * \param pvt DAHDI private pointer
1992  * \param chan Channel associated with the private pointer
1993  */
1994 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
1995 {
1996  struct dahdi_pvt *p = pvt;
1997 
1998  dahdi_ami_channel_event(p, chan);
1999 }
2000 #endif
2001 
2002 /* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
2003 * returns the last value of the linear setting
2004 */
2005 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
2006 {
2007  struct dahdi_pvt *p = pvt;
2008  int oldval;
2009  int idx = analogsub_to_dahdisub(sub);
2010 
2011  dahdi_setlinear(p->subs[idx].dfd, linear_mode);
2012  oldval = p->subs[idx].linear;
2013  p->subs[idx].linear = linear_mode ? 1 : 0;
2014  return oldval;
2015 }
2016 
2017 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
2018 {
2019  struct dahdi_pvt *p = pvt;
2020  int idx = analogsub_to_dahdisub(sub);
2021 
2022  p->subs[idx].inthreeway = inthreeway;
2023 }
2024 
2025 static int get_alarms(struct dahdi_pvt *p);
2026 static void handle_alarms(struct dahdi_pvt *p, int alms);
2027 static void my_get_and_handle_alarms(void *pvt)
2028 {
2029  int res;
2030  struct dahdi_pvt *p = pvt;
2031 
2032  res = get_alarms(p);
2033  handle_alarms(p, res);
2034 }
2035 
2036 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
2037 {
2039 
2040  if (bridged && ast_channel_tech(bridged) == &dahdi_tech) {
2041  struct dahdi_pvt *p = ast_channel_tech_pvt(bridged);
2042 
2043  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
2044  return p->sig_pvt;
2045  }
2046  }
2047  return NULL;
2048 }
2049 
2050 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
2051 {
2052  struct dahdi_pvt *p = pvt;
2053  int dahdi_sub = analogsub_to_dahdisub(sub);
2054  return p->subs[dahdi_sub].dfd;
2055 }
2056 
2057 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
2058 {
2059  struct dahdi_pvt *p = pvt;
2060 
2061  /* Choose proper cadence */
2062  if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
2063  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
2064  ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast_channel_name(ast), strerror(errno));
2065  *cid_rings = cidrings[p->distinctivering - 1];
2066  } else {
2067  if (p->distinctivering > 0) {
2068  ast_log(LOG_WARNING, "Cadence %d is not defined, falling back to default ring cadence\n", p->distinctivering);
2069  }
2070  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
2071  ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast_channel_name(ast), strerror(errno));
2072  *cid_rings = p->sendcalleridafter;
2073  }
2074 }
2075 
2076 static void my_set_alarm(void *pvt, int in_alarm)
2077 {
2078  struct dahdi_pvt *p = pvt;
2079 
2080  p->inalarm = in_alarm;
2081 }
2082 
2083 static void my_set_dialing(void *pvt, int is_dialing)
2084 {
2085  struct dahdi_pvt *p = pvt;
2086 
2087  p->dialing = is_dialing;
2088 }
2089 
2090 static void my_set_outgoing(void *pvt, int is_outgoing)
2091 {
2092  struct dahdi_pvt *p = pvt;
2093 
2094  p->outgoing = is_outgoing;
2095 }
2096 
2097 #if defined(HAVE_PRI) || defined(HAVE_SS7)
2098 static void my_set_digital(void *pvt, int is_digital)
2099 {
2100  struct dahdi_pvt *p = pvt;
2101 
2102  p->digital = is_digital;
2103 }
2104 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
2105 
2106 #if defined(HAVE_SS7)
2107 static void my_set_inservice(void *pvt, int is_inservice)
2108 {
2109  struct dahdi_pvt *p = pvt;
2110 
2111  p->inservice = is_inservice;
2112 }
2113 #endif /* defined(HAVE_SS7) */
2114 
2115 #if defined(HAVE_SS7)
2116 static void my_set_locallyblocked(void *pvt, int is_blocked)
2117 {
2118  struct dahdi_pvt *p = pvt;
2119 
2120  p->locallyblocked = is_blocked;
2121 }
2122 #endif /* defined(HAVE_SS7) */
2123 
2124 #if defined(HAVE_SS7)
2125 static void my_set_remotelyblocked(void *pvt, int is_blocked)
2126 {
2127  struct dahdi_pvt *p = pvt;
2128 
2129  p->remotelyblocked = is_blocked;
2130 }
2131 #endif /* defined(HAVE_SS7) */
2132 
2133 static void my_set_ringtimeout(void *pvt, int ringt)
2134 {
2135  struct dahdi_pvt *p = pvt;
2136  p->ringt = ringt;
2137 }
2138 
2139 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
2140 {
2141  struct dahdi_pvt *p = pvt;
2142 
2143  /* We reset p->waitfordialtonetemp here, to prevent leaking to future calls,
2144  * but we also need to check against this value until we get dialtone
2145  * or the timer expires, since waitingfordt is when the timer started,
2146  * not when it should expire.
2147  *
2148  * Critically, we only set p->waitingfordt here if waitfordialtone or waitfordialtonetemp
2149  * has already been set, as waitingfordt is what is checked at runtime to determine
2150  * if we should be waiting for dial tone. This ensures that if a second call
2151  * is initiated concurrently, the first one "consumes" waitfordialtonetemp and resets it,
2152  * preventing leaking to other calls while remaining available to check on the first one while dialing.
2153  */
2155  p->waitfordialtonetemp = 0;
2156 
2157  if (!(p->waitfordialtoneduration && CANPROGRESSDETECT(p))) {
2158  return;
2159  }
2160 
2161  /* Because the DSP is allocated when the channel is created,
2162  * if we requested waitfordialtone later (in a predial handler),
2163  * we need to create it now */
2164  if (!p->dsp) {
2165  p->dsp = ast_dsp_new();
2166  if (!p->dsp) {
2167  ast_log(LOG_ERROR, "Unable to allocate DSP\n");
2168  return;
2169  }
2170  }
2173 
2174  ast_debug(1, "Defer dialing for %dms or dialtone\n", p->waitfordialtoneduration);
2175  gettimeofday(&p->waitingfordt, NULL);
2177 }
2178 
2179 static int my_check_waitingfordt(void *pvt)
2180 {
2181  struct dahdi_pvt *p = pvt;
2182 
2183  if (p->waitingfordt.tv_sec) {
2184  return 1;
2185  }
2186 
2187  return 0;
2188 }
2189 
2190 static void my_set_confirmanswer(void *pvt, int flag)
2191 {
2192  struct dahdi_pvt *p = pvt;
2193  p->confirmanswer = flag;
2194 }
2195 
2196 static int my_check_confirmanswer(void *pvt)
2197 {
2198  struct dahdi_pvt *p = pvt;
2199  if (p->confirmanswer) {
2200  return 1;
2201  }
2202 
2203  return 0;
2204 }
2205 
2206 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
2207 {
2208  struct dahdi_pvt *p = pvt;
2209 
2210  p->callwaiting = callwaiting_enable;
2211 }
2212 
2213 static void my_cancel_cidspill(void *pvt)
2214 {
2215  struct dahdi_pvt *p = pvt;
2216 
2217  ast_free(p->cidspill);
2218  p->cidspill = NULL;
2219  restore_conference(p);
2220 }
2221 
2222 static int my_confmute(void *pvt, int mute)
2223 {
2224  struct dahdi_pvt *p = pvt;
2225  return dahdi_confmute(p, mute);
2226 }
2227 
2228 static void my_set_pulsedial(void *pvt, int flag)
2229 {
2230  struct dahdi_pvt *p = pvt;
2231  p->pulsedial = flag;
2232 }
2233 
2234 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
2235 {
2236  struct dahdi_pvt *p = pvt;
2237 
2238  p->owner = new_owner;
2239 }
2240 
2241 static const char *my_get_orig_dialstring(void *pvt)
2242 {
2243  struct dahdi_pvt *p = pvt;
2244 
2245  return p->dialstring;
2246 }
2247 
2248 static void my_increase_ss_count(void)
2249 {
2250  ast_mutex_lock(&ss_thread_lock);
2251  ss_thread_count++;
2252  ast_mutex_unlock(&ss_thread_lock);
2253 }
2254 
2255 static void my_decrease_ss_count(void)
2256 {
2257  ast_mutex_lock(&ss_thread_lock);
2258  ss_thread_count--;
2259  ast_cond_signal(&ss_thread_complete);
2260  ast_mutex_unlock(&ss_thread_lock);
2261 }
2262 
2263 static void my_all_subchannels_hungup(void *pvt)
2264 {
2265  struct dahdi_pvt *p = pvt;
2266  int res, law;
2267 
2268  p->faxhandled = 0;
2269  p->didtdd = 0;
2270 
2271  if (p->dsp) {
2272  ast_dsp_free(p->dsp);
2273  p->dsp = NULL;
2274  }
2275 
2276  p->law = p->law_default;
2277  law = p->law_default;
2278  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
2279  if (res < 0)
2280  ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
2281 
2282  dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
2283 
2284 #if 1
2285  {
2286  int i;
2287  p->owner = NULL;
2288  /* Cleanup owners here */
2289  for (i = 0; i < 3; i++) {
2290  p->subs[i].owner = NULL;
2291  }
2292  }
2293 #endif
2294 
2295  reset_conf(p);
2296  if (num_restart_pending == 0) {
2297  restart_monitor();
2298  }
2299 }
2300 
2301 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
2302 
2303 static int my_conf_del(void *pvt, enum analog_sub sub)
2304 {
2305  struct dahdi_pvt *p = pvt;
2306  int x = analogsub_to_dahdisub(sub);
2307 
2308  return conf_del(p, &p->subs[x], x);
2309 }
2310 
2311 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
2312 
2313 static int my_conf_add(void *pvt, enum analog_sub sub)
2314 {
2315  struct dahdi_pvt *p = pvt;
2316  int x = analogsub_to_dahdisub(sub);
2317 
2318  return conf_add(p, &p->subs[x], x, 0);
2319 }
2320 
2321 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
2322 
2323 static int my_complete_conference_update(void *pvt, int needconference)
2324 {
2325  struct dahdi_pvt *p = pvt;
2326  int needconf = needconference;
2327  int x;
2328  int useslavenative;
2329  struct dahdi_pvt *slave = NULL;
2330 
2331  useslavenative = isslavenative(p, &slave);
2332 
2333  /* If we have a slave, add him to our conference now. or DAX
2334  if this is slave native */
2335  for (x = 0; x < MAX_SLAVES; x++) {
2336  if (p->slaves[x]) {
2337  if (useslavenative)
2338  conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
2339  else {
2340  conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
2341  needconf++;
2342  }
2343  }
2344  }
2345  /* If we're supposed to be in there, do so now */
2346  if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
2347  if (useslavenative)
2348  conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
2349  else {
2350  conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
2351  needconf++;
2352  }
2353  }
2354  /* If we have a master, add ourselves to his conference */
2355  if (p->master) {
2356  if (isslavenative(p->master, NULL)) {
2357  conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
2358  } else {
2359  conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
2360  }
2361  }
2362  if (!needconf) {
2363  /* Nobody is left (or should be left) in our conference.
2364  Kill it. */
2365  p->confno = -1;
2366  }
2367 
2368  return 0;
2369 }
2370 
2371 static int check_for_conference(struct dahdi_pvt *p);
2372 
2373 static int my_check_for_conference(void *pvt)
2374 {
2375  struct dahdi_pvt *p = pvt;
2376  return check_for_conference(p);
2377 }
2378 
2379 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)
2380 {
2381  struct dahdi_pvt *p = pvt;
2382  int da, db;
2383  int tchan;
2384  int tinthreeway;
2385 
2386  da = analogsub_to_dahdisub(a);
2387  db = analogsub_to_dahdisub(b);
2388 
2389  tchan = p->subs[da].chan;
2390  p->subs[da].chan = p->subs[db].chan;
2391  p->subs[db].chan = tchan;
2392 
2393  tinthreeway = p->subs[da].inthreeway;
2394  p->subs[da].inthreeway = p->subs[db].inthreeway;
2395  p->subs[db].inthreeway = tinthreeway;
2396 
2397  p->subs[da].owner = ast_a;
2398  p->subs[db].owner = ast_b;
2399 
2400  if (ast_a)
2401  ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
2402  if (ast_b)
2403  ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
2404 
2405  wakeup_sub(p, a);
2406  wakeup_sub(p, b);
2407 
2408  return;
2409 }
2410 
2411 /*!
2412  * \internal
2413  * \brief performs duties of dahdi_new, but also removes and possibly unbinds (if callid_created is 1) before returning
2414  * \note this variant of dahdi should only be used in conjunction with ast_callid_threadstorage_auto()
2415  *
2416  * \param callid_created value returned from ast_callid_threadstorage_auto()
2417  * \param i, state, startpbx, idx, law, assignedids, requestor, callid
2418  */
2419 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);
2420 
2421 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);
2422 
2423 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
2424 {
2425  ast_callid callid = 0;
2426  int callid_created = ast_callid_threadstorage_auto(&callid);
2427  struct dahdi_pvt *p = pvt;
2428  int dsub = analogsub_to_dahdisub(sub);
2429 
2430  return dahdi_new_callid_clean(p, state, startpbx, dsub, 0, NULL, requestor, callid, callid_created);
2431 }
2432 
2433 #if defined(HAVE_PRI) || defined(HAVE_SS7)
2434 static int dahdi_setlaw(int dfd, int law)
2435 {
2436  int res;
2437  res = ioctl(dfd, DAHDI_SETLAW, &law);
2438  if (res)
2439  return res;
2440  return 0;
2441 }
2442 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
2443 
2444 #if defined(HAVE_PRI)
2445 static struct ast_channel *my_new_pri_ast_channel(void *pvt, int state,
2446  enum sig_pri_law law, char *exten, const struct ast_assigned_ids *assignedids,
2447  const struct ast_channel *requestor)
2448 {
2449  struct dahdi_pvt *p = pvt;
2450  int audio;
2451  int newlaw = -1;
2452  ast_callid callid = 0;
2453  int callid_created = ast_callid_threadstorage_auto(&callid);
2454 
2455  switch (p->sig) {
2456  case SIG_PRI_LIB_HANDLE_CASES:
2457  if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
2458  /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
2459  break;
2460  }
2461  /* Fall through */
2462  default:
2463  /* Set to audio mode at this point */
2464  audio = 1;
2465  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
2466  ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
2467  p->channel, audio, strerror(errno));
2468  }
2469  break;
2470  }
2471 
2472  if (law != SIG_PRI_DEFLAW) {
2473  dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
2474  }
2475 
2476  ast_copy_string(p->exten, exten, sizeof(p->exten));
2477 
2478  switch (law) {
2479  case SIG_PRI_DEFLAW:
2480  newlaw = 0;
2481  break;
2482  case SIG_PRI_ALAW:
2483  newlaw = DAHDI_LAW_ALAW;
2484  break;
2485  case SIG_PRI_ULAW:
2486  newlaw = DAHDI_LAW_MULAW;
2487  break;
2488  }
2489 
2490  return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, assignedids, requestor, callid, callid_created);
2491 }
2492 #endif /* defined(HAVE_PRI) */
2493 
2494 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
2495 
2496 #if defined(HAVE_PRI) || defined(HAVE_SS7)
2497 /*!
2498  * \internal
2499  * \brief Open the PRI/SS7 channel media path.
2500  * \since 1.8
2501  *
2502  * \param p Channel private control structure.
2503  */
2504 static void my_pri_ss7_open_media(void *p)
2505 {
2506  struct dahdi_pvt *pvt = p;
2507  int res;
2508  int dfd;
2509  int set_val;
2510 
2511  dfd = pvt->subs[SUB_REAL].dfd;
2512 
2513  /* Open the media path. */
2514  set_val = 1;
2515  res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
2516  if (res < 0) {
2517  ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
2518  pvt->channel, strerror(errno));
2519  }
2520 
2521  /* Set correct companding law for this call. */
2522  res = dahdi_setlaw(dfd, pvt->law);
2523  if (res < 0) {
2524  ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
2525  }
2526 
2527  /* Set correct gain for this call. */
2528  if (pvt->digital) {
2529  res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
2530  } else {
2531  res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
2532  pvt->law);
2533  }
2534  if (res < 0) {
2535  ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
2536  }
2537 
2538  if (pvt->dsp_features && pvt->dsp) {
2540  }
2541 }
2542 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
2543 
2544 #if defined(HAVE_PRI)
2545 /*!
2546  * \internal
2547  * \brief Ask DAHDI to dial the given dial string.
2548  * \since 1.8.11
2549  *
2550  * \param p Channel private control structure.
2551  * \param dial_string String to pass to DAHDI to dial.
2552  *
2553  * \note The channel private lock needs to be held when calling.
2554  */
2555 static void my_pri_dial_digits(void *p, const char *dial_string)
2556 {
2557  char dial_str[DAHDI_MAX_DTMF_BUF];
2558  struct dahdi_pvt *pvt = p;
2559  int res;
2560 
2561  snprintf(dial_str, sizeof(dial_str), "T%s", dial_string);
2562  res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
2563  if (!res) {
2564  pvt->dialing = 1;
2565  }
2566 }
2567 #endif /* defined(HAVE_PRI) */
2568 
2569 static int unalloc_sub(struct dahdi_pvt *p, int x);
2570 
2571 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
2572 {
2573  struct dahdi_pvt *p = pvt;
2574 
2575  return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
2576 }
2577 
2578 static int alloc_sub(struct dahdi_pvt *p, int x);
2579 
2580 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
2581 {
2582  struct dahdi_pvt *p = pvt;
2583 
2584  return alloc_sub(p, analogsub_to_dahdisub(analogsub));
2585 }
2586 
2587 static int has_voicemail(struct dahdi_pvt *p);
2588 
2589 static int my_has_voicemail(void *pvt)
2590 {
2591  struct dahdi_pvt *p = pvt;
2592 
2593  return has_voicemail(p);
2594 }
2595 
2596 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
2597 {
2598  struct dahdi_pvt *p = pvt;
2599  int index;
2600 
2601  index = analogsub_to_dahdisub(sub);
2602 
2603  return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
2604 }
2605 
2606 static enum analog_event dahdievent_to_analogevent(int event)
2607 {
2608  enum analog_event res;
2609 
2610  switch (event) {
2611  case DAHDI_EVENT_ONHOOK:
2612  res = ANALOG_EVENT_ONHOOK;
2613  break;
2614  case DAHDI_EVENT_RINGOFFHOOK:
2615  res = ANALOG_EVENT_RINGOFFHOOK;
2616  break;
2617  case DAHDI_EVENT_WINKFLASH:
2618  res = ANALOG_EVENT_WINKFLASH;
2619  break;
2620  case DAHDI_EVENT_ALARM:
2621  res = ANALOG_EVENT_ALARM;
2622  break;
2623  case DAHDI_EVENT_NOALARM:
2624  res = ANALOG_EVENT_NOALARM;
2625  break;
2626  case DAHDI_EVENT_DIALCOMPLETE:
2627  res = ANALOG_EVENT_DIALCOMPLETE;
2628  break;
2629  case DAHDI_EVENT_RINGERON:
2630  res = ANALOG_EVENT_RINGERON;
2631  break;
2632  case DAHDI_EVENT_RINGEROFF:
2633  res = ANALOG_EVENT_RINGEROFF;
2634  break;
2635  case DAHDI_EVENT_HOOKCOMPLETE:
2636  res = ANALOG_EVENT_HOOKCOMPLETE;
2637  break;
2638  case DAHDI_EVENT_PULSE_START:
2639  res = ANALOG_EVENT_PULSE_START;
2640  break;
2641  case DAHDI_EVENT_POLARITY:
2642  res = ANALOG_EVENT_POLARITY;
2643  break;
2644  case DAHDI_EVENT_RINGBEGIN:
2645  res = ANALOG_EVENT_RINGBEGIN;
2646  break;
2647  case DAHDI_EVENT_EC_DISABLED:
2648  res = ANALOG_EVENT_EC_DISABLED;
2649  break;
2650  case DAHDI_EVENT_REMOVED:
2651  res = ANALOG_EVENT_REMOVED;
2652  break;
2653  case DAHDI_EVENT_NEONMWI_ACTIVE:
2654  res = ANALOG_EVENT_NEONMWI_ACTIVE;
2655  break;
2656  case DAHDI_EVENT_NEONMWI_INACTIVE:
2657  res = ANALOG_EVENT_NEONMWI_INACTIVE;
2658  break;
2659 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
2660  case DAHDI_EVENT_TX_CED_DETECTED:
2661  res = ANALOG_EVENT_TX_CED_DETECTED;
2662  break;
2663  case DAHDI_EVENT_RX_CED_DETECTED:
2664  res = ANALOG_EVENT_RX_CED_DETECTED;
2665  break;
2666  case DAHDI_EVENT_EC_NLP_DISABLED:
2667  res = ANALOG_EVENT_EC_NLP_DISABLED;
2668  break;
2669  case DAHDI_EVENT_EC_NLP_ENABLED:
2670  res = ANALOG_EVENT_EC_NLP_ENABLED;
2671  break;
2672 #endif
2673  case DAHDI_EVENT_PULSEDIGIT:
2674  res = ANALOG_EVENT_PULSEDIGIT;
2675  break;
2676  case DAHDI_EVENT_DTMFDOWN:
2677  res = ANALOG_EVENT_DTMFDOWN;
2678  break;
2679  case DAHDI_EVENT_DTMFUP:
2680  res = ANALOG_EVENT_DTMFUP;
2681  break;
2682  default:
2683  switch(event & 0xFFFF0000) {
2684  case DAHDI_EVENT_PULSEDIGIT:
2685  case DAHDI_EVENT_DTMFDOWN:
2686  case DAHDI_EVENT_DTMFUP:
2687  /* The event includes a digit number in the low word.
2688  * Converting it to a 'enum analog_event' would remove
2689  * that information. Thus it is returned as-is.
2690  */
2691  return event;
2692  }
2693 
2694  res = ANALOG_EVENT_ERROR;
2695  break;
2696  }
2697 
2698  return res;
2699 }
2700 
2701 static inline int dahdi_wait_event(int fd);
2702 
2703 static int my_wait_event(void *pvt)
2704 {
2705  struct dahdi_pvt *p = pvt;
2706 
2707  return dahdi_wait_event(p->subs[SUB_REAL].dfd);
2708 }
2709 
2710 static int my_get_event(void *pvt)
2711 {
2712  struct dahdi_pvt *p = pvt;
2713  int res;
2714 
2715  if (p->fake_event) {
2716  res = p->fake_event;
2717  p->fake_event = 0;
2718  } else
2719  res = dahdi_get_event(p->subs[SUB_REAL].dfd);
2720 
2721  return dahdievent_to_analogevent(res);
2722 }
2723 
2724 static int my_is_off_hook(void *pvt)
2725 {
2726  struct dahdi_pvt *p = pvt;
2727  int res;
2728  struct dahdi_params par;
2729 
2730  memset(&par, 0, sizeof(par));
2731 
2732  if (p->subs[SUB_REAL].dfd > -1)
2733  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
2734  else {
2735  /* Assume not off hook on CVRS */
2736  res = 0;
2737  par.rxisoffhook = 0;
2738  }
2739  if (res) {
2740  ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
2741  }
2742 
2743  if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
2744  /* When "onhook" that means no battery on the line, and thus
2745  it is out of service..., if it's on a TDM card... If it's a channel
2746  bank, there is no telling... */
2747  return (par.rxbits > -1) || par.rxisoffhook;
2748  }
2749 
2750  return par.rxisoffhook;
2751 }
2752 
2753 static int my_set_echocanceller(void *pvt, int enable)
2754 {
2755  struct dahdi_pvt *p = pvt;
2756 
2757  if (enable)
2758  dahdi_ec_enable(p);
2759  else
2760  dahdi_ec_disable(p);
2761 
2762  return 0;
2763 }
2764 
2765 static int dahdi_ring_phone(struct dahdi_pvt *p);
2766 
2767 static int my_ring(void *pvt)
2768 {
2769  struct dahdi_pvt *p = pvt;
2770 
2771  return dahdi_ring_phone(p);
2772 }
2773 
2774 static int my_flash(void *pvt)
2775 {
2776  struct dahdi_pvt *p = pvt;
2777  int func = DAHDI_FLASH;
2778  return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
2779 }
2780 
2781 static inline int dahdi_set_hook(int fd, int hs);
2782 
2783 static int my_off_hook(void *pvt)
2784 {
2785  struct dahdi_pvt *p = pvt;
2786  return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
2787 }
2788 
2789 static void my_set_needringing(void *pvt, int value)
2790 {
2791  struct dahdi_pvt *p = pvt;
2792  p->subs[SUB_REAL].needringing = value;
2793 }
2794 
2795 static void my_set_polarity(void *pvt, int value)
2796 {
2797  struct dahdi_pvt *p = pvt;
2798 
2799  if (p->channel == CHAN_PSEUDO) {
2800  return;
2801  }
2802  p->polarity = value;
2803  ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
2804 }
2805 
2806 static void my_start_polarityswitch(void *pvt)
2807 {
2808  struct dahdi_pvt *p = pvt;
2809 
2811  my_set_polarity(pvt, 0);
2812  }
2813 }
2814 
2815 static void my_answer_polarityswitch(void *pvt)
2816 {
2817  struct dahdi_pvt *p = pvt;
2818 
2819  if (!p->answeronpolarityswitch) {
2820  return;
2821  }
2822 
2823  my_set_polarity(pvt, 1);
2824 }
2825 
2826 static void my_hangup_polarityswitch(void *pvt)
2827 {
2828  struct dahdi_pvt *p = pvt;
2829 
2830  if (!p->hanguponpolarityswitch) {
2831  return;
2832  }
2833 
2834  if (p->answeronpolarityswitch) {
2835  my_set_polarity(pvt, 0);
2836  } else {
2837  my_set_polarity(pvt, 1);
2838  }
2839 }
2840 
2841 /*! \brief Return DAHDI pivot if channel is FXO signalled */
2842 static struct dahdi_pvt *fxo_pvt(struct ast_channel *chan)
2843 {
2844  int res;
2845  struct dahdi_params dahdip;
2846  struct dahdi_pvt *pvt = NULL;
2847 
2848  if (strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {
2849  ast_log(LOG_WARNING, "%s is not a DAHDI channel\n", ast_channel_name(chan));
2850  return NULL;
2851  }
2852 
2853  memset(&dahdip, 0, sizeof(dahdip));
2854  res = ioctl(ast_channel_fd(chan, 0), DAHDI_GET_PARAMS, &dahdip);
2855 
2856  if (res) {
2857  ast_log(LOG_WARNING, "Unable to get parameters of %s: %s\n", ast_channel_name(chan), strerror(errno));
2858  return NULL;
2859  }
2860  if (!(dahdip.sigtype & __DAHDI_SIG_FXO)) {
2861  ast_log(LOG_WARNING, "%s is not FXO signalled\n", ast_channel_name(chan));
2862  return NULL;
2863  }
2864 
2865  pvt = ast_channel_tech_pvt(chan);
2866  if (!dahdi_analog_lib_handles(pvt->sig, 0, 0)) {
2867  ast_log(LOG_WARNING, "Channel signalling is not analog");
2868  return NULL;
2869  }
2870 
2871  return pvt;
2872 }
2873 
2874 static int polarity_read(struct ast_channel *chan, const char *cmd, char *data, char *buffer, size_t buflen)
2875 {
2876  struct dahdi_pvt *pvt;
2877 
2878  pvt = fxo_pvt(chan);
2879  if (!pvt) {
2880  return -1;
2881  }
2882 
2883  snprintf(buffer, buflen, "%d", pvt->polarity);
2884 
2885  return 0;
2886 }
2887 
2888 static int polarity_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
2889 {
2890  struct dahdi_pvt *pvt;
2891  int polarity;
2892 
2893  pvt = fxo_pvt(chan);
2894  if (!pvt) {
2895  return -1;
2896  }
2897 
2898  if (!strcasecmp(value, "idle")) {
2899  polarity = POLARITY_IDLE;
2900  } else if (!strcasecmp(value, "reverse")) {
2901  polarity = POLARITY_REV;
2902  } else {
2903  polarity = atoi(value);
2904  }
2905 
2906  if (polarity != POLARITY_IDLE && polarity != POLARITY_REV) {
2907  ast_log(LOG_WARNING, "Invalid polarity: '%s'\n", value);
2908  return -1;
2909  }
2910 
2911  my_set_polarity(pvt, polarity);
2912  return 0;
2913 }
2914 
2915 static struct ast_custom_function polarity_function = {
2916  .name = "POLARITY",
2917  .write = polarity_write,
2918  .read = polarity_read,
2919 };
2920 
2921 static int my_start(void *pvt)
2922 {
2923  struct dahdi_pvt *p = pvt;
2924  int x = DAHDI_START;
2925 
2926  return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
2927 }
2928 
2929 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
2930 {
2931  struct dahdi_pvt *p = pvt;
2932 
2933  if (dop->op != ANALOG_DIAL_OP_REPLACE) {
2934  ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
2935  return -1;
2936  }
2937 
2938  if (sub != ANALOG_SUB_REAL) {
2939  ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %u\n",
2940  dop->dialstr, p->channel, sub);
2941  return -1;
2942  }
2943 
2944  return dahdi_dial_str(p, DAHDI_DIAL_OP_REPLACE, dop->dialstr);
2945 }
2946 
2947 static void dahdi_train_ec(struct dahdi_pvt *p);
2948 
2949 static int my_train_echocanceller(void *pvt)
2950 {
2951  struct dahdi_pvt *p = pvt;
2952 
2953  dahdi_train_ec(p);
2954 
2955  return 0;
2956 }
2957 
2958 static int my_is_dialing(void *pvt, enum analog_sub sub)
2959 {
2960  struct dahdi_pvt *p = pvt;
2961  int index;
2962  int x;
2963 
2964  index = analogsub_to_dahdisub(sub);
2965 
2966  if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
2967  ast_debug(1, "DAHDI_DIALING ioctl failed!\n");
2968  return -1;
2969  }
2970 
2971  return x;
2972 }
2973 
2974 static int my_on_hook(void *pvt)
2975 {
2976  struct dahdi_pvt *p = pvt;
2977  return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
2978 }
2979 
2980 #if defined(HAVE_PRI)
2981 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
2982 {
2983  struct dahdi_pvt *old_chan = chan_old;
2984  struct dahdi_pvt *new_chan = chan_new;
2985 
2986  new_chan->owner = old_chan->owner;
2987  old_chan->owner = NULL;
2988  if (new_chan->owner) {
2989  ast_channel_tech_pvt_set(new_chan->owner, new_chan);
2990  ast_channel_internal_fd_set(new_chan->owner, 0, new_chan->subs[SUB_REAL].dfd);
2991  new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
2992  old_chan->subs[SUB_REAL].owner = NULL;
2993  }
2994  /* Copy any DSP that may be present */
2995  new_chan->dsp = old_chan->dsp;
2996  new_chan->dsp_features = old_chan->dsp_features;
2997  old_chan->dsp = NULL;
2998  old_chan->dsp_features = 0;
2999 
3000  /* Transfer flags from the old channel. */
3001  new_chan->dialing = old_chan->dialing;
3002  new_chan->digital = old_chan->digital;
3003  new_chan->outgoing = old_chan->outgoing;
3004  old_chan->dialing = 0;
3005  old_chan->digital = 0;
3006  old_chan->outgoing = 0;
3007 
3008  /* More stuff to transfer to the new channel. */
3009  new_chan->law = old_chan->law;
3010  strcpy(new_chan->dialstring, old_chan->dialstring);
3011 }
3012 #endif /* defined(HAVE_PRI) */
3013 
3014 #if defined(HAVE_PRI)
3015 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
3016 {
3017  switch (tone) {
3018  case SIG_PRI_TONE_RINGTONE:
3019  return DAHDI_TONE_RINGTONE;
3020  case SIG_PRI_TONE_STUTTER:
3021  return DAHDI_TONE_STUTTER;
3022  case SIG_PRI_TONE_CONGESTION:
3023  return DAHDI_TONE_CONGESTION;
3024  case SIG_PRI_TONE_DIALTONE:
3025  return DAHDI_TONE_DIALTONE;
3026  case SIG_PRI_TONE_DIALRECALL:
3027  return DAHDI_TONE_DIALRECALL;
3028  case SIG_PRI_TONE_INFO:
3029  return DAHDI_TONE_INFO;
3030  case SIG_PRI_TONE_BUSY:
3031  return DAHDI_TONE_BUSY;
3032  default:
3033  return -1;
3034  }
3035 }
3036 #endif /* defined(HAVE_PRI) */
3037 
3038 #if defined(HAVE_PRI)
3039 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
3040 {
3041  int x;
3042 
3043  ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
3044  switch (x) {
3045  case DAHDI_EVENT_NONE:
3046  break;
3047  case DAHDI_EVENT_ALARM:
3048  case DAHDI_EVENT_NOALARM:
3049  if (sig_pri_is_alarm_ignored(pri)) {
3050  break;
3051  }
3052  /* Fall through */
3053  default:
3054  ast_log(LOG_NOTICE, "Got DAHDI event: %s (%d) on D-channel of span %d\n",
3055  event2str(x), x, pri->span);
3056  break;
3057  }
3058  /* Keep track of alarm state */
3059  switch (x) {
3060  case DAHDI_EVENT_ALARM:
3061  pri_event_alarm(pri, index, 0);
3062  break;
3063  case DAHDI_EVENT_NOALARM:
3064  pri_event_noalarm(pri, index, 0);
3065  break;
3066  case DAHDI_EVENT_REMOVED:
3068  break;
3069  default:
3070  break;
3071  }
3072 }
3073 #endif /* defined(HAVE_PRI) */
3074 
3075 #if defined(HAVE_PRI)
3076 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
3077 {
3078  struct dahdi_pvt *p = pvt;
3079 
3080  return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
3081 }
3082 #endif /* defined(HAVE_PRI) */
3083 
3084 #if defined(HAVE_PRI) || defined(HAVE_SS7)
3085 /*!
3086  * \internal
3087  * \brief Set the caller id information.
3088  * \since 1.8
3089  *
3090  * \param pvt DAHDI private structure
3091  * \param caller Caller-id information to set.
3092  */
3093 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
3094 {
3095  struct dahdi_pvt *p = pvt;
3096 
3098  S_COR(caller->id.number.valid, caller->id.number.str, ""),
3099  sizeof(p->cid_num));
3101  S_COR(caller->id.name.valid, caller->id.name.str, ""),
3102  sizeof(p->cid_name));
3104  S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
3105  sizeof(p->cid_subaddr));
3106  p->cid_ton = caller->id.number.plan;
3107  p->callingpres = ast_party_id_presentation(&caller->id);
3108  if (caller->id.tag) {
3109  ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
3110  }
3112  S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
3113  sizeof(p->cid_ani));
3114  p->cid_ani2 = caller->ani2;
3115 }
3116 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
3117 
3118 #if defined(HAVE_PRI) || defined(HAVE_SS7)
3119 /*!
3120  * \internal
3121  * \brief Set the Dialed Number Identifier.
3122  * \since 1.8
3123  *
3124  * \param pvt DAHDI private structure
3125  * \param dnid Dialed Number Identifier string.
3126  */
3127 static void my_set_dnid(void *pvt, const char *dnid)
3128 {
3129  struct dahdi_pvt *p = pvt;
3130 
3131  ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
3132 }
3133 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
3134 
3135 #if defined(HAVE_PRI)
3136 /*!
3137  * \internal
3138  * \brief Set the Redirecting Directory Number Information Service (RDNIS).
3139  * \since 1.8
3140  *
3141  * \param pvt DAHDI private structure
3142  * \param rdnis Redirecting Directory Number Information Service (RDNIS) string.
3143  */
3144 static void my_set_rdnis(void *pvt, const char *rdnis)
3145 {
3146  struct dahdi_pvt *p = pvt;
3147 
3148  ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
3149 }
3150 #endif /* defined(HAVE_PRI) */
3151 
3152 #if defined(HAVE_PRI)
3153 /*!
3154  * \internal
3155  * \brief Make a dialstring for native ISDN CC to recall properly.
3156  * \since 1.8
3157  *
3158  * \param priv Channel private control structure.
3159  * \param buf Where to put the modified dialstring.
3160  * \param buf_size Size of modified dialstring buffer.
3161  *
3162  * \details
3163  * original dialstring:
3164  * \verbatim
3165  DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadence#>|d][/extension[/options]]
3166  \endverbatim
3167  *
3168  * The modified dialstring will have prefixed the channel-group section
3169  * with the ISDN channel restriction.
3170  *
3171  * buf:
3172  * \verbatim
3173  DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadence#>|d][/extension[/options]]
3174  \endverbatim
3175  *
3176  * The routine will check to see if the ISDN channel restriction is already
3177  * in the original dialstring.
3178  */
3179 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
3180 {
3181  char *dial;
3182  struct dahdi_pvt *pvt;
3183  AST_DECLARE_APP_ARGS(args,
3184  AST_APP_ARG(tech); /* channel technology token */
3185  AST_APP_ARG(group); /* channel/group token */
3186  //AST_APP_ARG(ext); /* extension token */
3187  //AST_APP_ARG(opts); /* options token */
3188  //AST_APP_ARG(other); /* Any remining unused arguments */
3189  );
3190 
3191  pvt = priv;
3192  dial = ast_strdupa(pvt->dialstring);
3193  AST_NONSTANDARD_APP_ARGS(args, dial, '/');
3194  if (!args.tech) {
3195  ast_copy_string(buf, pvt->dialstring, buf_size);
3196  return;
3197  }
3198  if (!args.group) {
3199  /* Append the ISDN span channel restriction to the dialstring. */
3200  snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
3201  return;
3202  }
3203  if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
3204  /* The ISDN span channel restriction is not needed or already
3205  * in the dialstring. */
3206  ast_copy_string(buf, pvt->dialstring, buf_size);
3207  return;
3208  }
3209  /* Insert the ISDN span channel restriction into the dialstring. */
3210  snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
3211 }
3212 #endif /* defined(HAVE_PRI) */
3213 
3214 #if defined(HAVE_PRI)
3215 /*!
3216  * \internal
3217  * \brief Reevaluate the PRI span device state.
3218  * \since 1.8
3219  *
3220  * \param pri Asterisk D channel control structure.
3221  *
3222  * \note Assumes the pri->lock is already obtained.
3223  */
3224 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
3225 {
3226  unsigned idx;
3227  unsigned num_b_chans; /* Number of B channels provisioned on the span. */
3228  unsigned in_use; /* Number of B channels in use on the span. */
3229  unsigned in_alarm; /* TRUE if the span is in alarm condition. */
3230  enum ast_device_state new_state;
3231 
3232  /* Count the number of B channels and the number of B channels in use. */
3233  num_b_chans = 0;
3234  in_use = 0;
3235  in_alarm = 1;
3236  for (idx = pri->numchans; idx--;) {
3237  if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
3238  /* This is a B channel interface. */
3239  ++num_b_chans;
3240  if (!sig_pri_is_chan_available(pri->pvts[idx])) {
3241  ++in_use;
3242  }
3243  if (!pri->pvts[idx]->inalarm) {
3244  /* There is a channel that is not in alarm. */
3245  in_alarm = 0;
3246  }
3247  }
3248  }
3249 
3250  /* Update the span congestion device state and report any change. */
3251  if (in_alarm) {
3252  new_state = AST_DEVICE_UNAVAILABLE;
3253  } else {
3254  new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
3255  }
3256  if (pri->congestion_devstate != new_state) {
3257  pri->congestion_devstate = new_state;
3259  }
3260 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
3261  /* Update the span threshold device state and report any change. */
3262  if (in_alarm) {
3263  new_state = AST_DEVICE_UNAVAILABLE;
3264  } else if (!in_use) {
3265  new_state = AST_DEVICE_NOT_INUSE;
3266  } else if (!pri->user_busy_threshold) {
3267  new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
3268  } else {
3269  new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
3270  : AST_DEVICE_BUSY;
3271  }
3272  if (pri->threshold_devstate != new_state) {
3273  pri->threshold_devstate = new_state;
3275  }
3276 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
3277 }
3278 #endif /* defined(HAVE_PRI) */
3279 
3280 #if defined(HAVE_PRI)
3281 /*!
3282  * \internal
3283  * \brief Reference this module.
3284  * \since 1.8
3285  */
3286 static void my_module_ref(void)
3287 {
3289 }
3290 #endif /* defined(HAVE_PRI) */
3291 
3292 #if defined(HAVE_PRI)
3293 /*!
3294  * \internal
3295  * \brief Unreference this module.
3296  * \since 1.8
3297  */
3298 static void my_module_unref(void)
3299 {
3301 }
3302 #endif /* defined(HAVE_PRI) */
3303 
3304 #if defined(HAVE_PRI)
3305 #if defined(HAVE_PRI_CALL_WAITING)
3306 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
3307 #endif /* defined(HAVE_PRI_CALL_WAITING) */
3308 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
3309 
3311 {
3312  .handle_dchan_exception = my_handle_dchan_exception,
3313  .play_tone = my_pri_play_tone,
3314  .set_echocanceller = my_set_echocanceller,
3315  .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
3316  .lock_private = my_lock_private,
3317  .unlock_private = my_unlock_private,
3318  .deadlock_avoidance_private = my_deadlock_avoidance_private,
3319  .new_ast_channel = my_new_pri_ast_channel,
3320  .fixup_chans = my_pri_fixup_chans,
3321  .set_alarm = my_set_alarm,
3322  .set_dialing = my_set_dialing,
3323  .set_outgoing = my_set_outgoing,
3324  .set_digital = my_set_digital,
3325  .set_callerid = my_set_callerid,
3326  .set_dnid = my_set_dnid,
3327  .set_rdnis = my_set_rdnis,
3328  .new_nobch_intf = dahdi_new_pri_nobch_channel,
3329 #if defined(HAVE_PRI_CALL_WAITING)
3330  .init_config = my_pri_init_config,
3331 #endif /* defined(HAVE_PRI_CALL_WAITING) */
3332  .get_orig_dialstring = my_get_orig_dialstring,
3333  .make_cc_dialstring = my_pri_make_cc_dialstring,
3334  .update_span_devstate = dahdi_pri_update_span_devstate,
3335  .module_ref = my_module_ref,
3336  .module_unref = my_module_unref,
3337  .dial_digits = my_pri_dial_digits,
3338  .open_media = my_pri_ss7_open_media,
3339  .ami_channel_event = my_ami_channel_event,
3340  .destroy_later = pri_queue_for_destruction,
3341 };
3342 #endif /* defined(HAVE_PRI) */
3343 
3344 #if defined(HAVE_SS7)
3345 /*!
3346  * \internal
3347  * \brief Handle the SS7 link exception.
3348  * \since 1.8
3349  *
3350  * \param linkset Controlling linkset for the channel.
3351  * \param which Link index of the signaling channel.
3352  */
3353 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
3354 {
3355  int event;
3356 
3357  if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
3358  ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
3359  linkset->span, which);
3360  return;
3361  }
3362  switch (event) {
3363  case DAHDI_EVENT_NONE:
3364  break;
3365  case DAHDI_EVENT_ALARM:
3366  ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
3367  event2str(event), event, linkset->span, which);
3368  sig_ss7_link_alarm(linkset, which);
3369  break;
3370  case DAHDI_EVENT_NOALARM:
3371  ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
3372  event2str(event), event, linkset->span, which);
3373  sig_ss7_link_noalarm(linkset, which);
3374  break;
3375  default:
3376  ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
3377  event2str(event), event, linkset->span, which);
3378  break;
3379  }
3380 }
3381 #endif /* defined(HAVE_SS7) */
3382 
3383 #if defined(HAVE_SS7)
3384 static void my_ss7_set_loopback(void *pvt, int enable)
3385 {
3386  struct dahdi_pvt *p = pvt;
3387 
3388  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
3389  ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
3390  strerror(errno));
3391  }
3392 }
3393 #endif /* defined(HAVE_SS7) */
3394 
3395 #if defined(HAVE_SS7)
3396 /*!
3397  * \internal
3398  * \brief Find the linkset to which SS7 belongs.
3399  * \since 11.0
3400  *
3401  * \param ss7 structure to match on.
3402  *
3403  * \retval linkset if found.
3404  * \retval NULL if not found.
3405  */
3406 static struct sig_ss7_linkset *my_ss7_find_linkset(struct ss7 *ss7)
3407 {
3408  int idx;
3409 
3410  if (!ss7) {
3411  return NULL;
3412  }
3413 
3414  for (idx = 0; idx < NUM_SPANS; ++idx) {
3415  if (linksets[idx].ss7.ss7 == ss7) {
3416  return &linksets[idx].ss7;
3417  }
3418  }
3419  return NULL;
3420 }
3421 #endif /* defined(HAVE_SS7) */
3422 
3423 #if defined(HAVE_SS7)
3424 /*!
3425  * \internal
3426  * \brief Create a new asterisk channel structure for SS7.
3427  * \since 1.8
3428  *
3429  * \param pvt Private channel structure.
3430  * \param state Initial state of new channel.
3431  * \param law Companding law to use.
3432  * \param exten Dialplan extension for incoming call.
3433  * \param requestor Channel requesting this new channel.
3434  * \param assignedids
3435  *
3436  * \retval ast_channel on success.
3437  * \retval NULL on error.
3438  */
3439 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)
3440 {
3441  struct dahdi_pvt *p = pvt;
3442  int audio;
3443  int newlaw;
3444  ast_callid callid = 0;
3445  int callid_created = ast_callid_threadstorage_auto(&callid);
3446 
3447  /* Set to audio mode at this point */
3448  audio = 1;
3449  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
3450  ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
3451  p->channel, audio, strerror(errno));
3452 
3453  if (law != SIG_SS7_DEFLAW) {
3454  dahdi_setlaw(p->subs[SUB_REAL].dfd,
3455  (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
3456  }
3457 
3458  ast_copy_string(p->exten, exten, sizeof(p->exten));
3459 
3460  newlaw = -1;
3461  switch (law) {
3462  case SIG_SS7_DEFLAW:
3463  newlaw = 0;
3464  break;
3465  case SIG_SS7_ALAW:
3466  newlaw = DAHDI_LAW_ALAW;
3467  break;
3468  case SIG_SS7_ULAW:
3469  newlaw = DAHDI_LAW_MULAW;
3470  break;
3471  }
3472  return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, assignedids, requestor, callid, callid_created);
3473 }
3474 #endif /* defined(HAVE_SS7) */
3475 
3476 #if defined(HAVE_SS7)
3477 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
3478 {
3479  switch (tone) {
3480  case SIG_SS7_TONE_RINGTONE:
3481  return DAHDI_TONE_RINGTONE;
3482  case SIG_SS7_TONE_STUTTER:
3483  return DAHDI_TONE_STUTTER;
3484  case SIG_SS7_TONE_CONGESTION:
3485  return DAHDI_TONE_CONGESTION;
3486  case SIG_SS7_TONE_DIALTONE:
3487  return DAHDI_TONE_DIALTONE;
3488  case SIG_SS7_TONE_DIALRECALL:
3489  return DAHDI_TONE_DIALRECALL;
3490  case SIG_SS7_TONE_INFO:
3491  return DAHDI_TONE_INFO;
3492  case SIG_SS7_TONE_BUSY:
3493  return DAHDI_TONE_BUSY;
3494  default:
3495  return -1;
3496  }
3497 }
3498 #endif /* defined(HAVE_SS7) */
3499 
3500 #if defined(HAVE_SS7)
3501 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
3502 {
3503  struct dahdi_pvt *p = pvt;
3504 
3505  return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
3506 }
3507 #endif /* defined(HAVE_SS7) */
3508 
3509 #if defined(HAVE_SS7)
3511 {
3512  .lock_private = my_lock_private,
3513  .unlock_private = my_unlock_private,
3514  .deadlock_avoidance_private = my_deadlock_avoidance_private,
3515 
3516  .set_echocanceller = my_set_echocanceller,
3517  .set_loopback = my_ss7_set_loopback,
3518 
3519  .new_ast_channel = my_new_ss7_ast_channel,
3520  .play_tone = my_ss7_play_tone,
3521 
3522  .handle_link_exception = my_handle_link_exception,
3523  .set_alarm = my_set_alarm,
3524  .set_dialing = my_set_dialing,
3525  .set_outgoing = my_set_outgoing,
3526  .set_digital = my_set_digital,
3527  .set_inservice = my_set_inservice,
3528  .set_locallyblocked = my_set_locallyblocked,
3529  .set_remotelyblocked = my_set_remotelyblocked,
3530  .set_callerid = my_set_callerid,
3531  .set_dnid = my_set_dnid,
3532  .open_media = my_pri_ss7_open_media,
3533  .find_linkset = my_ss7_find_linkset,
3534 };
3535 #endif /* defined(HAVE_SS7) */
3536 
3537 /*!
3538  * \brief Send MWI state change
3539  *
3540  * \param mailbox This is the mailbox associated with the FXO line that the
3541  * MWI state has changed on.
3542  * \param thereornot This argument should simply be set to 1 or 0, to indicate
3543  * whether there are messages waiting or not.
3544  *
3545  * This function does two things:
3546  *
3547  * 1) It generates an internal Asterisk event notifying any other module that
3548  * cares about MWI that the state of a mailbox has changed.
3549  *
3550  * 2) It runs the script specified by the mwimonitornotify option to allow
3551  * some custom handling of the state change.
3552  */
3553 static void notify_message(char *mailbox, int thereornot)
3554 {
3555  char s[sizeof(mwimonitornotify) + 164];
3556 
3557  if (ast_strlen_zero(mailbox)) {
3558  return;
3559  }
3560 
3561  ast_publish_mwi_state(mailbox, NULL, thereornot, thereornot);
3562  if (!ast_strlen_zero(mwimonitornotify)) {
3563  snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
3564  ast_safe_system(s);
3565  }
3566 }
3567 
3568 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
3569 {
3570  struct dahdi_pvt *p = pvt;
3571 
3572  if (neon_mwievent > -1 && !p->mwimonitor_neon)
3573  return;
3574 
3575  if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
3576  ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
3577  notify_message(p->mailbox, 1);
3578  } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
3579  ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
3580  notify_message(p->mailbox, 0);
3581  }
3582  /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
3583  /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
3584  if (neon_mwievent == -1 && p->mwimonitor_rpas) {
3585  ast_hangup(chan);
3586  return;
3587  }
3588 }
3589 
3590 static int my_have_progressdetect(void *pvt)
3591 {
3592  struct dahdi_pvt *p = pvt;
3593 
3594  if ((p->callprogress & CALLPROGRESS_PROGRESS)
3595  && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
3596  return 1;
3597  } else {
3598  /* Don't have progress detection. */
3599  return 0;
3600  }
3601 }
3602 
3603 #define gen_pvt_field_callback(type, field) \
3604  static type my_get_##field(void *pvt) \
3605  { \
3606  struct dahdi_pvt *p = pvt; \
3607  return p->field; \
3608  }
3609 
3610 gen_pvt_field_callback(int, firstdigit_timeout);
3611 gen_pvt_field_callback(int, interdigit_timeout);
3612 gen_pvt_field_callback(int, matchdigit_timeout);
3613 
3614 #undef gen_pvt_field_callback
3615 
3617 {
3618  .play_tone = my_play_tone,
3619  .get_event = my_get_event,
3620  .wait_event = my_wait_event,
3621  .is_off_hook = my_is_off_hook,
3622  .set_echocanceller = my_set_echocanceller,
3623  .ring = my_ring,
3624  .flash = my_flash,
3625  .off_hook = my_off_hook,
3626  .dial_digits = my_dial_digits,
3627  .train_echocanceller = my_train_echocanceller,
3628  .on_hook = my_on_hook,
3629  .is_dialing = my_is_dialing,
3630  .allocate_sub = my_allocate_sub,
3631  .unallocate_sub = my_unallocate_sub,
3632  .swap_subs = my_swap_subchannels,
3633  .has_voicemail = my_has_voicemail,
3634  .check_for_conference = my_check_for_conference,
3635  .conf_add = my_conf_add,
3636  .conf_del = my_conf_del,
3637  .complete_conference_update = my_complete_conference_update,
3638  .start = my_start,
3639  .all_subchannels_hungup = my_all_subchannels_hungup,
3640  .lock_private = my_lock_private,
3641  .unlock_private = my_unlock_private,
3642  .deadlock_avoidance_private = my_deadlock_avoidance_private,
3643  .handle_dtmf = my_handle_dtmf,
3644  .wink = my_wink,
3645  .new_ast_channel = my_new_analog_ast_channel,
3646  .dsp_set_digitmode = my_dsp_set_digitmode,
3647  .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
3648  .send_callerid = my_send_callerid,
3649  .callwait = my_callwait,
3650  .stop_callwait = my_stop_callwait,
3651  .get_callerid = my_get_callerid,
3652  .start_cid_detect = my_start_cid_detect,
3653  .stop_cid_detect = my_stop_cid_detect,
3654  .handle_notify_message = my_handle_notify_message,
3655  .increase_ss_count = my_increase_ss_count,
3656  .decrease_ss_count = my_decrease_ss_count,
3657  .distinctive_ring = my_distinctive_ring,
3658  .set_linear_mode = my_set_linear_mode,
3659  .set_inthreeway = my_set_inthreeway,
3660  .get_and_handle_alarms = my_get_and_handle_alarms,
3661  .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
3662  .get_sub_fd = my_get_sub_fd,
3663  .set_cadence = my_set_cadence,
3664  .set_alarm = my_set_alarm,
3665  .set_dialing = my_set_dialing,
3666  .set_outgoing = my_set_outgoing,
3667  .set_ringtimeout = my_set_ringtimeout,
3668  .set_waitingfordt = my_set_waitingfordt,
3669  .check_waitingfordt = my_check_waitingfordt,
3670  .set_confirmanswer = my_set_confirmanswer,
3671  .check_confirmanswer = my_check_confirmanswer,
3672  .set_callwaiting = my_set_callwaiting,
3673  .cancel_cidspill = my_cancel_cidspill,
3674  .confmute = my_confmute,
3675  .set_pulsedial = my_set_pulsedial,
3676  .set_new_owner = my_set_new_owner,
3677  .get_orig_dialstring = my_get_orig_dialstring,
3678  .set_needringing = my_set_needringing,
3679  .set_polarity = my_set_polarity,
3680  .start_polarityswitch = my_start_polarityswitch,
3681  .answer_polarityswitch = my_answer_polarityswitch,
3682  .hangup_polarityswitch = my_hangup_polarityswitch,
3683  .have_progressdetect = my_have_progressdetect,
3684  .get_firstdigit_timeout = my_get_firstdigit_timeout,
3685  .get_matchdigit_timeout = my_get_matchdigit_timeout,
3686  .get_interdigit_timeout = my_get_interdigit_timeout,
3687 };
3688 
3689 /*! Round robin search locations. */
3690 static struct dahdi_pvt *round_robin[64]; /* groups can range from 0-63 */
3691 
3692 int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
3693 {
3694  int res;
3695  if (p->subs[SUB_REAL].owner == ast)
3696  res = 0;
3697  else if (p->subs[SUB_CALLWAIT].owner == ast)
3698  res = 1;
3699  else if (p->subs[SUB_THREEWAY].owner == ast)
3700  res = 2;
3701  else {
3702  res = -1;
3703  if (!nullok)
3704  ast_log(LOG_WARNING,
3705  "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
3706  ast ? ast_channel_name(ast) : "", p->channel, fname, line);
3707  }
3708  return res;
3709 }
3710 
3711 /*!
3712  * \internal
3713  * \brief Obtain the specified subchannel owner lock if the owner exists.
3714  *
3715  * \param pvt Channel private struct.
3716  * \param sub_idx Subchannel owner to lock.
3717  *
3718  * \note Assumes the pvt->lock is already obtained.
3719  *
3720  * \note
3721  * Because deadlock avoidance may have been necessary, you need to confirm
3722  * the state of things before continuing.
3723  */
3724 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
3725 {
3726  for (;;) {
3727  if (!pvt->subs[sub_idx].owner) {
3728  /* No subchannel owner pointer */
3729  break;
3730  }
3731  if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
3732  /* Got subchannel owner lock */
3733  break;
3734  }
3735  /* We must unlock the private to avoid the possibility of a deadlock */
3736  DEADLOCK_AVOIDANCE(&pvt->lock);
3737  }
3738 }
3739 
3740 static void wakeup_sub(struct dahdi_pvt *p, int a)
3741 {
3742  dahdi_lock_sub_owner(p, a);
3743  if (p->subs[a].owner) {
3744  ast_queue_frame(p->subs[a].owner, &ast_null_frame);
3745  ast_channel_unlock(p->subs[a].owner);
3746  }
3747 }
3748 
3749 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
3750 {
3751  for (;;) {
3752  if (p->owner) {
3753  if (ast_channel_trylock(p->owner)) {
3754  DEADLOCK_AVOIDANCE(&p->lock);
3755  } else {
3756  ast_queue_frame(p->owner, f);
3757  ast_channel_unlock(p->owner);
3758  break;
3759  }
3760  } else
3761  break;
3762  }
3763 }
3764 
3765 static void publish_channel_alarm_clear(int channel)
3766 {
3767  RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
3768  RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free);
3769  if (!dahdi_chan) {
3770  return;
3771  }
3772 
3773  ast_str_set(&dahdi_chan, 0, "%d", channel);
3774  ast_log(LOG_NOTICE, "Alarm cleared on channel DAHDI/%d\n", channel);
3775  body = ast_json_pack("{s: s}", "DAHDIChannel", ast_str_buffer(dahdi_chan));
3776  if (!body) {
3777  return;
3778  }
3779 
3780  ast_manager_publish_event("AlarmClear", EVENT_FLAG_SYSTEM, body);
3781 }
3782 
3783 static void publish_span_alarm_clear(int span)
3784 {
3785  RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
3786 
3787  ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", span);
3788  body = ast_json_pack("{s: i}", "Span", span);
3789  if (!body) {
3790  return;
3791  }
3792 
3793  ast_manager_publish_event("SpanAlarmClear", EVENT_FLAG_SYSTEM, body);
3794 }
3795 
3796 static void handle_clear_alarms(struct dahdi_pvt *p)
3797 {
3798 #if defined(HAVE_PRI)
3799  if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
3800  return;
3801  }
3802 #endif /* defined(HAVE_PRI) */
3803 
3804  if (report_alarms & REPORT_CHANNEL_ALARMS) {
3805  publish_channel_alarm_clear(p->channel);
3806  }
3807  if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
3808  publish_span_alarm_clear(p->span);
3809  }
3810 }
3811 
3812 #ifdef HAVE_OPENR2
3813 static void mfcr2_queue_for_destruction(const struct dahdi_pvt *p)
3814 {
3815  const struct dahdi_mfcr2 *r2link = p->mfcr2;
3816  struct r2link_entry *cur;
3817  AST_LIST_LOCK(&r2links);
3818  AST_LIST_TRAVERSE_SAFE_BEGIN(&r2links, cur, list) {
3819  if (r2link == &cur->mfcr2) {
3820  ast_debug(3, "MFC/R2 channel %d queued for destruction\n", p->channel);
3821  AST_LIST_MOVE_CURRENT(&nodev_r2links, list);
3822  break;
3823  }
3824  }
3826  AST_LIST_UNLOCK(&r2links);
3827 }
3828 
3829 static int dahdi_r2_answer(struct dahdi_pvt *p)
3830 {
3831  int res = 0;
3832  /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
3833  * and does not has support for openr2_chan_answer_call_with_mode
3834  * */
3835 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
3836  const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
3837  int wants_double_answer = ast_true(double_answer) ? 1 : 0;
3838  if (!double_answer) {
3839  /* this still can result in double answer if the channel context
3840  * was configured that way */
3841  res = openr2_chan_answer_call(p->r2chan);
3842  } else if (wants_double_answer) {
3843  res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
3844  } else {
3845  res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
3846  }
3847 #else
3848  res = openr2_chan_answer_call(p->r2chan);
3849 #endif
3850  return res;
3851 }
3852 
3853 
3854 
3855 /* should be called with the ast_channel locked */
3856 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
3857 {
3858  openr2_calling_party_category_t cat;
3859  const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
3860  struct dahdi_pvt *p = ast_channel_tech_pvt(c);
3861  if (ast_strlen_zero(catstr)) {
3862  ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
3863  ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
3864  return p->mfcr2_category;
3865  }
3866  if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
3867  ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
3868  catstr, ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
3869  return p->mfcr2_category;
3870  }
3871  ast_debug(1, "Using category %s\n", catstr);
3872  return cat;
3873 }
3874 
3875 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
3876 {
3877  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3878  ast_mutex_lock(&p->lock);
3879  if (p->mfcr2call) {
3880  ast_mutex_unlock(&p->lock);
3881  /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
3882  interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
3883  can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
3884  the other end will see our seize as a forced release and drop the call, we will see an invalid
3885  pattern that will be seen and treated as protocol error. */
3886  ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
3887  return;
3888  }
3889  p->mfcr2call = 1;
3890  /* better safe than sorry ... */
3891  p->cid_name[0] = '\0';
3892  p->cid_num[0] = '\0';
3893  p->cid_subaddr[0] = '\0';
3894  p->rdnis[0] = '\0';
3895  p->exten[0] = '\0';
3896  p->mfcr2_ani_index = '\0';
3897  p->mfcr2_dnis_index = '\0';
3898  p->mfcr2_dnis_matched = 0;
3899  p->mfcr2_answer_pending = 0;
3900  p->mfcr2_call_accepted = 0;
3901  ast_mutex_unlock(&p->lock);
3902  ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
3903 }
3904 
3905 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
3906 {
3907  int res;
3908  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3909  ast_mutex_lock(&p->lock);
3910  p->inalarm = alarm ? 1 : 0;
3911  if (p->inalarm) {
3912  res = get_alarms(p);
3913  if (res == DAHDI_ALARM_NOTOPEN) {
3914  mfcr2_queue_for_destruction(p);
3915  }
3916  handle_alarms(p, res);
3917  } else {
3918  handle_clear_alarms(p);
3919  }
3920  ast_mutex_unlock(&p->lock);
3921 }
3922 
3923 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
3924 {
3925  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3926 
3927  ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
3928  ast_mutex_lock(&p->lock);
3929  /* Disconnected? */
3930  if (errorcode == ENODEV) {
3931  struct dahdi_mfcr2 *r2link = p->mfcr2;
3932  p->mfcr2call = 0;
3933  if (r2link) {
3934  r2link->nodev = 1;
3935  }
3936  }
3937  ast_mutex_unlock(&p->lock);
3938 }
3939 
3940 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
3941 {
3942  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3943  ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
3944  if (p->owner) {
3945  ast_channel_hangupcause_set(p->owner, AST_CAUSE_PROTOCOL_ERROR);
3946  ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
3947  }
3948  ast_mutex_lock(&p->lock);
3949  p->mfcr2call = 0;
3950  ast_mutex_unlock(&p->lock);
3951 }
3952 
3953 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
3954 {
3955  if (openr2_chan_disconnect_call(p->r2chan, cause)) {
3956  ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
3957  p->channel, openr2_proto_get_disconnect_string(cause));
3958  /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
3959  openr2_chan_set_idle(p->r2chan);
3960  ast_mutex_lock(&p->lock);
3961  p->mfcr2call = 0;
3962  ast_mutex_unlock(&p->lock);
3963  }
3964 }
3965 
3966 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
3967 {
3968  struct dahdi_pvt *p;
3969  struct ast_channel *c;
3970  ast_callid callid = 0;
3971  int callid_created = ast_callid_threadstorage_auto(&callid);
3972  ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
3973  openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
3974  openr2_proto_get_category_string(category));
3975  p = openr2_chan_get_client_data(r2chan);
3976  /* if collect calls are not allowed and this is a collect call, reject it! */
3977  if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
3978  ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
3979  dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
3980  goto dahdi_r2_on_call_offered_cleanup;
3981  }
3982  ast_mutex_lock(&p->lock);
3983  p->mfcr2_recvd_category = category;
3984  /* if we're not supposed to use CID, clear whatever we have */
3985  if (!p->use_callerid) {
3986  ast_debug(1, "No CID allowed in configuration, CID is being cleared!\n");
3987  p->cid_num[0] = 0;
3988  p->cid_name[0] = 0;
3989  }
3990  /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
3991  if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
3992  ast_debug(1, "Setting exten => s because of immediate or 0 DNIS configured\n");
3993  p->exten[0] = 's';
3994  p->exten[1] = 0;
3995  }
3996  ast_mutex_unlock(&p->lock);
3997  if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
3998  ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
3999  p->channel, p->exten, p->context);
4000  dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
4001  goto dahdi_r2_on_call_offered_cleanup;
4002  }
4003  if (!p->mfcr2_accept_on_offer) {
4004  /* The user wants us to start the PBX thread right away without accepting the call first */
4005  c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, NULL, callid);
4006  if (c) {
4007  /* Done here, don't disable reading now since we still need to generate MF tones to accept
4008  the call or reject it and detect the tone off condition of the other end, all of this
4009  will be done in the PBX thread now */
4010  goto dahdi_r2_on_call_offered_cleanup;
4011  }
4012  ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
4013  dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
4014  } else if (p->mfcr2_charge_calls) {
4015  ast_debug(1, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
4016  openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
4017  } else {
4018  ast_debug(1, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
4019  openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
4020  }
4021 
4022 dahdi_r2_on_call_offered_cleanup:
4023  ast_callid_threadstorage_auto_clean(callid, callid_created);
4024 }
4025 
4026 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
4027 {
4028  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4029  ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
4030  ast_mutex_lock(&p->lock);
4031  p->mfcr2call = 0;
4032  ast_mutex_unlock(&p->lock);
4033 }
4034 
4035 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
4036 {
4037  struct dahdi_pvt *p = NULL;
4038  struct ast_channel *c = NULL;
4039  ast_callid callid = 0;
4040  int callid_created = ast_callid_threadstorage_auto(&callid);
4041  p = openr2_chan_get_client_data(r2chan);
4042  dahdi_ec_enable(p);
4043  p->mfcr2_call_accepted = 1;
4044  /* if it's an incoming call ... */
4045  if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
4046  ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
4047  /* If accept on offer is not set, it means at this point the PBX thread is already
4048  launched (was launched in the 'on call offered' handler) and therefore this callback
4049  is being executed already in the PBX thread rather than the monitor thread, don't launch
4050  any other thread, just disable the openr2 reading and answer the call if needed */
4051  if (!p->mfcr2_accept_on_offer) {
4052  openr2_chan_disable_read(r2chan);
4053  if (p->mfcr2_answer_pending) {
4054  ast_debug(1, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
4055  dahdi_r2_answer(p);
4056  }
4057  goto dahdi_r2_on_call_accepted_cleanup;
4058  }
4059  c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, NULL, callid);
4060  if (c) {
4061  /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
4062  library to forget about it */
4063  openr2_chan_disable_read(r2chan);
4064  goto dahdi_r2_on_call_accepted_cleanup;
4065  }
4066  ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
4067  /* failed to create the channel, bail out and report it as an out of order line */
4068  dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
4069  goto dahdi_r2_on_call_accepted_cleanup;
4070  }
4071  /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
4072  ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
4073  p->subs[SUB_REAL].needringing = 1;
4074  p->dialing = 0;
4075  /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
4076  openr2_chan_disable_read(r2chan);
4077 
4078 dahdi_r2_on_call_accepted_cleanup:
4079  ast_callid_threadstorage_auto_clean(callid, callid_created);
4080 }
4081 
4082 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
4083 {
4084  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4085  ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
4086  p->subs[SUB_REAL].needanswer = 1;
4087 }
4088 
4089 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
4090 {
4091  /*ast_debug(1, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
4092 }
4093 
4094 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
4095 {
4096  switch (cause) {
4097  case OR2_CAUSE_BUSY_NUMBER:
4098  return AST_CAUSE_BUSY;
4099  case OR2_CAUSE_NETWORK_CONGESTION:
4100  return AST_CAUSE_CONGESTION;
4101  case OR2_CAUSE_OUT_OF_ORDER:
4102  return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
4103  case OR2_CAUSE_UNALLOCATED_NUMBER:
4104  return AST_CAUSE_UNREGISTERED;
4105  case OR2_CAUSE_NO_ANSWER:
4106  return AST_CAUSE_NO_ANSWER;
4107  case OR2_CAUSE_NORMAL_CLEARING:
4108  return AST_CAUSE_NORMAL_CLEARING;
4109  case OR2_CAUSE_UNSPECIFIED:
4110  default:
4111  return AST_CAUSE_NOTDEFINED;
4112  }
4113 }
4114 
4115 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
4116 {
4117  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4118  char cause_str[50];
4119  struct ast_control_pvt_cause_code *cause_code;
4120  int datalen = sizeof(*cause_code);
4121 
4122  ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
4123  ast_mutex_lock(&p->lock);
4124  if (!p->owner) {
4125  ast_mutex_unlock(&p->lock);
4126  /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
4127  dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
4128  return;
4129  }
4130 
4131  snprintf(cause_str, sizeof(cause_str), "R2 DISCONNECT (%s)", openr2_proto_get_disconnect_string(cause));
4132  datalen += strlen(cause_str);
4133  cause_code = ast_alloca(datalen);
4134  memset(cause_code, 0, datalen);
4135  cause_code->ast_cause = dahdi_r2_cause_to_ast_cause(cause);
4136  ast_copy_string(cause_code->chan_name, ast_channel_name(p->owner), AST_CHANNEL_NAME);
4137  ast_copy_string(cause_code->code, cause_str, datalen + 1 - sizeof(*cause_code));
4138  ast_queue_control_data(p->owner, AST_CONTROL_PVT_CAUSE_CODE, cause_code, datalen);
4139  ast_channel_hangupcause_hash_set(p->owner, cause_code, datalen);
4140  ast_channel_hangupcause_set(p->owner, cause_code->ast_cause);
4141 
4142  /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
4143  be done in dahdi_hangup */
4144  if (ast_channel_state(p->owner) == AST_STATE_UP) {
4145  ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
4146  ast_mutex_unlock(&p->lock);
4147  } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
4148  /* being the forward side we must report what happened to the call to whoever requested it */
4149  switch (cause) {
4150  case OR2_CAUSE_BUSY_NUMBER:
4151  p->subs[SUB_REAL].needbusy = 1;
4152  break;
4153  case OR2_CAUSE_NETWORK_CONGESTION:
4154  case OR2_CAUSE_OUT_OF_ORDER:
4155  case OR2_CAUSE_UNALLOCATED_NUMBER:
4156  case OR2_CAUSE_NO_ANSWER:
4157  case OR2_CAUSE_UNSPECIFIED:
4158  case OR2_CAUSE_NORMAL_CLEARING:
4159  p->subs[SUB_REAL].needcongestion = 1;
4160  break;
4161  default:
4162  ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
4163  }
4164  ast_mutex_unlock(&p->lock);
4165  } else {
4166  ast_mutex_unlock(&p->lock);
4167  /* being the backward side and not UP yet, we only need to request hangup */
4168  /* TODO: what about doing this same thing when were AST_STATE_UP? */
4169  ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
4170  }
4171 }
4172 
4173 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
4174 {
4175  switch (level) {
4176  case OR2_LOG_NOTICE:
4177  ast_verbose("%s", logmessage);
4178  break;
4179  case OR2_LOG_WARNING:
4180  ast_log(LOG_WARNING, "%s", logmessage);
4181  break;
4182  case OR2_LOG_ERROR:
4183  ast_log(LOG_ERROR, "%s", logmessage);
4184  break;
4185  case OR2_LOG_STACK_TRACE:
4186  case OR2_LOG_MF_TRACE:
4187  case OR2_LOG_CAS_TRACE:
4188  case OR2_LOG_DEBUG:
4189  case OR2_LOG_EX_DEBUG:
4190  ast_debug(1, "%s", logmessage);
4191  break;
4192  default:
4193  ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
4194  ast_debug(1, "%s", logmessage);
4195  break;
4196  }
4197 }
4198 
4199 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
4200 {
4201  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4202  ast_mutex_lock(&p->lock);
4203  p->remotelyblocked = 1;
4204  ast_mutex_unlock(&p->lock);
4205  ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
4206 }
4207 
4208 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
4209 {
4210  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4211  ast_mutex_lock(&p->lock);
4212  p->remotelyblocked = 0;
4213  ast_mutex_unlock(&p->lock);
4214  ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
4215 }
4216 
4217 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
4218  __attribute__((format (printf, 3, 0)));
4219 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
4220 {
4221 #define CONTEXT_TAG "Context - "
4222  char logmsg[256];
4223  char completemsg[sizeof(logmsg) * 2];
4224  vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
4225  snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
4226  dahdi_r2_write_log(level, completemsg);
4227 #undef CONTEXT_TAG
4228 }
4229 
4230 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
4231  __attribute__((format (printf, 3, 0)));
4232 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
4233 {
4234 #define CHAN_TAG "Chan "
4235  char logmsg[256];
4236  char completemsg[sizeof(logmsg) * 2];
4237  vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
4238  snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
4239  dahdi_r2_write_log(level, completemsg);
4240 #undef CHAN_TAG
4241 }
4242 
4243 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
4244 {
4245  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4246  /* if 'immediate' is set, let's stop requesting DNIS */
4247  if (p->immediate) {
4248  return 0;
4249  }
4250  p->exten[p->mfcr2_dnis_index] = digit;
4251  p->rdnis[p->mfcr2_dnis_index] = digit;
4252  p->mfcr2_dnis_index++;
4253  p->exten[p->mfcr2_dnis_index] = 0;
4254  p->rdnis[p->mfcr2_dnis_index] = 0;
4255  /* if the DNIS is a match and cannot match more, stop requesting DNIS */
4256  if ((p->mfcr2_dnis_matched ||
4257  (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
4258  !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
4259  return 0;
4260  }
4261  /* otherwise keep going */
4262  return 1;
4263 }
4264 
4265 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
4266 {
4267  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4268  p->cid_num[p->mfcr2_ani_index] = digit;
4269  p->cid_name[p->mfcr2_ani_index] = digit;
4270  p->mfcr2_ani_index++;
4271  p->cid_num[p->mfcr2_ani_index] = 0;
4272  p->cid_name[p->mfcr2_ani_index] = 0;
4273 }
4274 
4275 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
4276 {
4277  ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
4278 }
4279 
4280 static openr2_event_interface_t dahdi_r2_event_iface = {
4281  .on_call_init = dahdi_r2_on_call_init,
4282  .on_call_offered = dahdi_r2_on_call_offered,
4283  .on_call_accepted = dahdi_r2_on_call_accepted,
4284  .on_call_answered = dahdi_r2_on_call_answered,
4285  .on_call_disconnect = dahdi_r2_on_call_disconnect,
4286  .on_call_end = dahdi_r2_on_call_end,
4287  .on_call_read = dahdi_r2_on_call_read,
4288  .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
4289  .on_os_error = dahdi_r2_on_os_error,
4290  .on_protocol_error = dahdi_r2_on_protocol_error,
4291  .on_line_blocked = dahdi_r2_on_line_blocked,
4292  .on_line_idle = dahdi_r2_on_line_idle,
4293  /* cast seems to be needed to get rid of the annoying warning regarding format attribute */
4294  .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
4295  .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
4296  .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
4297  /* so far we do nothing with billing pulses */
4298  .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
4299 };
4300 
4301 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
4302 {
4303  return AST_ALAW(sample);
4304 }
4305 
4306 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
4307 {
4308  return AST_LIN2A(sample);
4309 }
4310 
4311 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
4312  dahdi_r2_alaw_to_linear,
4313  dahdi_r2_linear_to_alaw
4314 };
4315 
4316 #endif /* HAVE_OPENR2 */
4317 
4318 static void swap_subs(struct dahdi_pvt *p, int a, int b)
4319 {
4320  int tchan;
4321  int tinthreeway;
4322  struct ast_channel *towner;
4323 
4324  ast_debug(1, "Swapping %d and %d\n", a, b);
4325 
4326  tchan = p->subs[a].chan;
4327  towner = p->subs[a].owner;
4328  tinthreeway = p->subs[a].inthreeway;
4329 
4330  p->subs[a].chan = p->subs[b].chan;
4331  p->subs[a].owner = p->subs[b].owner;
4332  p->subs[a].inthreeway = p->subs[b].inthreeway;
4333 
4334  p->subs[b].chan = tchan;
4335  p->subs[b].owner = towner;
4336  p->subs[b].inthreeway = tinthreeway;
4337 
4338  if (p->subs[a].owner)
4339  ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
4340  if (p->subs[b].owner)
4341  ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
4342  wakeup_sub(p, a);
4343  wakeup_sub(p, b);
4344 }
4345 
4346 static int dahdi_open(char *fn)
4347 {
4348  int fd;
4349  int isnum;
4350  int chan = 0;
4351  int bs;
4352  int x;
4353  isnum = 1;
4354  for (x = 0; x < strlen(fn); x++) {
4355  if (!isdigit(fn[x])) {
4356  isnum = 0;
4357  break;
4358  }
4359  }
4360  if (isnum) {
4361  chan = atoi(fn);
4362  if (chan < 1) {
4363  ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
4364  return -1;
4365  }
4366  fn = "/dev/dahdi/channel";
4367  }
4368  fd = open(fn, O_RDWR | O_NONBLOCK);
4369  if (fd < 0) {
4370  ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
4371  return -1;
4372  }
4373  if (chan) {
4374  if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
4375  x = errno;
4376  close(fd);
4377  errno = x;
4378  ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
4379  return -1;
4380  }
4381  }
4382  bs = READ_SIZE;
4383  if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
4384  ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
4385  x = errno;
4386  close(fd);
4387  errno = x;
4388  return -1;
4389  }
4390  return fd;
4391 }
4392 
4393 static void dahdi_close(int fd)
4394 {
4395  if (fd > 0)
4396  close(fd);
4397 }
4398 
4399 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
4400 {
4401  dahdi_close(chan_pvt->subs[sub_num].dfd);
4402  chan_pvt->subs[sub_num].dfd = -1;
4403 }
4404 
4405 #if defined(HAVE_PRI)
4406 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
4407 {
4408  dahdi_close(pri->pri.fds[fd_num]);
4409  pri->pri.fds[fd_num] = -1;
4410 }
4411 #endif /* defined(HAVE_PRI) */
4412 
4413 #if defined(HAVE_SS7)
4414 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
4415 {
4416  dahdi_close(ss7->ss7.fds[fd_num]);
4417  ss7->ss7.fds[fd_num] = -1;
4418 }
4419 #endif /* defined(HAVE_SS7) */
4420 
4421 static int dahdi_setlinear(int dfd, int linear)
4422 {
4423  return ioctl(dfd, DAHDI_SETLINEAR, &linear);
4424 }
4425 
4426 
4427 static int alloc_sub(struct dahdi_pvt *p, int x)
4428 {
4429  struct dahdi_bufferinfo bi;
4430  int res;
4431  if (p->subs[x].dfd >= 0) {
4432  ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
4433  return -1;
4434  }
4435 
4436  p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
4437  if (p->subs[x].dfd <= -1) {
4438  ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
4439  return -1;
4440  }
4441 
4442  res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
4443  if (!res) {
4444  bi.txbufpolicy = p->buf_policy;
4445  bi.rxbufpolicy = p->buf_policy;
4446  bi.numbufs = p->buf_no;
4447  res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
4448  if (res < 0) {
4449  ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
4450  }
4451  } else
4452  ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
4453 
4454  if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
4455  ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
4456  dahdi_close_sub(p, x);
4457  p->subs[x].dfd = -1;
4458  return -1;
4459  }
4460  ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
4461  return 0;
4462 }
4463 
4464 static int unalloc_sub(struct dahdi_pvt *p, int x)
4465 {
4466  if (!x) {
4467  ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
4468  return -1;
4469  }
4470  ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
4471  dahdi_close_sub(p, x);
4472  p->subs[x].linear = 0;
4473  p->subs[x].chan = 0;
4474  p->subs[x].owner = NULL;
4475  p->subs[x].inthreeway = 0;
4476  p->polarity = POLARITY_IDLE;
4477  memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
4478  return 0;
4479 }
4480 
4481 static int digit_to_dtmfindex(char digit)
4482 {
4483  if (isdigit(digit))
4484  return DAHDI_TONE_DTMF_BASE + (digit - '0');
4485  else if (digit >= 'A' && digit <= 'D')
4486  return DAHDI_TONE_DTMF_A + (digit - 'A');
4487  else if (digit >= 'a' && digit <= 'd')
4488  return DAHDI_TONE_DTMF_A + (digit - 'a');
4489  else if (digit == '*')
4490  return DAHDI_TONE_DTMF_s;
4491  else if (digit == '#')
4492  return DAHDI_TONE_DTMF_p;
4493  else
4494  return -1;
4495 }
4496 
4497 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
4498 {
4499  struct dahdi_pvt *pvt;
4500  int idx;
4501  int dtmf;
4502  int res;
4503 
4504  pvt = ast_channel_tech_pvt(chan);
4505 
4506  ast_mutex_lock(&pvt->lock);
4507 
4508  idx = dahdi_get_index(chan, pvt, 0);
4509 
4510  if ((idx != SUB_REAL) || !pvt->owner)
4511  goto out;
4512 
4513 #ifdef HAVE_PRI
4514  switch (pvt->sig) {
4515  case SIG_PRI_LIB_HANDLE_CASES:
4516  res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
4517  if (!res)
4518  goto out;
4519  break;
4520  default:
4521  break;
4522  }
4523 #endif
4524  dtmf = digit_to_dtmfindex(digit);
4525  if (dtmf == -1) {
4526  /* Not a valid DTMF digit */
4527  goto out;
4528  }
4529 
4530  if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
4531  char dial_str[] = { 'T', digit, '\0' };
4532 
4533  res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
4534  if (!res) {
4535  pvt->dialing = 1;
4536  }
4537  } else {
4538  pvt->dialing = 1;
4539  pvt->begindigit = digit;
4540 
4541  /* Flush the write buffer in DAHDI to start sending the digit immediately. */
4542  dtmf = DAHDI_FLUSH_WRITE;
4543  res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &dtmf);
4544  if (res) {
4545  ast_log(LOG_WARNING, "Unable to flush the DAHDI write buffer to send DTMF on channel %d: %s\n",
4546  pvt->channel, strerror(errno));
4547  }
4548 
4549  ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
4550  ast_channel_name(chan), digit);
4551  }
4552 
4553 out:
4554  ast_mutex_unlock(&pvt->lock);
4555 
4556  return 0;
4557 }
4558 
4559 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
4560 {
4561  struct dahdi_pvt *pvt;
4562  int res = 0;
4563  int idx;
4564  int x;
4565 
4566  pvt = ast_channel_tech_pvt(chan);
4567 
4568  ast_mutex_lock(&pvt->lock);
4569 
4570  idx = dahdi_get_index(chan, pvt, 0);
4571 
4572  if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
4573  goto out;
4574 
4575 #ifdef HAVE_PRI
4576  /* This means that the digit was already sent via PRI signalling */
4577  if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
4578  goto out;
4579  }
4580 #endif
4581 
4582  if (pvt->begindigit) {
4583  x = -1;
4584  ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
4585  ast_channel_name(chan), digit);
4586  res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
4587  pvt->dialing = 0;
4588  pvt->begindigit = 0;
4589  }
4590 
4591 out:
4592  ast_mutex_unlock(&pvt->lock);
4593 
4594  return res;
4595 }
4596 
4597 static const char * const events[] = {
4598  "No event",
4599  "On hook",
4600  "Ring/Answered",
4601  "Wink/Flash",
4602  "Alarm",
4603  "No more alarm",
4604  "HDLC Abort",
4605  "HDLC Overrun",
4606  "HDLC Bad FCS",
4607  "Dial Complete",
4608  "Ringer On",
4609  "Ringer Off",
4610  "Hook Transition Complete",
4611  "Bits Changed",
4612  "Pulse Start",
4613  "Timer Expired",
4614  "Timer Ping",
4615  "Polarity Reversal",
4616  "Ring Begin",
4617 };
4618 
4619 static struct {
4620  int alarm;
4621  char *name;
4622 } alarms[] = {
4623  { DAHDI_ALARM_RED, "Red Alarm" },
4624  { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
4625  { DAHDI_ALARM_BLUE, "Blue Alarm" },
4626  { DAHDI_ALARM_RECOVER, "Recovering" },
4627  { DAHDI_ALARM_LOOPBACK, "Loopback" },
4628  { DAHDI_ALARM_NOTOPEN, "Not Open" },
4629  { DAHDI_ALARM_NONE, "None" },
4630 };
4631 
4632 static char *alarm2str(int alm)
4633 {
4634  int x;
4635  for (x = 0; x < ARRAY_LEN(alarms); x++) {
4636  if (alarms[x].alarm & alm)
4637  return alarms[x].name;
4638  }
4639  return alm ? "Unknown Alarm" : "No Alarm";
4640 }
4641 
4642 static const char *event2str(int event)
4643 {
4644  static char buf[256];
4645  if ((event > -1) && (event < (ARRAY_LEN(events))) )
4646  return events[event];
4647  sprintf(buf, "Event %d", event); /* safe */
4648  return buf;
4649 }
4650 
4651 static char *dahdi_sig2str(int sig)
4652 {
4653  static char buf[256];
4654  switch (sig) {
4655  case SIG_EM:
4656  return "E & M Immediate";
4657  case SIG_EMWINK:
4658  return "E & M Wink";
4659  case SIG_EM_E1:
4660  return "E & M E1";
4661  case SIG_FEATD:
4662  return "Feature Group D (DTMF)";
4663  case SIG_FEATDMF:
4664  return "Feature Group D (MF)";
4665  case SIG_FEATDMF_TA:
4666  return "Feature Group D (MF) Tandem Access";
4667  case SIG_FEATB:
4668  return "Feature Group B (MF)";
4669  case SIG_E911:
4670  return "E911 (MF)";
4671  case SIG_FGC_CAMA:
4672  return "FGC/CAMA (Dialpulse)";
4673  case SIG_FGC_CAMAMF:
4674  return "FGC/CAMA (MF)";
4675  case SIG_FXSLS:
4676  return "FXS Loopstart";
4677  case SIG_FXSGS:
4678  return "FXS Groundstart";
4679  case SIG_FXSKS:
4680  return "FXS Kewlstart";
4681  case SIG_FXOLS:
4682  return "FXO Loopstart";
4683  case SIG_FXOGS:
4684  return "FXO Groundstart";
4685  case SIG_FXOKS:
4686  return "FXO Kewlstart";
4687  case SIG_PRI:
4688  return "ISDN PRI";
4689  case SIG_BRI:
4690  return "ISDN BRI Point to Point";
4691  case SIG_BRI_PTMP:
4692  return "ISDN BRI Point to MultiPoint";
4693  case SIG_SS7:
4694  return "SS7";
4695  case SIG_MFCR2:
4696  return "MFC/R2";
4697  case SIG_SF:
4698  return "SF (Tone) Immediate";
4699  case SIG_SFWINK:
4700  return "SF (Tone) Wink";
4701  case SIG_SF_FEATD:
4702  return "SF (Tone) with Feature Group D (DTMF)";
4703  case SIG_SF_FEATDMF:
4704  return "SF (Tone) with Feature Group D (MF)";
4705  case SIG_SF_FEATB:
4706  return "SF (Tone) with Feature Group B (MF)";
4707  case 0:
4708  return "Pseudo";
4709  default:
4710  snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
4711  return buf;
4712  }
4713 }
4714 
4715 #define sig2str dahdi_sig2str
4716 
4717 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
4718 {
4719  /* If the conference already exists, and we're already in it
4720  don't bother doing anything */
4721  struct dahdi_confinfo zi;
4722 
4723  memset(&zi, 0, sizeof(zi));
4724  zi.chan = 0;
4725 
4726  if (slavechannel > 0) {
4727  /* If we have only one slave, do a digital mon */
4728  zi.confmode = DAHDI_CONF_DIGITALMON;
4729  zi.confno = slavechannel;
4730  } else {
4731  if (!idx) {
4732  /* Real-side and pseudo-side both participate in conference */
4733  zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
4734  DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
4735  } else
4736  zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
4737  zi.confno = p->confno;
4738  }
4739  if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
4740  return 0;
4741  if (c->dfd < 0)
4742  return 0;
4743  if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4744  ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
4745  return -1;
4746  }
4747  if (slavechannel < 1) {
4748  p->confno = zi.confno;
4749  }
4750  c->curconf = zi;
4751  ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4752  return 0;
4753 }
4754 
4755 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
4756 {
4757  /* If they're listening to our channel, they're ours */
4758  if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
4759  return 1;
4760  /* If they're a talker on our (allocated) conference, they're ours */
4761  if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
4762  return 1;
4763  return 0;
4764 }
4765 
4766 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
4767 {
4768  struct dahdi_confinfo zi;
4769  if (/* Can't delete if there's no dfd */
4770  (c->dfd < 0) ||
4771  /* Don't delete from the conference if it's not our conference */
4772  !isourconf(p, c)
4773  /* Don't delete if we don't think it's conferenced at all (implied) */
4774  ) return 0;
4775  memset(&zi, 0, sizeof(zi));
4776  if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4777  ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
4778  return -1;
4779  }
4780  ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4781  memcpy(&c->curconf, &zi, sizeof(c->curconf));
4782  return 0;
4783 }
4784 
4785 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
4786 {
4787  int x;
4788  int useslavenative;
4789  struct dahdi_pvt *slave = NULL;
4790  /* Start out optimistic */
4791  useslavenative = 1;
4792  /* Update conference state in a stateless fashion */
4793  for (x = 0; x < 3; x++) {
4794  /* Any three-way calling makes slave native mode *definitely* out
4795  of the question */
4796  if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
4797  useslavenative = 0;
4798  }
4799  /* If we don't have any 3-way calls, check to see if we have
4800  precisely one slave */
4801  if (useslavenative) {
4802  for (x = 0; x < MAX_SLAVES; x++) {
4803  if (p->slaves[x]) {
4804  if (slave) {
4805  /* Whoops already have a slave! No
4806  slave native and stop right away */
4807  slave = NULL;
4808  useslavenative = 0;
4809  break;
4810  } else {
4811  /* We have one slave so far */
4812  slave = p->slaves[x];
4813  }
4814  }
4815  }
4816  }
4817  /* If no slave, slave native definitely out */
4818  if (!slave)
4819  useslavenative = 0;
4820  else if (slave->law != p->law) {
4821  useslavenative = 0;
4822  slave = NULL;
4823  }
4824  if (out)
4825  *out = slave;
4826  return useslavenative;
4827 }
4828 
4829 static int reset_conf(struct dahdi_pvt *p)
4830 {
4831  p->confno = -1;
4832  memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
4833  if (p->subs[SUB_REAL].dfd > -1) {
4834  struct dahdi_confinfo zi;
4835 
4836  memset(&zi, 0, sizeof(zi));
4837  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
4838  ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
4839  }
4840  return 0;
4841 }
4842 
4843 void dahdi_conf_update(struct dahdi_pvt *p)
4844 {
4845  int needconf = 0;
4846  int x;
4847  int useslavenative;
4848  struct dahdi_pvt *slave = NULL;
4849 
4850  useslavenative = isslavenative(p, &slave);
4851  /* Start with the obvious, general stuff */
4852  for (x = 0; x < 3; x++) {
4853  /* Look for three way calls */
4854  if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
4855  conf_add(p, &p->subs[x], x, 0);
4856  needconf++;
4857  } else {
4858  conf_del(p, &p->subs[x], x);
4859  }
4860  }
4861  /* If we have a slave, add him to our conference now. or DAX
4862  if this is slave native */
4863  for (x = 0; x < MAX_SLAVES; x++) {
4864  if (p->slaves[x]) {
4865  if (useslavenative)
4866  conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
4867  else {
4868  conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
4869  needconf++;
4870  }
4871  }
4872  }
4873  /* If we're supposed to be in there, do so now */
4874  if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
4875  if (useslavenative)
4876  conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
4877  else {
4878  conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
4879  needconf++;
4880  }
4881  }
4882  /* If we have a master, add ourselves to his conference */
4883  if (p->master) {
4884  if (isslavenative(p->master, NULL)) {
4885  conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
4886  } else {
4887  conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
4888  }
4889  }
4890  if (!needconf) {
4891  /* Nobody is left (or should be left) in our conference.
4892  Kill it. */
4893  p->confno = -1;
4894  }
4895  ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
4896 }
4897 
4898 void dahdi_ec_enable(struct dahdi_pvt *p)
4899 {
4900  int res;
4901  if (!p)
4902  return;
4903  if (p->echocanon) {
4904  ast_debug(1, "Echo cancellation already on\n");
4905  return;
4906  }
4907  if (p->digital) {
4908  ast_debug(1, "Echo cancellation isn't required on digital connection\n");
4909  return;
4910  }
4911  if (p->echocancel.head.tap_length) {
4912 #if defined(HAVE_PRI) || defined(HAVE_SS7)
4913  switch (p->sig) {
4914 #if defined(HAVE_PRI)
4915  case SIG_PRI_LIB_HANDLE_CASES:
4916  if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
4917  /*
4918  * PRI nobch pseudo channel. Does not need ec anyway.
4919  * Does not handle ioctl(DAHDI_AUDIOMODE)
4920  */
4921  return;
4922  }
4923  /* Fall through */
4924 #endif /* defined(HAVE_PRI) */
4925 #if defined(HAVE_SS7)
4926  case SIG_SS7:
4927 #endif /* defined(HAVE_SS7) */
4928  {
4929  int x = 1;
4930 
4931  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
4932  if (res)
4933  ast_log(LOG_WARNING,
4934  "Unable to enable audio mode on channel %d (%s)\n",
4935  p->channel, strerror(errno));
4936  }
4937  break;
4938  default:
4939  break;
4940  }
4941 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
4942  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
4943  if (res) {
4944  ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
4945  } else {
4946  p->echocanon = 1;
4947  ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
4948  }
4949  } else
4950  ast_debug(1, "No echo cancellation requested\n");
4951 }
4952 
4953 static void dahdi_train_ec(struct dahdi_pvt *p)
4954 {
4955  int x;
4956  int res;
4957 
4958  if (p && p->echocanon && p->echotraining) {
4959  x = p->echotraining;
4960  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
4961  if (res)
4962  ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
4963  else
4964  ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
4965  } else {
4966  ast_debug(1, "No echo training requested\n");
4967  }
4968 }
4969 
4970 void dahdi_ec_disable(struct dahdi_pvt *p)
4971 {
4972  int res;
4973 
4974  if (p->echocanon) {
4975  struct dahdi_echocanparams ecp = { .tap_length = 0 };
4976 
4977  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
4978 
4979  if (res)
4980  ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
4981  else
4982  ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
4983  }
4984 
4985  p->echocanon = 0;
4986 }
4987 
4988 static int set_hwgain(int fd, float gain, int tx_direction)
4989 {
4990  struct dahdi_hwgain hwgain;
4991 
4992  hwgain.newgain = gain * 10.0;
4993  hwgain.tx = tx_direction;
4994  return ioctl(fd, DAHDI_SET_HWGAIN, &hwgain) < 0;
4995 }
4996 
4997 /* perform a dynamic range compression transform on the given sample */
4998 static int drc_sample(int sample, float drc)
4999 {
5000  float neg;
5001  float shallow, steep;
5002  float max = SHRT_MAX;
5003 
5004  neg = (sample < 0 ? -1 : 1);
5005  steep = drc*sample;
5006  shallow = neg*(max-max/drc)+(float)sample/drc;
5007  if (fabsf(steep) < fabsf(shallow)) {
5008  sample = steep;
5009  }
5010  else {
5011  sample = shallow;
5012  }
5013 
5014  return sample;
5015 }
5016 
5017 
5018 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
5019 {
5020  int j;
5021  int k;
5022 
5023  float linear_gain = pow(10.0, gain / 20.0);
5024 
5025  switch (law) {
5026  case DAHDI_LAW_ALAW:
5027  for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
5028  if (gain || drc) {
5029  k = AST_ALAW(j);
5030  if (drc) {
5031  k = drc_sample(k, drc);
5032  }
5033  k = (float)k * linear_gain;
5034  if (k > 32767) {
5035  k = 32767;
5036  } else if (k < -32768) {
5037  k = -32768;
5038  }
5039  g->txgain[j] = AST_LIN2A(k);
5040  } else {
5041  g->txgain[j] = j;
5042  }
5043  }
5044  break;
5045  case DAHDI_LAW_MULAW:
5046  for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
5047  if (gain || drc) {
5048  k = AST_MULAW(j);
5049  if (drc) {
5050  k = drc_sample(k, drc);
5051  }
5052  k = (float)k * linear_gain;
5053  if (k > 32767) {
5054  k = 32767;
5055  } else if (k < -32768) {
5056  k = -32768;
5057  }
5058  g->txgain[j] = AST_LIN2MU(k);
5059 
5060  } else {
5061  g->txgain[j] = j;
5062  }
5063  }
5064  break;
5065  }
5066 }
5067 
5068 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
5069 {
5070  int j;
5071  int k;
5072  float linear_gain = pow(10.0, gain / 20.0);
5073 
5074  switch (law) {
5075  case DAHDI_LAW_ALAW:
5076  for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
5077  if (gain || drc) {
5078  k = AST_ALAW(j);
5079  if (drc) {
5080  k = drc_sample(k, drc);
5081  }
5082  k = (float)k * linear_gain;
5083  if (k > 32767) {
5084  k = 32767;
5085  } else if (k < -32768) {
5086  k = -32768;
5087  }
5088  g->rxgain[j] = AST_LIN2A(k);
5089  } else {
5090  g->rxgain[j] = j;
5091  }
5092  }
5093  break;
5094  case DAHDI_LAW_MULAW:
5095  for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
5096  if (gain || drc) {
5097  k = AST_MULAW(j);
5098  if (drc) {
5099  k = drc_sample(k, drc);
5100  }
5101  k = (float)k * linear_gain;
5102  if (k > 32767) {
5103  k = 32767;
5104  } else if (k < -32768) {
5105  k = -32768;
5106  }
5107  g->rxgain[j] = AST_LIN2MU(k);
5108  } else {
5109  g->rxgain[j] = j;
5110  }
5111  }
5112  break;
5113  }
5114 }
5115 
5116 static int set_actual_txgain(int fd, float gain, float drc, int law)
5117 {
5118  struct dahdi_gains g;
5119  int res;
5120 
5121  memset(&g, 0, sizeof(g));
5122  res = ioctl(fd, DAHDI_GETGAINS, &g);
5123  if (res) {
5124  ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
5125  return res;
5126  }
5127 
5128  fill_txgain(&g, gain, drc, law);
5129 
5130  return ioctl(fd, DAHDI_SETGAINS, &g);
5131 }
5132 
5133 static int set_actual_rxgain(int fd, float gain, float drc, int law)
5134 {
5135  struct dahdi_gains g;
5136  int res;
5137 
5138  memset(&g, 0, sizeof(g));
5139  res = ioctl(fd, DAHDI_GETGAINS, &g);
5140  if (res) {
5141  ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
5142  return res;
5143  }
5144 
5145  fill_rxgain(&g, gain, drc, law);
5146 
5147  return ioctl(fd, DAHDI_SETGAINS, &g);
5148 }
5149 
5150 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
5151 {
5152  return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
5153 }
5154 
5155 static int bump_gains(struct dahdi_pvt *p)
5156 {
5157  int res;
5158 
5159  /* Bump receive gain by value stored in cid_rxgain */
5160  res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5161  if (res) {
5162  ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
5163  return -1;
5164  }
5165 
5166  return 0;
5167 }
5168 
5169 static int restore_gains(struct dahdi_pvt *p)
5170 {
5171  int res;
5172 
5173  res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5174  if (res) {
5175  ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
5176  return -1;
5177  }
5178 
5179  return 0;
5180 }
5181 
5182 static inline int dahdi_set_hook(int fd, int hs)
5183 {
5184  int x, res;
5185 
5186  x = hs;
5187  res = ioctl(fd, DAHDI_HOOK, &x);
5188 
5189  if (res < 0) {
5190  if (errno == EINPROGRESS)
5191  return 0;
5192  ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
5193  /* will expectedly fail if phone is off hook during operation, such as during a restart */
5194  }
5195 
5196  return res;
5197 }
5198 
5199 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
5200 {
5201  int x, res;
5202 
5203  x = muted;
5204 #if defined(HAVE_PRI) || defined(HAVE_SS7)
5205  switch (p->sig) {
5206 #if defined(HAVE_PRI)
5207  case SIG_PRI_LIB_HANDLE_CASES:
5208  if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
5209  /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
5210  break;
5211  }
5212  /* Fall through */
5213 #endif /* defined(HAVE_PRI) */
5214 #if defined(HAVE_SS7)
5215  case SIG_SS7:
5216 #endif /* defined(HAVE_SS7) */
5217  {
5218  int y = 1;
5219 
5220  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
5221  if (res)
5222  ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
5223  p->channel, strerror(errno));
5224  }
5225  break;
5226  default:
5227  break;
5228  }
5229 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
5230  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
5231  if (res < 0)
5232  ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
5233  return res;
5234 }
5235 
5236 static int save_conference(struct dahdi_pvt *p)
5237 {
5238  struct dahdi_confinfo c;
5239  int res;
5240  if (p->saveconf.confmode) {
5241  ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
5242  return -1;
5243  }
5244  p->saveconf.chan = 0;
5245  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
5246  if (res) {
5247  ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
5248  p->saveconf.confmode = 0;
5249  return -1;
5250  }
5251  memset(&c, 0, sizeof(c));
5252  c.confmode = DAHDI_CONF_NORMAL;
5253  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
5254  if (res) {
5255  ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
5256  return -1;
5257  }
5258  ast_debug(1, "Disabled conferencing\n");
5259  return 0;
5260 }
5261 
5262 static int restore_conference(struct dahdi_pvt *p)
5263 {
5264  int res;
5265  if (p->saveconf.confmode) {
5266  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
5267  p->saveconf.confmode = 0;
5268  if (res) {
5269  ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
5270  return -1;
5271  }
5272  ast_debug(1, "Restored conferencing\n");
5273  }
5274  return 0;
5275 }
5276 
5277 static int send_cwcidspill(struct dahdi_pvt *p)
5278 {
5279  p->callwaitcas = 0;
5280  p->cidcwexpire = 0;
5281  p->cid_suppress_expire = 0;
5282  if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
5283  return -1;
5285  /* Make sure we account for the end */
5286  p->cidlen += READ_SIZE * 4;
5287  p->cidpos = 0;
5288  send_callerid(p);
5289  ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
5290  return 0;
5291 }
5292 
5293 static int has_voicemail(struct dahdi_pvt *p)
5294 {
5295  int new_msgs;
5296  RAII_VAR(struct stasis_message *, mwi_message, NULL, ao2_cleanup);
5297 
5298  /* A manual MWI disposition has been requested, use that instead
5299  * if this is for sending the new MWI indication. */
5300  if (p->mwioverride_active) {
5301  /* We don't clear p->mwioverride_active automatically,
5302  * because otherwise do_monitor would just change it back to the way it was.
5303  * We need to keep the override active until explicitly disabled by the user,
5304  * so that we can keep returning the correct answer in subsequent calls to do_monitor. */
5305  ast_debug(6, "MWI manual override active on channel %d: pretending that it should be %s\n",
5306  p->channel, p->mwioverride_disposition ? "active" : "inactive");
5307  return p->mwioverride_disposition;
5308  }
5309 
5311  if (mwi_message) {
5312  struct ast_mwi_state *mwi_state = stasis_message_data(mwi_message);
5313  new_msgs = mwi_state->new_msgs;
5314  } else {
5315  new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
5316  }
5317 
5318  return new_msgs;
5319 }
5320 
5321 
5322 
5323 static int send_callerid(struct dahdi_pvt *p)
5324 {
5325  /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
5326  int res;
5327  /* Take out of linear mode if necessary */
5328  if (p->subs[SUB_REAL].linear) {
5329  p->subs[SUB_REAL].linear = 0;
5330  dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
5331  }
5332  while (p->cidpos < p->cidlen) {
5333  res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
5334  ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
5335  if (res < 0) {
5336  if (errno == EAGAIN)
5337  return 0;
5338  else {
5339  ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
5340  return -1;
5341  }
5342  }
5343  if (!res)
5344  return 0;
5345  p->cidpos += res;
5346  }
5348  ast_free(p->cidspill);
5349  p->cidspill = NULL;
5350  if (p->callwaitcas) {
5351  /* Wait for CID/CW to expire */
5354  } else
5355  restore_conference(p);
5356  return 0;
5357 }
5358 
5359 static int dahdi_callwait(struct ast_channel *ast)
5360 {
5361  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5362 
5364  if (p->cidspill) {
5365  ast_log(LOG_WARNING, "Spill already exists?!?\n");
5366  ast_free(p->cidspill);
5367  }
5368 
5369  /*
5370  * SAS: Subscriber Alert Signal, 440Hz for 300ms
5371  * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
5372  */
5373  if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
5374  return -1;
5375  save_conference(p);
5376  /* Silence */
5377  memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
5378  if (!p->callwaitrings && p->callwaitingcallerid) {
5379  ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
5380  p->callwaitcas = 1;
5381  p->cidlen = 2400 + 680 + READ_SIZE * 4;
5382  } else {
5383  ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
5384  p->callwaitcas = 0;
5385  p->cidlen = 2400 + READ_SIZE * 4;
5386  }
5387  p->cidpos = 0;
5388  send_callerid(p);
5389 
5390  return 0;
5391 }
5392 
5393 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout)
5394 {
5395  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5396  int x, res, mysig;
5397  char *dest;
5398  AST_DECLARE_APP_ARGS(args,
5399  AST_APP_ARG(group); /* channel/group token */
5400  AST_APP_ARG(ext); /* extension token */
5401  //AST_APP_ARG(opts); /* options token */
5402  AST_APP_ARG(other); /* Any remining unused arguments */
5403  );
5404 
5405  ast_mutex_lock(&p->lock);
5406  ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
5407 
5408  /* Split the dialstring */
5409  dest = ast_strdupa(rdest);
5410  AST_NONSTANDARD_APP_ARGS(args, dest, '/');
5411  if (!args.ext) {
5412  args.ext = "";
5413  }
5414 
5415 #if defined(HAVE_PRI)
5416  if (dahdi_sig_pri_lib_handles(p->sig)) {
5417  char *subaddr;
5418 
5419  sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
5420 
5421  /* Remove any subaddress for uniformity with incoming calls. */
5422  subaddr = strchr(p->exten, ':');
5423  if (subaddr) {
5424  *subaddr = '\0';
5425  }
5426  } else
5427 #endif /* defined(HAVE_PRI) */
5428  {
5429  ast_copy_string(p->exten, args.ext, sizeof(p->exten));
5430  }
5431 
5432  if ((ast_channel_state(ast) == AST_STATE_BUSY)) {
5433  p->subs[SUB_REAL].needbusy = 1;
5434  ast_mutex_unlock(&p->lock);
5435  return 0;
5436  }
5438  ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
5439  ast_mutex_unlock(&p->lock);
5440  return -1;
5441  }
5442  p->waitingfordt.tv_sec = 0;
5443  p->dialednone = 0;
5444  if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
5445  {
5446  /* Special pseudo -- automatically up */
5447  ast_setstate(ast, AST_STATE_UP);
5448  ast_mutex_unlock(&p->lock);
5449  return 0;
5450  }
5451  x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
5452  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
5453  if (res)
5454  ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
5455  p->outgoing = 1;
5456 
5457  if (IS_DIGITAL(ast_channel_transfercapability(ast))){
5458  set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
5459  } else {
5460  set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5461  }
5462 
5463 #ifdef HAVE_PRI
5464  if (dahdi_sig_pri_lib_handles(p->sig)) {
5465  res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
5466  (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
5467  ast_mutex_unlock(&p->lock);
5468  return res;
5469  }
5470 #endif
5471 
5472 #if defined(HAVE_SS7)
5473  if (p->sig == SIG_SS7) {
5474  res = sig_ss7_call(p->sig_pvt, ast, rdest);
5475  ast_mutex_unlock(&p->lock);
5476  return res;
5477  }
5478 #endif /* defined(HAVE_SS7) */
5479 
5480  /* If this is analog signalling we can exit here */
5481  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
5482  p->callwaitrings = 0;
5483  res = analog_call(p->sig_pvt, ast, rdest, timeout);
5484  ast_mutex_unlock(&p->lock);
5485  return res;
5486  }
5487 
5488  mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
5489  switch (mysig) {
5490  case 0:
5491  /* Special pseudo -- automatically up*/
5492  ast_setstate(ast, AST_STATE_UP);
5493  break;
5494  case SIG_MFCR2:
5495  break;
5496  default:
5497  ast_debug(1, "not yet implemented\n");
5498  ast_mutex_unlock(&p->lock);
5499  return -1;
5500  }
5501 
5502 #ifdef HAVE_OPENR2
5503  if (p->mfcr2) {
5504  openr2_calling_party_category_t chancat;
5505  int callres = 0;
5506  char *c, *l;
5507 
5508  /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
5509  p->dialdest[0] = '\0';
5510 
5511  c = args.ext;
5512  if (!p->hidecallerid) {
5513  l = ast_channel_connected(ast)->id.number.valid ? ast_channel_connected(ast)->id.number.str : NULL;
5514  } else {
5515  l = NULL;
5516  }
5517  if (strlen(c) < p->stripmsd) {
5518  ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
5519  ast_mutex_unlock(&p->lock);
5520  return -1;
5521  }
5522  p->dialing = 1;
5523  chancat = dahdi_r2_get_channel_category(ast);
5524  callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
5525  if (-1 == callres) {
5526  ast_mutex_unlock(&p->lock);
5527  ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
5528  return -1;
5529  }
5530  p->mfcr2_call_accepted = 0;
5531  p->mfcr2_progress_sent = 0;
5533  }
5534 #endif /* HAVE_OPENR2 */
5535  ast_mutex_unlock(&p->lock);
5536  return 0;
5537 }
5538 
5539 /*!
5540  * \internal
5541  * \brief Insert the given chan_dahdi interface structure into the interface list.
5542  * \since 1.8
5543  *
5544  * \param pvt chan_dahdi private interface structure to insert.
5545  *
5546  * \details
5547  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
5548  * Any duplicates are inserted after the existing entries.
5549  *
5550  * \note The new interface must not already be in the list.
5551  */
5552 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
5553 {
5554  struct dahdi_pvt *cur;
5555 
5557 
5558  /* Find place in middle of list for the new interface. */
5559  for (cur = iflist; cur; cur = cur->next) {
5560  if (pvt->channel < cur->channel) {
5561  /* New interface goes before the current interface. */
5562  pvt->prev = cur->prev;
5563  pvt->next = cur;
5564  if (cur->prev) {
5565  /* Insert into the middle of the list. */
5566  cur->prev->next = pvt;
5567  } else {
5568  /* Insert at head of list. */
5569  iflist = pvt;
5570  }
5571  cur->prev = pvt;
5572  return;
5573  }
5574  }
5575 
5576  /* New interface goes onto the end of the list */
5577  pvt->prev = ifend;
5578  pvt->next = NULL;
5579  if (ifend) {
5580  ifend->next = pvt;
5581  }
5582  ifend = pvt;
5583  if (!iflist) {
5584  /* List was empty */
5585  iflist = pvt;
5586  }
5587 }
5588 
5589 /*!
5590  * \internal
5591  * \brief Extract the given chan_dahdi interface structure from the interface list.
5592  * \since 1.8
5593  *
5594  * \param pvt chan_dahdi private interface structure to extract.
5595  *
5596  * \note
5597  * The given interface structure can be either in the interface list or a stand alone
5598  * structure that has not been put in the list if the next and prev pointers are NULL.
5599  */
5600 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
5601 {
5602  /* Extract from the forward chain. */
5603  if (pvt->prev) {
5604  pvt->prev->next = pvt->next;
5605  } else if (iflist == pvt) {
5606  /* Node is at the head of the list. */
5607  iflist = pvt->next;
5608  }
5609 
5610  /* Extract from the reverse chain. */
5611  if (pvt->next) {
5612  pvt->next->prev = pvt->prev;
5613  } else if (ifend == pvt) {
5614  /* Node is at the end of the list. */
5615  ifend = pvt->prev;
5616  }
5617 
5618  /* Node is no longer in the list. */
5620  pvt->prev = NULL;
5621  pvt->next = NULL;
5622 }
5623 
5624 #if defined(HAVE_PRI)
5625 /*!
5626  * \internal
5627  * \brief Insert the given chan_dahdi interface structure into the no B channel list.
5628  * \since 1.8
5629  *
5630  * \param pri sig_pri span control structure holding no B channel list.
5631  * \param pvt chan_dahdi private interface structure to insert.
5632  *
5633  * \details
5634  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
5635  * Any duplicates are inserted after the existing entries.
5636  *
5637  * \note The new interface must not already be in the list.
5638  */
5639 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
5640 {
5641  struct dahdi_pvt *cur;
5642 
5644 
5645  /* Find place in middle of list for the new interface. */
5646  for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
5647  if (pvt->channel < cur->channel) {
5648  /* New interface goes before the current interface. */
5649  pvt->prev = cur->prev;
5650  pvt->next = cur;
5651  if (cur->prev) {
5652  /* Insert into the middle of the list. */
5653  cur->prev->next = pvt;
5654  } else {
5655  /* Insert at head of list. */
5656  pri->no_b_chan_iflist = pvt;
5657  }
5658  cur->prev = pvt;
5659  return;
5660  }
5661  }
5662 
5663  /* New interface goes onto the end of the list */
5664  pvt->prev = pri->no_b_chan_end;
5665  pvt->next = NULL;
5666  if (pri->no_b_chan_end) {
5667  ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
5668  }
5669  pri->no_b_chan_end = pvt;
5670  if (!pri->no_b_chan_iflist) {
5671  /* List was empty */
5672  pri->no_b_chan_iflist = pvt;
5673  }
5674 }
5675 #endif /* defined(HAVE_PRI) */
5676 
5677 #if defined(HAVE_PRI)
5678 /*!
5679  * \internal
5680  * \brief Extract the given chan_dahdi interface structure from the no B channel list.
5681  * \since 1.8
5682  *
5683  * \param pri sig_pri span control structure holding no B channel list.
5684  * \param pvt chan_dahdi private interface structure to extract.
5685  *
5686  * \note
5687  * The given interface structure can be either in the interface list or a stand alone
5688  * structure that has not been put in the list if the next and prev pointers are NULL.
5689  */
5690 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
5691 {
5692  /* Extract from the forward chain. */
5693  if (pvt->prev) {
5694  pvt->prev->next = pvt->next;
5695  } else if (pri->no_b_chan_iflist == pvt) {
5696  /* Node is at the head of the list. */
5697  pri->no_b_chan_iflist = pvt->next;
5698  }
5699 
5700  /* Extract from the reverse chain. */
5701  if (pvt->next) {
5702  pvt->next->prev = pvt->prev;
5703  } else if (pri->no_b_chan_end == pvt) {
5704  /* Node is at the end of the list. */
5705  pri->no_b_chan_end = pvt->prev;
5706  }
5707 
5708  /* Node is no longer in the list. */
5710  pvt->prev = NULL;
5711  pvt->next = NULL;
5712 }
5713 #endif /* defined(HAVE_PRI) */
5714 
5715 #if defined(HAVE_PRI)
5716 /*!
5717  * \internal
5718  * \brief Unlink the channel interface from the PRI private pointer array.
5719  * \since 1.8
5720  *
5721  * \param pvt chan_dahdi private interface structure to unlink.
5722  */
5723 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
5724 {
5725  unsigned idx;
5726  struct sig_pri_span *pri;
5727 
5728  pri = pvt->pri;
5729  if (!pri) {
5730  /* Not PRI signaling so cannot be in a PRI private pointer array. */
5731  return;
5732  }
5733  ast_mutex_lock(&pri->lock);
5734  for (idx = 0; idx < pri->numchans; ++idx) {
5735  if (pri->pvts[idx] == pvt->sig_pvt) {
5736  pri->pvts[idx] = NULL;
5737  ast_mutex_unlock(&pri->lock);
5738  return;
5739  }
5740  }
5741  ast_mutex_unlock(&pri->lock);
5742 }
5743 #endif /* defined(HAVE_PRI) */
5744 
5745 #if defined(HAVE_SS7)
5746 /*!
5747  * \internal
5748  * \brief Unlink the channel interface from the SS7 private pointer array.
5749  * \since 1.8
5750  *
5751  * \param pvt chan_dahdi private interface structure to unlink.
5752  */
5753 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
5754 {
5755  unsigned idx;
5756  struct sig_ss7_linkset *ss7;
5757 
5758  ss7 = pvt->ss7;
5759  if (!ss7) {
5760  /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
5761  return;
5762  }
5763  ast_mutex_lock(&ss7->lock);
5764  for (idx = 0; idx < ss7->numchans; ++idx) {
5765  if (ss7->pvts[idx] == pvt->sig_pvt) {
5766  ss7->pvts[idx] = NULL;
5767  ast_mutex_unlock(&ss7->lock);
5768  return;
5769  }
5770  }
5771  ast_mutex_unlock(&ss7->lock);
5772 }
5773 #endif /* defined(HAVE_SS7) */
5774 
5775 #if defined(HAVE_OPENR2)
5776 /*!
5777  * \internal
5778  * \brief Unlink the channel interface from the MFC/R2 private pointer array.
5779  *
5780  * \param pvt chan_dahdi private interface structure to unlink.
5781  */
5782 static void dahdi_unlink_mfcr2_pvt(struct dahdi_pvt *pvt)
5783 {
5784  unsigned idx;
5785  struct dahdi_mfcr2 *mfcr2;
5786  int should_destroy_link = 0;
5787 
5788  ast_mutex_lock(&pvt->lock);
5789  if (pvt->r2chan) {
5790  ast_debug(1, "Disable MFC/R2 channel %d read\n", pvt->channel);
5791  openr2_chan_disable_read(pvt->r2chan);
5792  }
5793  mfcr2 = pvt->mfcr2;
5794  if (mfcr2) {
5795  for (idx = 0; idx < mfcr2->numchans; ++idx) {
5796  if (mfcr2->pvts[idx] == pvt) {
5797  ast_debug(1, "Removing MFC/R2 channel %d from the mfcr2 link\n", pvt->channel);
5798  mfcr2->pvts[idx] = NULL;
5799  mfcr2->live_chans--;
5800  break;
5801  }
5802  }
5803  if (!mfcr2->live_chans) {
5804  ast_debug(1, "MFC/R2 link is now empty\n");
5805  should_destroy_link = 1;
5806  }
5807  }
5808  ast_mutex_unlock(&pvt->lock);
5809  if (should_destroy_link) {
5810  ast_debug(1, "MFC/R2 link is now empty\n");
5811  mfcr2_queue_for_destruction(pvt);
5812  }
5813 }
5814 #endif /* defined(HAVE_OPENR2) */
5815 
5816 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
5817 {
5818  if (cur->next && cur->next->span == cur->span) {
5819  return cur->next;
5820  } else if (cur->prev && cur->prev->span == cur->span) {
5821  return cur->prev;
5822  }
5823 
5824  return NULL;
5825 }
5826 
5827 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
5828 {
5829  struct dahdi_pvt *p = pvt;
5830 
5831  if (p->manages_span_alarms) {
5832  struct dahdi_pvt *next = find_next_iface_in_span(p);
5833  if (next) {
5834  next->manages_span_alarms = 1;
5835  }
5836  }
5837 
5838  /* Remove channel from the list */
5839 #if defined(HAVE_PRI)
5840  dahdi_unlink_pri_pvt(p);
5841 #endif /* defined(HAVE_PRI) */
5842 #if defined(HAVE_SS7)
5843  dahdi_unlink_ss7_pvt(p);
5844 #endif /* defined(HAVE_SS7) */
5845 #if defined(HAVE_OPENR2)
5846  dahdi_unlink_mfcr2_pvt(p);
5847 #endif /* defined(HAVE_SS7) */
5848  switch (pvt->which_iflist) {
5849  case DAHDI_IFLIST_NONE:
5850  break;
5851  case DAHDI_IFLIST_MAIN:
5852  dahdi_iflist_extract(p);
5853  break;
5854 #if defined(HAVE_PRI)
5856  if (p->pri) {
5857  dahdi_nobch_extract(p->pri, p);
5858  }
5859  break;
5860 #endif /* defined(HAVE_PRI) */
5861  }
5862 
5863  if (p->sig_pvt) {
5864  if (dahdi_analog_lib_handles(p->sig, 0, 0)) {
5865  analog_delete(p->sig_pvt);
5866  }
5867  switch (p->sig) {
5868 #if defined(HAVE_PRI)
5869  case SIG_PRI_LIB_HANDLE_CASES:
5870  sig_pri_chan_delete(p->sig_pvt);
5871  break;
5872 #endif /* defined(HAVE_PRI) */
5873 #if defined(HAVE_SS7)
5874  case SIG_SS7:
5875  sig_ss7_chan_delete(p->sig_pvt);
5876  break;
5877 #endif /* defined(HAVE_SS7) */
5878  default:
5879  break;
5880  }
5881  }
5882  ast_free(p->cidspill);
5883  if (p->use_smdi) {
5884  ao2_cleanup(p->smdi_iface);
5885  }
5886  if (p->mwi_event_sub) {
5888  }
5889  if (p->vars) {
5891  }
5892  if (p->cc_params) {
5893  ast_cc_config_params_destroy(p->cc_params);
5894  }
5895 
5896  p->named_callgroups = ast_unref_namedgroups(p->named_callgroups);
5897  p->named_pickupgroups = ast_unref_namedgroups(p->named_pickupgroups);
5898 
5899  ast_mutex_destroy(&p->lock);
5900  dahdi_close_sub(p, SUB_REAL);
5901  if (p->owner) {
5902  ast_channel_tech_pvt_set(p->owner, NULL);
5903  }
5904  ast_free(p);
5905 }
5906 
5907 static void destroy_channel(struct dahdi_pvt *cur, int now)
5908 {
5909  int i;
5910 
5911  if (!now) {
5912  /* Do not destroy the channel now if it is owned by someone. */
5913  if (cur->owner) {
5914  return;
5915  }
5916  for (i = 0; i < 3; i++) {
5917  if (cur->subs[i].owner) {
5918  return;
5919  }
5920  }
5921  }
5922  destroy_dahdi_pvt(cur);
5923 }
5924 
5925 static void destroy_all_channels(void)
5926 {
5927  int chan;
5928 #if defined(HAVE_PRI)
5929  unsigned span;
5930  struct sig_pri_span *pri;
5931 #endif /* defined(HAVE_PRI) */
5932  struct dahdi_pvt *p;
5933 
5934  while (num_restart_pending) {
5935  usleep(1);
5936  }
5937 
5938  ast_mutex_lock(&iflock);
5939  /* Destroy all the interfaces and free their memory */
5940  while (iflist) {
5941  p = iflist;
5942 
5943  chan = p->channel;
5944 #if defined(HAVE_PRI_SERVICE_MESSAGES)
5945  {
5946  char db_chan_name[20];
5947  char db_answer[5];
5948  char state;
5949  int why = -1;
5950 
5951  snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
5952  if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
5953  sscanf(db_answer, "%1c:%30d", &state, &why);
5954  }
5955  if (!why) {
5956  /* SRVST persistence is not required */
5957  ast_db_del(db_chan_name, SRVST_DBKEY);
5958  }
5959  }
5960 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
5961  /* Free associated memory */
5962  destroy_dahdi_pvt(p);
5963  ast_verb(3, "Unregistered channel %d\n", chan);
5964  }
5965  ifcount = 0;
5966  ast_mutex_unlock(&iflock);
5967 
5968 #if defined(HAVE_PRI)
5969  /* Destroy all of the no B channel interface lists */
5970  for (span = 0; span < NUM_SPANS; ++span) {
5971  if (!pris[span].dchannels[0]) {
5972  break;
5973  }
5974  pri = &pris[span].pri;
5975  ast_mutex_lock(&pri->lock);
5976  while (pri->no_b_chan_iflist) {
5977  p = pri->no_b_chan_iflist;
5978 
5979  /* Free associated memory */
5980  destroy_dahdi_pvt(p);
5981  }
5982  ast_mutex_unlock(&pri->lock);
5983  }
5984 #endif /* defined(HAVE_PRI) */
5985 }
5986 
5987 #if defined(HAVE_PRI)
5988 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
5989 
5990 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
5991 {
5992  /* Data will be our digit string */
5993  struct dahdi_pvt *p;
5994 
5995  if (ast_strlen_zero(digits)) {
5996  ast_debug(1, "No digit string sent to application!\n");
5997  return -1;
5998  }
5999 
6000  p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
6001 
6002  if (!p) {
6003  ast_debug(1, "Unable to find technology private\n");
6004  return -1;
6005  }
6006 
6007  pri_send_keypad_facility_exec(p->sig_pvt, digits);
6008 
6009  return 0;
6010 }
6011 #endif /* defined(HAVE_PRI) */
6012 
6013 #if defined(HAVE_PRI)
6014 #if defined(HAVE_PRI_PROG_W_CAUSE)
6015 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
6016 
6017 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
6018 {
6019  /* Data will be our digit string */
6020  struct dahdi_pvt *pvt;
6021  char *parse;
6022  int res;
6023  AST_DECLARE_APP_ARGS(args,
6024  AST_APP_ARG(destination);
6025  AST_APP_ARG(original);
6026  AST_APP_ARG(reason);
6027  );
6028 
6029  if (ast_strlen_zero(data)) {
6030  ast_debug(1, "No data sent to application!\n");
6031  return -1;
6032  }
6033  if (ast_channel_tech(chan) != &dahdi_tech) {
6034  ast_debug(1, "Only DAHDI technology accepted!\n");
6035  return -1;
6036  }
6037  pvt = (struct dahdi_pvt *) ast_channel_tech_pvt(chan);
6038  if (!pvt) {
6039  ast_debug(1, "Unable to find technology private\n");
6040  return -1;
6041  }
6042  switch (pvt->sig) {
6043  case SIG_PRI_LIB_HANDLE_CASES:
6044  break;
6045  default:
6046  ast_debug(1, "callrerouting attempted on non-ISDN channel %s\n",
6047  ast_channel_name(chan));
6048  return -1;
6049  }
6050 
6051  parse = ast_strdupa(data);
6052  AST_STANDARD_APP_ARGS(args, parse);
6053 
6054  if (ast_strlen_zero(args.destination)) {
6055  ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
6056  return -1;
6057  }
6058 
6059  if (ast_strlen_zero(args.original)) {
6060  ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
6061  args.original = NULL;
6062  }
6063 
6064  if (ast_strlen_zero(args.reason)) {
6065  ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
6066  args.reason = NULL;
6067  }
6068 
6069  res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, ast_channel_state(chan),
6070  args.destination, args.original, args.reason);
6071  if (!res) {
6072  /*
6073  * Wait up to 5 seconds for a reply before hanging up this call
6074  * leg if the peer does not disconnect first.
6075  */
6076  ast_safe_sleep(chan, 5000);
6077  }
6078 
6079  return -1;
6080 }
6081 #endif /* defined(HAVE_PRI_PROG_W_CAUSE) */
6082 #endif /* defined(HAVE_PRI) */
6083 
6084 #if defined(HAVE_OPENR2)
6085 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
6086 
6087 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
6088 {
6089  /* data is whether to accept with charge or no charge */
6090  openr2_call_mode_t accept_mode;
6091  int res, timeout, maxloops;
6092  struct ast_frame *f;
6093  struct dahdi_pvt *p;
6094  char *parse;
6095  AST_DECLARE_APP_ARGS(args,
6096  AST_APP_ARG(charge);
6097  );
6098 
6099  if (ast_strlen_zero(data)) {
6100  ast_debug(1, "No data sent to application!\n");
6101  return -1;
6102  }
6103 
6104  if (ast_channel_tech(chan) != &dahdi_tech) {
6105  ast_debug(1, "Only DAHDI technology accepted!\n");
6106  return -1;
6107  }
6108 
6109  p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
6110  if (!p) {
6111  ast_debug(1, "Unable to find technology private!\n");
6112  return -1;
6113  }
6114 
6115  parse = ast_strdupa(data);
6116  AST_STANDARD_APP_ARGS(args, parse);
6117 
6118  if (ast_strlen_zero(args.charge)) {
6119  ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
6120  return -1;
6121  }
6122 
6123  ast_mutex_lock(&p->lock);
6124  if (!p->mfcr2 || !p->mfcr2call) {
6125  ast_mutex_unlock(&p->lock);
6126  ast_debug(1, "Channel %s does not seems to be an R2 active channel!\n", ast_channel_name(chan));
6127  return -1;
6128  }
6129 
6130  if (p->mfcr2_call_accepted) {
6131  ast_mutex_unlock(&p->lock);
6132  ast_debug(1, "MFC/R2 call already accepted on channel %s!\n", ast_channel_name(chan));
6133  return 0;
6134  }
6135  accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
6136  if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
6137  ast_mutex_unlock(&p->lock);
6138  ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
6139  return -1;
6140  }
6141  ast_mutex_unlock(&p->lock);
6142 
6143  res = 0;
6144  timeout = 100;
6145  maxloops = 50; /* wait up to 5 seconds */
6146  /* we need to read() until the call is accepted */
6147  while (maxloops > 0) {
6148  maxloops--;
6149  if (ast_check_hangup(chan)) {
6150  break;
6151  }
6152  res = ast_waitfor(chan, timeout);
6153  if (res < 0) {
6154  ast_debug(1, "ast_waitfor failed on channel %s, going out ...\n", ast_channel_name(chan));
6155  res = -1;
6156  break;
6157  }
6158  if (res == 0) {
6159  continue;
6160  }
6161  res = 0;
6162  f = ast_read(chan);
6163  if (!f) {
6164  ast_debug(1, "No frame read on channel %s, going out ...\n", ast_channel_name(chan));
6165  res = -1;
6166  break;
6167  }
6169  ast_debug(1, "Got HANGUP frame on channel %s, going out ...\n", ast_channel_name(chan));
6170  ast_frfree(f);
6171  res = -1;
6172  break;
6173  }
6174  ast_frfree(f);
6175  ast_mutex_lock(&p->lock);
6176  if (p->mfcr2_call_accepted) {
6177  ast_mutex_unlock(&p->lock);
6178  ast_debug(1, "Accepted MFC/R2 call!\n");
6179  break;
6180  }
6181  ast_mutex_unlock(&p->lock);
6182  }
6183  if (res == -1) {
6184  ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
6185  }
6186  return res;
6187 }
6188 
6189 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
6190 {
6191  openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
6192  switch (cause) {
6193  case AST_CAUSE_USER_BUSY:
6194  case AST_CAUSE_CALL_REJECTED:
6195  case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
6196  r2cause = OR2_CAUSE_BUSY_NUMBER;
6197  break;
6198 
6199  case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
6200  case AST_CAUSE_SWITCH_CONGESTION:
6201  r2cause = OR2_CAUSE_NETWORK_CONGESTION;
6202  break;
6203 
6204  case AST_CAUSE_UNALLOCATED:
6205  r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
6206  break;
6207 
6208  case AST_CAUSE_NETWORK_OUT_OF_ORDER:
6209  case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
6210  r2cause = OR2_CAUSE_OUT_OF_ORDER;
6211  break;
6212 
6213  case AST_CAUSE_NO_ANSWER:
6214  case AST_CAUSE_NO_USER_RESPONSE:
6215  r2cause = OR2_CAUSE_NO_ANSWER;
6216  break;
6217 
6218  default:
6219  r2cause = OR2_CAUSE_NORMAL_CLEARING;
6220  break;
6221  }
6222  ast_debug(1, "ast cause %d resulted in openr2 cause %d/%s\n",
6223  cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
6224  return r2cause;
6225 }
6226 #endif
6227 
6228 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
6229 {
6230  if (p->bufferoverrideinuse) {
6231  /* faxbuffers are in use, revert them */
6232  struct dahdi_bufferinfo bi = {
6233  .txbufpolicy = p->buf_policy,
6234  .rxbufpolicy = p->buf_policy,
6235  .bufsize = p->bufsize,
6236  .numbufs = p->buf_no
6237  };
6238  int bpres;
6239 
6240  if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
6241  ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast_channel_name(ast), strerror(errno));
6242  }
6243  p->bufferoverrideinuse = 0;
6244  return bpres;
6245  }
6246 
6247  return -1;
6248 }
6249 
6250 static int dahdi_hangup(struct ast_channel *ast)
6251 {
6252  int res = 0;
6253  int idx,x;
6254  int law;
6255  /*static int restore_gains(struct dahdi_pvt *p);*/
6256  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
6257  struct dahdi_params par;
6258 
6259  ast_debug(1, "dahdi_hangup(%s)\n", ast_channel_name(ast));
6260  if (!ast_channel_tech_pvt(ast)) {
6261  ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
6262  return 0;
6263  }
6264 
6265  ast_mutex_lock(&p->lock);
6266  p->exten[0] = '\0';
6267  /* Always use sig_analog hangup handling for operator mode */
6268  if (dahdi_analog_lib_handles(p->sig, p->radio, 0)) {
6269  p->oprmode = 0;
6270  dahdi_confmute(p, 0);
6271  restore_gains(p);
6272  p->ignoredtmf = 0;
6273  p->waitingfordt.tv_sec = 0;
6274 
6275  res = analog_hangup(p->sig_pvt, ast);
6276  revert_fax_buffers(p, ast);
6277 
6278  goto hangup_out;
6279  } else {
6280  p->cid_num[0] = '\0';
6281  p->cid_name[0] = '\0';
6282  p->cid_subaddr[0] = '\0';
6283  }
6284 
6285 #if defined(HAVE_PRI)
6286  if (dahdi_sig_pri_lib_handles(p->sig)) {
6287  x = 1;
6288  ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6289 
6290  dahdi_confmute(p, 0);
6291  p->muting = 0;
6292  restore_gains(p);
6293  if (p->dsp) {
6294  ast_dsp_free(p->dsp);
6295  p->dsp = NULL;
6296  }
6297  p->ignoredtmf = 0;
6298 
6299  /* Real channel, do some fixup */
6300  p->subs[SUB_REAL].owner = NULL;
6301  p->subs[SUB_REAL].needbusy = 0;
6302  dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
6303 
6304  p->owner = NULL;
6305  p->cid_tag[0] = '\0';
6306  p->ringt = 0;/* Probably not used in this mode. Reset anyway. */
6307  p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
6308  p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
6309  p->outgoing = 0;
6310  p->digital = 0;
6311  p->faxhandled = 0;
6312  p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
6313 
6314  revert_fax_buffers(p, ast);
6315 
6316  p->law = p->law_default;
6317  law = p->law_default;
6318  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6319  if (res < 0) {
6320  ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
6321  p->channel, strerror(errno));
6322  }
6323 
6324  sig_pri_hangup(p->sig_pvt, ast);
6325 
6326  tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6327  dahdi_ec_disable(p);
6328 
6329  x = 0;
6330  ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
6331  p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
6332 
6333  p->rdnis[0] = '\0';
6334  dahdi_conf_update(p);
6335  reset_conf(p);
6336 
6337  /* Restore data mode */
6338  x = 0;
6339  ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6340 
6341  if (num_restart_pending == 0) {
6342  restart_monitor();
6343  }
6344  goto hangup_out;
6345  }
6346 #endif /* defined(HAVE_PRI) */
6347 
6348 #if defined(HAVE_SS7)
6349  if (p->sig == SIG_SS7) {
6350  x = 1;
6351  ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6352 
6353  dahdi_confmute(p, 0);
6354  p->muting = 0;
6355  restore_gains(p);
6356  if (p->dsp) {
6357  ast_dsp_free(p->dsp);
6358  p->dsp = NULL;
6359  }
6360  p->ignoredtmf = 0;
6361 
6362  /* Real channel, do some fixup */
6363  p->subs[SUB_REAL].owner = NULL;
6364  p->subs[SUB_REAL].needbusy = 0;
6365  dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
6366 
6367  p->owner = NULL;
6368  p->ringt = 0;/* Probably not used in this mode. Reset anyway. */
6369  p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
6370  p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
6371  p->outgoing = 0;
6372  p->digital = 0;
6373  p->faxhandled = 0;
6374  p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
6375 
6376  revert_fax_buffers(p, ast);
6377 
6378  p->law = p->law_default;
6379  law = p->law_default;
6380  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6381  if (res < 0) {
6382  ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
6383  p->channel, strerror(errno));
6384  }
6385 
6386  sig_ss7_hangup(p->sig_pvt, ast);
6387 
6388  tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6389  dahdi_ec_disable(p);
6390 
6391  x = 0;
6392  ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
6393  p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
6394 
6395  dahdi_conf_update(p);
6396  reset_conf(p);
6397 
6398  /* Restore data mode */
6399  x = 0;
6400  ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6401 
6402  if (num_restart_pending == 0) {
6403  restart_monitor();
6404  }
6405  goto hangup_out;
6406  }
6407 #endif /* defined(HAVE_SS7) */
6408 
6409  idx = dahdi_get_index(ast, p, 1);
6410 
6411  dahdi_confmute(p, 0);
6412  p->muting = 0;
6413  restore_gains(p);
6414  if (p->origcid_num) {
6415  ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
6416  ast_free(p->origcid_num);
6417  p->origcid_num = NULL;
6418  }
6419  if (p->origcid_name) {
6420  ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
6421  ast_free(p->origcid_name);
6422  p->origcid_name = NULL;
6423  }
6424  if (p->dsp)
6426 
6427  ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
6428  p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
6429  p->ignoredtmf = 0;
6430 
6431  if (idx > -1) {
6432  /* Real channel, do some fixup */
6433  p->subs[idx].owner = NULL;
6434  p->subs[idx].needanswer = 0;
6435  p->subs[idx].needflash = 0;
6436  p->subs[idx].needringing = 0;
6437  p->subs[idx].needbusy = 0;
6438  p->subs[idx].needcongestion = 0;
6439  p->subs[idx].linear = 0;
6440  p->polarity = POLARITY_IDLE;
6441  dahdi_setlinear(p->subs[idx].dfd, 0);
6442  if (idx == SUB_REAL) {
6443  if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
6444  ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
6445  if (p->subs[SUB_CALLWAIT].inthreeway) {
6446  /* We had flipped over to answer a callwait and now it's gone */
6447  ast_debug(1, "We were flipped over to the callwait, moving back and not owning.\n");
6448  /* Move to the call-wait, but un-own us until they flip back. */
6449  swap_subs(p, SUB_CALLWAIT, SUB_REAL);
6450  unalloc_sub(p, SUB_CALLWAIT);
6451  p->owner = NULL;
6452  } else {
6453  /* The three way hung up, but we still have a call wait */
6454  ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
6455  swap_subs(p, SUB_THREEWAY, SUB_REAL);
6456  unalloc_sub(p, SUB_THREEWAY);
6457  if (p->subs[SUB_REAL].inthreeway) {
6458  /* This was part of a three way call. Immediately make way for
6459  another call */
6460  ast_debug(1, "Call was complete, setting owner to former third call\n");
6461  p->owner = p->subs[SUB_REAL].owner;
6462  } else {
6463  /* This call hasn't been completed yet... Set owner to NULL */
6464  ast_debug(1, "Call was incomplete, setting owner to NULL\n");
6465  p->owner = NULL;
6466  }
6467  p->subs[SUB_REAL].inthreeway = 0;
6468  }
6469  } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
6470  /* Move to the call-wait and switch back to them. */
6471  swap_subs(p, SUB_CALLWAIT, SUB_REAL);
6472  unalloc_sub(p, SUB_CALLWAIT);
6473  p->owner = p->subs[SUB_REAL].owner;
6475  p->subs[SUB_REAL].needanswer = 1;
6476  ast_queue_unhold(p->subs[SUB_REAL].owner);
6477  } else if (p->subs[SUB_THREEWAY].dfd > -1) {
6478  swap_subs(p, SUB_THREEWAY, SUB_REAL);
6479  unalloc_sub(p, SUB_THREEWAY);
6480  if (p->subs[SUB_REAL].inthreeway) {
6481  /* This was part of a three way call. Immediately make way for
6482  another call */
6483  ast_debug(1, "Call was complete, setting owner to former third call\n");
6484  p->owner = p->subs[SUB_REAL].owner;
6485  } else {
6486  /* This call hasn't been completed yet... Set owner to NULL */
6487  ast_debug(1, "Call was incomplete, setting owner to NULL\n");
6488  p->owner = NULL;
6489  }
6490  p->subs[SUB_REAL].inthreeway = 0;
6491  }
6492  } else if (idx == SUB_CALLWAIT) {
6493  /* Ditch the holding callwait call, and immediately make it availabe */
6494  if (p->subs[SUB_CALLWAIT].inthreeway) {
6495  /* This is actually part of a three way, placed on hold. Place the third part
6496  on music on hold now */
6497  if (p->subs[SUB_THREEWAY].owner) {
6498  ast_queue_hold(p->subs[SUB_THREEWAY].owner, p->mohsuggest);
6499  }
6500  p->subs[SUB_THREEWAY].inthreeway = 0;
6501  /* Make it the call wait now */
6502  swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
6503  unalloc_sub(p, SUB_THREEWAY);
6504  } else
6505  unalloc_sub(p, SUB_CALLWAIT);
6506  } else if (idx == SUB_THREEWAY) {
6507  if (p->subs[SUB_CALLWAIT].inthreeway) {
6508  /* The other party of the three way call is currently in a call-wait state.
6509  Start music on hold for them, and take the main guy out of the third call */
6510  if (p->subs[SUB_CALLWAIT].owner) {
6511  ast_queue_hold(p->subs[SUB_CALLWAIT].owner, p->mohsuggest);
6512  }
6513  p->subs[SUB_CALLWAIT].inthreeway = 0;
6514  }
6515  p->subs[SUB_REAL].inthreeway = 0;
6516  /* If this was part of a three way call index, let us make
6517  another three way call */
6518  unalloc_sub(p, SUB_THREEWAY);
6519  } else {
6520  /* This wasn't any sort of call, but how are we an index? */
6521  ast_log(LOG_WARNING, "Index found but not any type of call?\n");
6522  }
6523  }
6524 
6525  if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
6526  p->owner = NULL;
6527  p->ringt = 0;
6528  p->distinctivering = 0;
6529  p->confirmanswer = 0;
6530  p->outgoing = 0;
6531  p->digital = 0;
6532  p->faxhandled = 0;
6533  p->pulsedial = 0;
6534  if (p->dsp) {
6535  ast_dsp_free(p->dsp);
6536  p->dsp = NULL;
6537  }
6538 
6539  revert_fax_buffers(p, ast);
6540 
6541  p->law = p->law_default;
6542  law = p->law_default;
6543  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6544  if (res < 0)
6545  ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
6546  /* Perform low level hangup if no owner left */
6547 #ifdef HAVE_OPENR2
6548  if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
6549  ast_debug(1, "disconnecting MFC/R2 call on chan %d\n", p->channel);
6550  /* If it's an incoming call, check the mfcr2_forced_release setting */
6551  if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
6552  dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
6553  } else {
6554  const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
6555  int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
6556  openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
6557  : dahdi_ast_cause_to_r2_cause(ast_channel_hangupcause(ast));
6558  dahdi_r2_disconnect_call(p, r2cause);
6559  }
6560  } else if (p->mfcr2call) {
6561  ast_debug(1, "Clearing call request on channel %d\n", p->channel);
6562  /* since ast_request() was called but not ast_call() we have not yet dialed
6563  and the openr2 stack will not call on_call_end callback, we need to unset
6564  the mfcr2call flag and bump the monitor count so the monitor thread can take
6565  care of this channel events from now on */
6566  p->mfcr2call = 0;
6567  }
6568 #endif
6569  switch (p->sig) {
6570  case SIG_SS7:
6571  case SIG_MFCR2:
6572  case SIG_PRI_LIB_HANDLE_CASES:
6573  case 0:
6574  break;
6575  default:
6576  res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6577  break;
6578  }
6579  if (res < 0) {
6580  ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast_channel_name(ast));
6581  }
6582  switch (p->sig) {
6583  case SIG_FXOGS:
6584  case SIG_FXOLS:
6585  case SIG_FXOKS:
6586  memset(&par, 0, sizeof(par));
6587  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
6588  if (!res) {
6589  struct analog_pvt *analog_p = p->sig_pvt;
6590 #if 0
6591  ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
6592 #endif
6593  /* If they're off hook, try playing congestion */
6594  if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
6595  tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6596  else
6597  tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6598  analog_p->fxsoffhookstate = par.rxisoffhook;
6599  }
6600  break;
6601  case SIG_FXSGS:
6602  case SIG_FXSLS:
6603  case SIG_FXSKS:
6604  /* Make sure we're not made available for at least two seconds assuming
6605  we were actually used for an inbound or outbound call. */
6606  if (ast_channel_state(ast) != AST_STATE_RESERVED) {
6607  time(&p->guardtime);
6608  p->guardtime += 2;
6609  }
6610  break;
6611  default:
6612  tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6613  break;
6614  }
6615  if (p->sig)
6616  dahdi_ec_disable(p);
6617  x = 0;
6618  ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
6619  ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
6620  p->didtdd = 0;
6621  p->callwaitcas = 0;
6622  p->callwaiting = p->permcallwaiting;
6624  p->waitingfordt.tv_sec = 0;
6625  p->dialing = 0;
6626  p->rdnis[0] = '\0';
6627  dahdi_conf_update(p);
6628  reset_conf(p);
6629  /* Restore data mode */
6630  switch (p->sig) {
6631  case SIG_PRI_LIB_HANDLE_CASES:
6632  case SIG_SS7:
6633  x = 0;
6634  ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
6635  break;
6636  default:
6637  break;
6638  }
6639  if (num_restart_pending == 0)
6640  restart_monitor();
6641  }
6642 
6643  p->callwaitingrepeat = 0;
6644  p->cidcwexpire = 0;
6645  p->cid_suppress_expire = 0;
6646  p->oprmode = 0;
6647 hangup_out:
6648  ast_channel_tech_pvt_set(ast, NULL);
6649  ast_free(p->cidspill);
6650  p->cidspill = NULL;
6651 
6652  if (p->reoriginate && p->sig == SIG_FXOKS && dahdi_analog_lib_handles(p->sig, p->radio, 0)) {
6653  /* Automatic reorigination: if all calls towards a user have hung up,
6654  * give dial tone again, so user doesn't need to cycle the hook state manually. */
6655  if (my_is_off_hook(p) && !p->owner) {
6656  /* 2 important criteria: channel must be off-hook, with no calls remaining (no owner) */
6657  ast_debug(1, "Queuing reorigination for channel %d\n", p->channel);
6658  my_play_tone(p, SUB_REAL, -1); /* Stop any congestion tone that may be present. */
6659  /* Must wait for the loop disconnect to end.
6660  * Sadly, these definitions are in dahdi/kernel.h, not dahdi/user.h
6661  * Calling usleep on an active DAHDI channel is a no-no, but this is okay.
6662  */
6663  usleep(800000); /* DAHDI_KEWLTIME + DAHDI_AFTERKEWLTIME */
6664  /* If the line is still off-hook and ownerless, actually queue the reorigination.
6665  * do_monitor will actually go ahead and do it. */
6666  if (!p->owner && my_is_off_hook(p)) {
6667  p->doreoriginate = 1; /* Tell do_monitor to reoriginate this channel */
6668  /* Note, my_off_hook will fail if called before the loop disconnect has finished
6669  * (important for FXOKS signaled channels). This is because DAHDI will reject
6670  * DAHDI_OFFHOOK while the channel is in TXSTATE_KEWL or TXSTATE_AFTERKEWL,
6671  * so we have to wait for that to finish (see comment above).
6672  * do_monitor itself cannot block, so make the blocking usleep call
6673  * here in the channel thread instead.
6674  */
6675  my_off_hook(p); /* Now, go ahead and take the channel back off hook (sig_analog put it on hook) */
6676  } else {
6677  ast_debug(1, "Channel %d is no longer eligible for reorigination (went back on hook or became in use)\n", p->channel);
6678  }
6679  }
6680  }
6681 
6682  ast_mutex_unlock(&p->lock);
6683  ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast));
6684 
6685  ast_mutex_lock(&iflock);
6686  if (p->restartpending) {
6687  num_restart_pending--;
6688  }
6689 
6690  if (p->destroy) {
6691  destroy_channel(p, 0);
6692  }
6693  ast_mutex_unlock(&iflock);
6694 
6696  return 0;
6697 }
6698 
6699 static int dahdi_answer(struct ast_channel *ast)
6700 {
6701  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
6702  int res = 0;
6703  int idx;
6704  ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
6705  ast_mutex_lock(&p->lock);
6706  idx = dahdi_get_index(ast, p, 0);
6707  if (idx < 0)
6708  idx = SUB_REAL;
6709  /* nothing to do if a radio channel */
6710  if ((p->radio || (p->oprmode < 0))) {
6711  ast_mutex_unlock(&p->lock);
6712  return 0;
6713  }
6714 
6715  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
6716  res = analog_answer(p->sig_pvt, ast);
6717  ast_mutex_unlock(&p->lock);
6718  return res;
6719  }
6720 
6721  switch (p->sig) {
6722 #if defined(HAVE_PRI)
6723  case SIG_PRI_LIB_HANDLE_CASES:
6724  res = sig_pri_answer(p->sig_pvt, ast);
6725  break;
6726 #endif /* defined(HAVE_PRI) */
6727 #if defined(HAVE_SS7)
6728  case SIG_SS7:
6729  res = sig_ss7_answer(p->sig_pvt, ast);
6730  break;
6731 #endif /* defined(HAVE_SS7) */
6732 #ifdef HAVE_OPENR2
6733  case SIG_MFCR2:
6734  if (!p->mfcr2_call_accepted) {
6735  /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
6736  openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
6737  p->mfcr2_answer_pending = 1;
6738  if (p->mfcr2_charge_calls) {
6739  ast_debug(1, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
6740  openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
6741  } else {
6742  ast_debug(1, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
6743  openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
6744  }
6745  } else {
6746  ast_debug(1, "Answering MFC/R2 call on chan %d\n", p->channel);
6747  dahdi_r2_answer(p);
6748  }
6749  break;
6750 #endif
6751  case 0:
6752  ast_mutex_unlock(&p->lock);
6753  return 0;
6754  default:
6755  ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
6756  res = -1;
6757  break;
6758  }
6759  ast_mutex_unlock(&p->lock);
6760  return res;
6761 }
6762 
6763 void dahdi_dtmf_detect_disable(struct dahdi_pvt *p)
6764 {
6765  int val = 0;
6766 
6767  p->ignoredtmf = 1;
6768 
6769  ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
6770 
6771  if (!p->hardwaredtmf && p->dsp) {
6772  p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
6774  }
6775 }
6776 
6777 void dahdi_dtmf_detect_enable(struct dahdi_pvt *p)
6778 {
6779  int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
6780 
6781  if (p->channel == CHAN_PSEUDO)
6782  return;
6783 
6784  p->ignoredtmf = 0;
6785 
6786  ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
6787 
6788  if (!p->hardwaredtmf && p->dsp) {
6789  p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
6791  }
6792 }
6793 
6794 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
6795 {
6796  char *cp;
6797  struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
6798 
6799  /* all supported options require data */
6800  if (!p || !data || (*datalen < 1)) {
6801  errno = EINVAL;
6802  return -1;
6803  }
6804 
6805  switch (option) {
6806  case AST_OPTION_TDD:
6807  cp = (char *) data;
6808  if (p->mate) {
6809  *cp = 2;
6810  } else {
6811  *cp = p->tdd ? 1 : 0;
6812  }
6813  break;
6815  cp = (char *) data;
6816  *cp = p->ignoredtmf ? 0 : 1;
6817  ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
6818  break;
6819  case AST_OPTION_FAX_DETECT:
6820  cp = (char *) data;
6821  *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
6822  ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
6823  break;
6825 #if defined(HAVE_PRI)
6826 #if defined(HAVE_PRI_CCSS)
6827  if (dahdi_sig_pri_lib_handles(p->sig)) {
6828  ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
6829  break;
6830  }
6831 #endif /* defined(HAVE_PRI_CCSS) */
6832 #endif /* defined(HAVE_PRI) */
6833  return -1;
6834  default:
6835  return -1;
6836  }
6837 
6838  errno = 0;
6839 
6840  return 0;
6841 }
6842 
6843 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
6844 {
6845  char *cp;
6846  signed char *scp;
6847  int x;
6848  int idx;
6849  struct dahdi_pvt *p = ast_channel_tech_pvt(chan), *pp;
6850  struct oprmode *oprmode;
6851 
6852 
6853  /* all supported options require data */
6854  if (!p || !data || (datalen < 1)) {
6855  errno = EINVAL;
6856  return -1;
6857  }
6858 
6859  switch (option) {
6860  case AST_OPTION_TXGAIN:
6861  scp = (signed char *) data;
6862  idx = dahdi_get_index(chan, p, 0);
6863  if (idx < 0) {
6864  ast_log(LOG_WARNING, "No index in TXGAIN?\n");
6865  return -1;
6866  }
6867  ast_debug(1, "Setting actual tx gain on %s to %f\n", ast_channel_name(chan), p->txgain + (float) *scp);
6868  return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
6869  case AST_OPTION_RXGAIN:
6870  scp = (signed char *) data;
6871  idx = dahdi_get_index(chan, p, 0);
6872  if (idx < 0) {
6873  ast_log(LOG_WARNING, "No index in RXGAIN?\n");
6874  return -1;
6875  }
6876  ast_debug(1, "Setting actual rx gain on %s to %f\n", ast_channel_name(chan), p->rxgain + (float) *scp);
6877  return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
6879  if (!p->dsp)
6880  break;
6881  cp = (char *) data;
6882  switch (*cp) {
6883  case 1:
6884  ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",ast_channel_name(chan));
6885  ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
6886  break;
6887  case 2:
6888  ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",ast_channel_name(chan));
6889  ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
6890  break;
6891  default:
6892  ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",ast_channel_name(chan));
6893  ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
6894  break;
6895  }
6896  break;
6897  case AST_OPTION_TDD:
6898  /* turn on or off TDD */
6899  cp = (char *) data;
6900  p->mate = 0;
6901  if (!*cp) { /* turn it off */
6902  ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",ast_channel_name(chan));
6903  if (p->tdd)
6904  tdd_free(p->tdd);
6905  p->tdd = 0;
6906  break;
6907  }
6908  ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
6909  (*cp == 2) ? "MATE" : "ON", (int) *cp, ast_channel_name(chan));
6910  dahdi_ec_disable(p);
6911  /* otherwise, turn it on */
6912  if (!p->didtdd) { /* if havent done it yet */
6913  unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
6914  unsigned char *buf;
6915  int size, res, fd, len;
6916  struct pollfd fds[1];
6917 
6918  buf = mybuf;
6919  memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
6920  ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */
6921  len = 40000;
6922  idx = dahdi_get_index(chan, p, 0);
6923  if (idx < 0) {
6924  ast_log(LOG_WARNING, "No index in TDD?\n");
6925  return -1;
6926  }
6927  fd = p->subs[idx].dfd;
6928  while (len) {
6929  if (ast_check_hangup(chan))
6930  return -1;
6931  size = len;
6932  if (size > READ_SIZE)
6933  size = READ_SIZE;
6934  fds[0].fd = fd;
6935  fds[0].events = POLLPRI | POLLOUT;
6936  fds[0].revents = 0;
6937  res = poll(fds, 1, -1);
6938  if (!res) {
6939  ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
6940  continue;
6941  }
6942  /* if got exception */
6943  if (fds[0].revents & POLLPRI)
6944  return -1;
6945  if (!(fds[0].revents & POLLOUT)) {
6946  ast_debug(1, "write fd not ready on channel %d\n", p->channel);
6947  continue;
6948  }
6949  res = write(fd, buf, size);
6950  if (res != size) {
6951  if (res == -1) return -1;
6952  ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
6953  break;
6954  }
6955  len -= size;
6956  buf += size;
6957  }
6958  p->didtdd = 1; /* set to have done it now */
6959  }
6960  if (*cp == 2) { /* Mate mode */
6961  if (p->tdd)
6962  tdd_free(p->tdd);
6963  p->tdd = 0;
6964  p->mate = 1;
6965  break;
6966  }
6967  if (!p->tdd) { /* if we don't have one yet */
6968  p->tdd = tdd_new(); /* allocate one */
6969  }
6970  break;
6971  case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
6972  if (!p->dsp)
6973  break;
6974  cp = (char *) data;
6975  ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
6976  *cp ? "ON" : "OFF", (int) *cp, ast_channel_name(chan));
6978  break;
6979  case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
6980 #if defined(HAVE_PRI)
6981  if (dahdi_sig_pri_lib_handles(p->sig)
6982  && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
6983  /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
6984  break;
6985  }
6986 #endif /* defined(HAVE_PRI) */
6987 
6988  cp = (char *) data;
6989  if (!*cp) {
6990  ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", ast_channel_name(chan));
6991  x = 0;
6992  dahdi_ec_disable(p);
6993  } else {
6994  ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", ast_channel_name(chan));
6995  x = 1;
6996  }
6997  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
6998  ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
6999  break;
7000  case AST_OPTION_OPRMODE: /* Operator services mode */
7001  oprmode = (struct oprmode *) data;
7002  /* We don't support operator mode across technologies */
7003  if (strcasecmp(ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type)) {
7004  ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
7005  ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type);
7006  errno = EINVAL;
7007  return -1;
7008  }
7009  pp = ast_channel_tech_pvt(oprmode->peer);
7010  p->oprmode = pp->oprmode = 0;
7011  /* setup peers */
7012  p->oprpeer = pp;
7013  pp->oprpeer = p;
7014  /* setup modes, if any */
7015  if (oprmode->mode)
7016  {
7017  pp->oprmode = oprmode->mode;
7018  p->oprmode = -oprmode->mode;
7019  }
7020  ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
7021  oprmode->mode, ast_channel_name(chan),ast_channel_name(oprmode->peer));
7022  break;
7023  case AST_OPTION_ECHOCAN:
7024  cp = (char *) data;
7025  if (*cp) {
7026  ast_debug(1, "Enabling echo cancellation on %s\n", ast_channel_name(chan));
7027  dahdi_ec_enable(p);
7028  } else {
7029  ast_debug(1, "Disabling echo cancellation on %s\n", ast_channel_name(chan));
7030  dahdi_ec_disable(p);
7031  }
7032  break;
7034  cp = (char *) data;
7035  ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
7036  if (*cp) {
7037  dahdi_dtmf_detect_enable(p);
7038  } else {
7039  dahdi_dtmf_detect_disable(p);
7040  }
7041  break;
7042  case AST_OPTION_FAX_DETECT:
7043  cp = (char *) data;
7044  if (p->dsp) {
7045  ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
7046  if (*cp) {
7047  p->dsp_features |= DSP_FEATURE_FAX_DETECT;
7048  } else {
7049  p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
7050  }
7052  }
7053  break;
7054  default:
7055  return -1;
7056  }
7057  errno = 0;
7058 
7059  return 0;
7060 }
7061 
7062 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
7063 {
7064  struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
7065  int res = 0;
7066 
7067  if (!p) {
7068  /* No private structure! */
7069  *buf = '\0';
7070  return -1;
7071  }
7072 
7073  if (!strcasecmp(data, "rxgain")) {
7074  ast_mutex_lock(&p->lock);
7075  snprintf(buf, len, "%f", p->rxgain);
7076  ast_mutex_unlock(&p->lock);
7077  } else if (!strcasecmp(data, "txgain")) {
7078  ast_mutex_lock(&p->lock);
7079  snprintf(buf, len, "%f", p->txgain);
7080  ast_mutex_unlock(&p->lock);
7081  } else if (!strcasecmp(data, "dahdi_channel")) {
7082  ast_mutex_lock(&p->lock);
7083  snprintf(buf, len, "%d", p->channel);
7084  ast_mutex_unlock(&p->lock);
7085  } else if (!strcasecmp(data, "dahdi_span")) {
7086  ast_mutex_lock(&p->lock);
7087  snprintf(buf, len, "%d", p->span);
7088  ast_mutex_unlock(&p->lock);
7089  } else if (!strcasecmp(data, "dahdi_group")) {
7090  ast_mutex_lock(&p->lock);
7091  snprintf(buf, len, "%llu", p->group);
7092  ast_mutex_unlock(&p->lock);
7093  } else if (!strcasecmp(data, "dahdi_type")) {
7094  ast_mutex_lock(&p->lock);
7095  switch (p->sig) {
7096 #if defined(HAVE_OPENR2)
7097  case SIG_MFCR2:
7098  ast_copy_string(buf, "mfc/r2", len);
7099  break;
7100 #endif /* defined(HAVE_OPENR2) */
7101 #if defined(HAVE_PRI)
7102  case SIG_PRI_LIB_HANDLE_CASES:
7103  ast_copy_string(buf, "pri", len);
7104  break;
7105 #endif /* defined(HAVE_PRI) */
7106  case 0:
7107  ast_copy_string(buf, "pseudo", len);
7108  break;
7109 #if defined(HAVE_SS7)
7110  case SIG_SS7:
7111  ast_copy_string(buf, "ss7", len);
7112  break;
7113 #endif /* defined(HAVE_SS7) */
7114  default:
7115  /* The only thing left is analog ports. */
7116  ast_copy_string(buf, "analog", len);
7117  break;
7118  }
7119  ast_mutex_unlock(&p->lock);
7120 #if defined(HAVE_PRI)
7121 #if defined(HAVE_PRI_REVERSE_CHARGE)
7122  } else if (!strcasecmp(data, "reversecharge")) {
7123  ast_mutex_lock(&p->lock);
7124  switch (p->sig) {
7125  case SIG_PRI_LIB_HANDLE_CASES:
7126  snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
7127  break;
7128  default:
7129  *buf = '\0';
7130  res = -1;
7131  break;
7132  }
7133  ast_mutex_unlock(&p->lock);
7134 #endif
7135 #if defined(HAVE_PRI_SETUP_KEYPAD)
7136  } else if (!strcasecmp(data, "keypad_digits")) {
7137  ast_mutex_lock(&p->lock);
7138  switch (p->sig) {
7139  case SIG_PRI_LIB_HANDLE_CASES:
7140  ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
7141  len);
7142  break;
7143  default:
7144  *buf = '\0';
7145  res = -1;
7146  break;
7147  }
7148  ast_mutex_unlock(&p->lock);
7149 #endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
7150  } else if (!strcasecmp(data, "no_media_path")) {
7151  ast_mutex_lock(&p->lock);
7152  switch (p->sig) {
7153  case SIG_PRI_LIB_HANDLE_CASES:
7154  /*
7155  * TRUE if the call is on hold or is call waiting because
7156  * there is no media path available.
7157  */
7158  snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
7159  break;
7160  default:
7161  *buf = '\0';
7162  res = -1;
7163  break;
7164  }
7165  ast_mutex_unlock(&p->lock);
7166 #endif /* defined(HAVE_PRI) */
7167  } else if (!strcasecmp(data, "dialmode")) {
7168  struct analog_pvt *analog_p;
7169  ast_mutex_lock(&p->lock);
7170  analog_p = p->sig_pvt;
7171  /* Hardcode p->radio and p->oprmode as 0 since we're using this to check for analogness, not the handler */
7172  if (dahdi_analog_lib_handles(p->sig, 0, 0) && analog_p) {
7173  switch (analog_p->dialmode) {
7174  case ANALOG_DIALMODE_BOTH:
7175  ast_copy_string(buf, "both", len);
7176  break;
7177  case ANALOG_DIALMODE_PULSE:
7178  ast_copy_string(buf, "pulse", len);
7179  break;
7180  case ANALOG_DIALMODE_DTMF:
7181  ast_copy_string(buf, "dtmf", len);
7182  break;
7183  case ANALOG_DIALMODE_NONE:
7184  ast_copy_string(buf, "none", len);
7185  break;
7186  }
7187  } else {
7188  ast_log(LOG_WARNING, "%s only supported on analog channels\n", data);
7189  *buf = '\0';
7190  res = -1;
7191  }
7192  ast_mutex_unlock(&p->lock);
7193  } else {
7194  *buf = '\0';
7195  res = -1;
7196  }
7197 
7198  return res;
7199 }
7200 
7201 
7202 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
7203 {
7204  int res;
7205  char policy_str[21] = "";
7206 
7207  if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
7208  ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
7209  return 1;
7210  }
7211  if (*num_buffers < 0) {
7212  ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
7213  return -1;
7214  }
7215  if (!strcasecmp(policy_str, "full")) {
7216  *policy = DAHDI_POLICY_WHEN_FULL;
7217  } else if (!strcasecmp(policy_str, "immediate")) {
7218  *policy = DAHDI_POLICY_IMMEDIATE;
7219 #if defined(HAVE_DAHDI_HALF_FULL)
7220  } else if (!strcasecmp(policy_str, "half")) {
7221  *policy = DAHDI_POLICY_HALF_FULL;
7222 #endif
7223  } else {
7224  ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
7225  return -1;
7226  }
7227 
7228  return 0;
7229 }
7230 
7231 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
7232 {
7233  struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
7234  int res = 0;
7235 
7236  if (!p) {
7237  /* No private structure! */
7238  return -1;
7239  }
7240 
7241  if (!strcasecmp(data, "buffers")) {
7242  int num_bufs, policy;
7243 
7244  if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
7245  struct dahdi_bufferinfo bi = {
7246  .txbufpolicy = policy,
7247  .rxbufpolicy = policy,
7248  .bufsize = p->bufsize,
7249  .numbufs = num_bufs,
7250  };
7251  int bpres;
7252 
7253  if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
7254  ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
7255  } else {
7256  p->bufferoverrideinuse = 1;
7257  }
7258  } else {
7259  res = -1;
7260  }
7261  } else if (!strcasecmp(data, "echocan_mode")) {
7262  if (!strcasecmp(value, "on")) {
7263  ast_mutex_lock(&p->lock);
7264  dahdi_ec_enable(p);
7265  ast_mutex_unlock(&p->lock);
7266  } else if (!strcasecmp(value, "off")) {
7267  ast_mutex_lock(&p->lock);
7268  dahdi_ec_disable(p);
7269  ast_mutex_unlock(&p->lock);
7270 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
7271  } else if (!strcasecmp(value, "fax")) {
7272  int blah = 1;
7273 
7274  ast_mutex_lock(&p->lock);
7275  if (!p->echocanon) {
7276  dahdi_ec_enable(p);
7277  }
7278  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
7279  ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
7280  }
7281  ast_mutex_unlock(&p->lock);
7282  } else if (!strcasecmp(value, "voice")) {
7283  int blah = 0;
7284 
7285  ast_mutex_lock(&p->lock);
7286  if (!p->echocanon) {
7287  dahdi_ec_enable(p);
7288  }
7289  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
7290  ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
7291  }
7292  ast_mutex_unlock(&p->lock);
7293 #endif
7294  } else {
7295  ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
7296  res = -1;
7297  }
7298  } else if (!strcasecmp(data, "dialmode")) {
7299  struct analog_pvt *analog_p;
7300 
7301  ast_mutex_lock(&p->lock);
7302  analog_p = p->sig_pvt;
7303  if (!dahdi_analog_lib_handles(p->sig, 0, 0) || !analog_p) {
7304  ast_log(LOG_WARNING, "%s only supported on analog channels\n", data);
7305  ast_mutex_unlock(&p->lock);
7306  return -1;
7307  }
7308  /* analog pvt is used for pulse dialing, so update both */
7309  if (!strcasecmp(value, "pulse")) {
7310  p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_PULSE;
7311  } else if (!strcasecmp(value, "dtmf") || !strcasecmp(value, "tone")) {
7312  p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_DTMF;
7313  } else if (!strcasecmp(value, "none")) {
7314  p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_NONE;
7315  } else if (!strcasecmp(value, "both")) {
7316  p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_BOTH;
7317  } else {
7318  ast_log(LOG_WARNING, "'%s' is an invalid setting for %s\n", value, data);
7319  res = -1;
7320  }
7321  ast_mutex_unlock(&p->lock);
7322  } else if (!strcasecmp(data, "waitfordialtone")) {
7323  if (ast_strlen_zero(value)) {
7324  ast_log(LOG_WARNING, "waitfordialtone requires a duration in ms\n");
7325  return -1;
7326  }
7327 
7328  ast_mutex_lock(&p->lock);
7329  if (!CANPROGRESSDETECT(p)) {
7330  ast_log(LOG_WARNING, "%s only supported on analog trunks\n", data);
7331  ast_mutex_unlock(&p->lock);
7332  return -1;
7333  }
7334  /* Only set the temp waitfordialtone setting, not the permanent one. */
7335  p->waitfordialtonetemp = atoi(value);
7336  ast_mutex_unlock(&p->lock);
7337  } else {
7338  res = -1;
7339  }
7340 
7341  return res;
7342 }
7343 
7344 void dahdi_master_slave_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
7345 {
7346  /* Unlink a specific slave or all slaves/masters from a given master */
7347  int x;
7348  int hasslaves;
7349  if (!master)
7350  return;
7351  if (needlock) {
7352  ast_mutex_lock(&master->lock);
7353  if (slave) {
7354  while (ast_mutex_trylock(&slave->lock)) {
7355  DEADLOCK_AVOIDANCE(&master->lock);
7356  }
7357  }
7358  }
7359  hasslaves = 0;
7360  for (x = 0; x < MAX_SLAVES; x++) {
7361  if (master->slaves[x]) {
7362  if (!slave || (master->slaves[x] == slave)) {
7363  /* Take slave out of the conference */
7364  ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
7365  conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
7366  conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
7367  master->slaves[x]->master = NULL;
7368  master->slaves[x] = NULL;
7369  } else
7370  hasslaves = 1;
7371  }
7372  if (!hasslaves)
7373  master->inconference = 0;
7374  }
7375  if (!slave) {
7376  if (master->master) {
7377  /* Take master out of the conference */
7378  conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
7379  conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
7380  hasslaves = 0;
7381  for (x = 0; x < MAX_SLAVES; x++) {
7382  if (master->master->slaves[x] == master)
7383  master->master->slaves[x] = NULL;
7384  else if (master->master->slaves[x])
7385  hasslaves = 1;
7386  }
7387  if (!hasslaves)
7388  master->master->inconference = 0;
7389  }
7390  master->master = NULL;
7391  }
7392  dahdi_conf_update(master);
7393  if (needlock) {
7394  if (slave)
7395  ast_mutex_unlock(&slave->lock);
7396  ast_mutex_unlock(&master->lock);
7397  }
7398 }
7399 
7400 void dahdi_master_slave_link(struct dahdi_pvt *slave, struct dahdi_pvt *master)
7401 {
7402  int x;
7403  if (!slave || !master) {
7404  ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
7405  return;
7406  }
7407  for (x = 0; x < MAX_SLAVES; x++) {
7408  if (!master->slaves[x]) {
7409  master->slaves[x] = slave;
7410  break;
7411  }
7412  }
7413  if (x >= MAX_SLAVES) {
7414  ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
7415  master->slaves[MAX_SLAVES - 1] = slave;
7416  }
7417  if (slave->master)
7418  ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
7419  slave->master = master;
7420 
7421  ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
7422 }
7423 
7424 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
7425 {
7426  struct dahdi_pvt *p = ast_channel_tech_pvt(newchan);
7427  int x;
7428 
7429  ast_mutex_lock(&p->lock);
7430 
7431  ast_debug(1, "New owner for channel %d is %s\n", p->channel, ast_channel_name(newchan));
7432  if (p->owner == oldchan) {
7433  p->owner = newchan;
7434  }
7435  for (x = 0; x < 3; x++) {
7436  if (p->subs[x].owner == oldchan) {
7437  if (!x) {
7438  dahdi_master_slave_unlink(NULL, p, 0);
7439  }
7440  p->subs[x].owner = newchan;
7441  }
7442  }
7443  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
7444  analog_fixup(oldchan, newchan, p->sig_pvt);
7445 #if defined(HAVE_PRI)
7446  } else if (dahdi_sig_pri_lib_handles(p->sig)) {
7447  sig_pri_fixup(oldchan, newchan, p->sig_pvt);
7448 #endif /* defined(HAVE_PRI) */
7449 #if defined(HAVE_SS7)
7450  } else if (p->sig == SIG_SS7) {
7451  sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
7452 #endif /* defined(HAVE_SS7) */
7453  }
7454  dahdi_conf_update(p);
7455 
7456  ast_mutex_unlock(&p->lock);
7457 
7458  if (ast_channel_state(newchan) == AST_STATE_RINGING) {
7459  dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
7460  }
7461  return 0;
7462 }
7463 
7464 static int dahdi_ring_phone(struct dahdi_pvt *p)
7465 {
7466  int x;
7467  int res;
7468  /* Make sure our transmit state is on hook */
7469  x = 0;
7470  x = DAHDI_ONHOOK;
7471  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
7472  do {
7473  x = DAHDI_RING;
7474  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
7475  if (res) {
7476  switch (errno) {
7477  case EBUSY:
7478  case EINTR:
7479  /* Wait just in case */
7480  usleep(10000);
7481  continue;
7482  case EINPROGRESS:
7483  res = 0;
7484  break;
7485  default:
7486  ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
7487  res = 0;
7488  }
7489  }
7490  } while (res);
7491  return res;
7492 }
7493 
7494 static void *analog_ss_thread(void *data);
7495 
7496 /*!
7497  * \internal
7498  * \brief Attempt to transfer 3-way call.
7499  *
7500  * \param p DAHDI private structure.
7501  *
7502  * \note On entry these locks are held: real-call, private, 3-way call.
7503  * \note On exit these locks are held: real-call, private.
7504  *
7505  * \retval 0 on success.
7506  * \retval -1 on error.
7507  */
7508 static int attempt_transfer(struct dahdi_pvt *p)
7509 {
7510  struct ast_channel *owner_real;
7511  struct ast_channel *owner_3way;
7512  enum ast_transfer_result xfer_res;
7513  int res = 0;
7514 
7515  owner_real = ast_channel_ref(p->subs[SUB_REAL].owner);
7516  owner_3way = ast_channel_ref(p->subs[SUB_THREEWAY].owner);
7517 
7518  ast_verb(3, "TRANSFERRING %s to %s\n",
7519  ast_channel_name(owner_3way), ast_channel_name(owner_real));
7520 
7521  ast_channel_unlock(owner_real);
7522  ast_channel_unlock(owner_3way);
7523  ast_mutex_unlock(&p->lock);
7524 
7525  xfer_res = ast_bridge_transfer_attended(owner_3way, owner_real);
7526  if (xfer_res != AST_BRIDGE_TRANSFER_SUCCESS) {
7527  ast_softhangup(owner_3way, AST_SOFTHANGUP_DEV);
7528  res = -1;
7529  }
7530 
7531  /* Must leave with these locked. */
7532  ast_channel_lock(owner_real);
7533  ast_mutex_lock(&p->lock);
7534 
7535  ast_channel_unref(owner_real);
7536  ast_channel_unref(owner_3way);
7537 
7538  return res;
7539 }
7540 
7541 static int check_for_conference(struct dahdi_pvt *p)
7542 {
7543  struct dahdi_confinfo ci;
7544  /* Fine if we already have a master, etc */
7545  if (p->master || (p->confno > -1))
7546  return 0;
7547  memset(&ci, 0, sizeof(ci));
7548  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
7549  ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
7550  return 0;
7551  }
7552  /* If we have no master and don't have a confno, then
7553  if we're in a conference, it's probably a MeetMe room or
7554  some such, so don't let us 3-way out! */
7555  if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
7556  ast_verb(3, "Avoiding 3-way call when in an external conference\n");
7557  return 1;
7558  }
7559  return 0;
7560 }
7561 
7562 /*! Checks channel for alarms
7563  * \param p a channel to check for alarms.
7564  * \returns the alarms on the span to which the channel belongs, or alarms on
7565  * the channel if no span alarms.
7566  */
7567 static int get_alarms(struct dahdi_pvt *p)
7568 {
7569  int res;
7570  struct dahdi_spaninfo zi;
7571  struct dahdi_params params;
7572 
7573  memset(&zi, 0, sizeof(zi));
7574  zi.spanno = p->span;
7575 
7576  if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
7577  if (zi.alarms != DAHDI_ALARM_NONE)
7578  return zi.alarms;
7579  } else {
7580  ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
7581  return 0;
7582  }
7583 
7584  /* No alarms on the span. Check for channel alarms. */
7585  memset(&params, 0, sizeof(params));
7586  if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
7587  return params.chan_alarms;
7588 
7589  ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
7590 
7591  return DAHDI_ALARM_NONE;
7592 }
7593 
7594 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
7595 {
7596  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
7597  struct ast_frame *f = *dest;
7598 
7599  ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
7600  f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
7601  (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
7602 
7603  if (p->confirmanswer) {
7604  if (f->frametype == AST_FRAME_DTMF_END) {
7605  ast_debug(1, "Confirm answer on %s!\n", ast_channel_name(ast));
7606  /* Upon receiving a DTMF digit, consider this an answer confirmation instead
7607  of a DTMF digit */
7608  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7610  /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
7611  p->confirmanswer = 0;
7612  } else {
7613  p->subs[idx].f.frametype = AST_FRAME_NULL;
7614  p->subs[idx].f.subclass.integer = 0;
7615  }
7616  *dest = &p->subs[idx].f;
7617  } else if (p->callwaitcas) {
7618  if (f->frametype == AST_FRAME_DTMF_END) {
7619  if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
7620  ast_debug(1, "Got some DTMF, but it's for the CAS\n");
7621  ast_free(p->cidspill);
7622  p->cidspill = NULL;
7623  send_cwcidspill(p);
7624  }
7625  p->callwaitcas = 0;
7626  }
7627  p->subs[idx].f.frametype = AST_FRAME_NULL;
7628  p->subs[idx].f.subclass.integer = 0;
7629  *dest = &p->subs[idx].f;
7630  } else if (f->subclass.integer == 'f') {
7631  if (f->frametype == AST_FRAME_DTMF_END) {
7632  /* Fax tone -- Handle and return NULL */
7633  if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
7634  /* If faxbuffers are configured, use them for the fax transmission */
7635  if (p->usefaxbuffers && !p->bufferoverrideinuse) {
7636  struct dahdi_bufferinfo bi = {
7637  .txbufpolicy = p->faxbuf_policy,
7638  .bufsize = p->bufsize,
7639  .numbufs = p->faxbuf_no
7640  };
7641  int res;
7642 
7643  if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
7644  ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
7645  } else {
7646  p->bufferoverrideinuse = 1;
7647  }
7648  }
7649  p->faxhandled = 1;
7650  if (p->dsp) {
7651  p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
7653  ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
7654  }
7655  if (strcmp(ast_channel_exten(ast), "fax")) {
7656  const char *target_context = ast_channel_context(ast);
7657 
7658  /*
7659  * We need to unlock 'ast' here because ast_exists_extension has the
7660  * potential to start autoservice on the channel. Such action is prone
7661  * to deadlock if the channel is locked.
7662  *
7663  * ast_async_goto() has its own restriction on not holding the
7664  * channel lock.
7665  */
7666  ast_mutex_unlock(&p->lock);
7667  ast_channel_unlock(ast);
7668  if (ast_exists_extension(ast, target_context, "fax", 1,
7669  S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
7670  ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
7671  /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
7672  pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
7673  if (ast_async_goto(ast, target_context, "fax", 1))
7674  ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
7675  } else {
7676  ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
7677  }
7678  ast_channel_lock(ast);
7679  ast_mutex_lock(&p->lock);
7680  } else {
7681  ast_debug(1, "Already in a fax extension, not redirecting\n");
7682  }
7683  } else {
7684  ast_debug(1, "Fax already handled\n");
7685  }
7686  dahdi_confmute(p, 0);
7687  }
7688  p->subs[idx].f.frametype = AST_FRAME_NULL;
7689  p->subs[idx].f.subclass.integer = 0;
7690  *dest = &p->subs[idx].f;
7691  }
7692 }
7693 
7694 static void publish_span_alarm(int span, const char *alarm_txt)
7695 {
7696  RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
7697 
7698  body = ast_json_pack("{s: i, s: s}",
7699  "Span", span,
7700  "Alarm", alarm_txt);
7701  if (!body) {
7702  return;
7703  }
7704 
7705  ast_manager_publish_event("SpanAlarm", EVENT_FLAG_SYSTEM, body);
7706 }
7707 
7708 static void publish_channel_alarm(int channel, const char *alarm_txt)
7709 {
7710  RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
7711  RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free);
7712  if (!dahdi_chan) {
7713  return;
7714  }
7715 
7716  ast_str_set(&dahdi_chan, 0, "%d", channel);
7717  body = ast_json_pack("{s: s, s: s}",
7718  "DAHDIChannel", ast_str_buffer(dahdi_chan),
7719  "Alarm", alarm_txt);
7720  if (!body) {
7721  return;
7722  }
7723 
7724  ast_manager_publish_event("Alarm", EVENT_FLAG_SYSTEM, body);
7725 }
7726 
7727 static void handle_alarms(struct dahdi_pvt *p, int alms)
7728 {
7729  const char *alarm_str;
7730 
7731 #if defined(HAVE_PRI)
7732  if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
7733  return;
7734  }
7735 #endif /* defined(HAVE_PRI) */
7736 
7737  alarm_str = alarm2str(alms);
7738  if (report_alarms & REPORT_CHANNEL_ALARMS) {
7739  ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
7740  publish_channel_alarm(p->channel, alarm_str);
7741  }
7742 
7743  if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
7744  ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
7745  publish_span_alarm(p->span, alarm_str);
7746  }
7747 }
7748 
7749 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
7750 {
7751  int res, x;
7752  int idx, mysig;
7753  char *c;
7754  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
7755  pthread_t threadid;
7756  struct ast_channel *chan;
7757  struct ast_frame *f;
7758 
7759  idx = dahdi_get_index(ast, p, 0);
7760  if (idx < 0) {
7761  return &ast_null_frame;
7762  }
7763  mysig = p->sig;
7764  if (p->outsigmod > -1)
7765  mysig = p->outsigmod;
7766  p->subs[idx].f.frametype = AST_FRAME_NULL;
7767  p->subs[idx].f.subclass.integer = 0;
7768  p->subs[idx].f.datalen = 0;
7769  p->subs[idx].f.samples = 0;
7770  p->subs[idx].f.mallocd = 0;
7771  p->subs[idx].f.offset = 0;
7772  p->subs[idx].f.src = "dahdi_handle_event";
7773  p->subs[idx].f.data.ptr = NULL;
7774  f = &p->subs[idx].f;
7775 
7776  if (p->fake_event) {
7777  res = p->fake_event;
7778  p->fake_event = 0;
7779  } else
7780  res = dahdi_get_event(p->subs[idx].dfd);
7781 
7782  ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
7783 
7784  if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
7785  p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
7786  ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
7787 #if defined(HAVE_PRI)
7788  if (dahdi_sig_pri_lib_handles(p->sig)
7789  && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
7790  && p->pri
7791  && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
7792  /* absorb event */
7793  } else
7794 #endif /* defined(HAVE_PRI) */
7795  {
7796  /* Unmute conference */
7797  dahdi_confmute(p, 0);
7798  p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
7799  p->subs[idx].f.subclass.integer = res & 0xff;
7800  dahdi_handle_dtmf(ast, idx, &f);
7801  }
7802  return f;
7803  }
7804 
7805  if (res & DAHDI_EVENT_DTMFDOWN) {
7806  ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
7807 #if defined(HAVE_PRI)
7808  if (dahdi_sig_pri_lib_handles(p->sig)
7809  && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
7810  && p->pri
7811  && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
7812  /* absorb event */
7813  } else
7814 #endif /* defined(HAVE_PRI) */
7815  {
7816  /* Mute conference */
7817  dahdi_confmute(p, 1);
7819  p->subs[idx].f.subclass.integer = res & 0xff;
7820  dahdi_handle_dtmf(ast, idx, &f);
7821  }
7822  return &p->subs[idx].f;
7823  }
7824 
7825  switch (res) {
7826  case DAHDI_EVENT_EC_DISABLED:
7827  ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
7828  p->echocanon = 0;
7829  break;
7830 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
7831  case DAHDI_EVENT_TX_CED_DETECTED:
7832  ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
7833  break;
7834  case DAHDI_EVENT_RX_CED_DETECTED:
7835  ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
7836  break;
7837  case DAHDI_EVENT_EC_NLP_DISABLED:
7838  ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
7839  break;
7840  case DAHDI_EVENT_EC_NLP_ENABLED:
7841  ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
7842  break;
7843 #endif
7844  case DAHDI_EVENT_BITSCHANGED:
7845 #ifdef HAVE_OPENR2
7846  if (p->sig != SIG_MFCR2) {
7847  ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
7848  } else {
7849  ast_debug(1, "bits changed in chan %d\n", p->channel);
7850  openr2_chan_handle_cas(p->r2chan);
7851  }
7852 #else
7853  ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
7854 #endif
7855  break;
7856  case DAHDI_EVENT_PULSE_START:
7857  /* Stop tone if there's a pulse start and the PBX isn't started */
7858  if (!ast_channel_pbx(ast))
7859  tone_zone_play_tone(p->subs[idx].dfd, -1);
7860  break;
7861  case DAHDI_EVENT_DIALCOMPLETE:
7862  /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
7863 #if defined(HAVE_PRI)
7864  if (dahdi_sig_pri_lib_handles(p->sig)) {
7865  if (p->inalarm) {
7866  break;
7867  }
7868  if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
7869  ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",
7870  ast_channel_name(ast), strerror(errno));
7871  return NULL;
7872  }
7873  if (x) {
7874  /* Still dialing in DAHDI driver */
7875  break;
7876  }
7877  /*
7878  * The ast channel is locked and the private may be locked more
7879  * than once.
7880  */
7881  sig_pri_dial_complete(p->sig_pvt, ast);
7882  break;
7883  }
7884 #endif /* defined(HAVE_PRI) */
7885 #ifdef HAVE_OPENR2
7886  if ((p->sig & SIG_MFCR2) && p->r2chan && ast_channel_state(ast) != AST_STATE_UP) {
7887  /* we don't need to do anything for this event for R2 signaling
7888  if the call is being setup */
7889  break;
7890  }
7891 #endif
7892  if (p->inalarm) break;
7893  if ((p->radio || (p->oprmode < 0))) break;
7894  if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
7895  ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",ast_channel_name(ast), strerror(errno));
7896  return NULL;
7897  }
7898  if (!x) { /* if not still dialing in driver */
7899  dahdi_ec_enable(p);
7900  if (p->echobreak) {
7901  dahdi_train_ec(p);
7902  ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
7903  p->dop.op = DAHDI_DIAL_OP_REPLACE;
7904  res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
7905  p->echobreak = 0;
7906  } else {
7907  p->dialing = 0;
7908  if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
7909  /* if thru with dialing after offhook */
7911  ast_setstate(ast, AST_STATE_UP);
7912  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7914  break;
7915  } else { /* if to state wait for offhook to dial rest */
7916  /* we now wait for off hook */
7918  }
7919  }
7920  if (ast_channel_state(ast) == AST_STATE_DIALING) {
7921  if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
7922  ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
7923  } else if (p->confirmanswer || (!p->dialednone
7924  && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
7925  || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
7926  || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
7927  || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
7928  || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
7929  || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
7930  || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
7931  || (mysig == SIG_SF_FEATB)))) {
7933  } else if (!p->answeronpolarityswitch) {
7934  ast_setstate(ast, AST_STATE_UP);
7935  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7937  /* If aops=0 and hops=1, this is necessary */
7938  p->polarity = POLARITY_REV;
7939  } else {
7940  /* Start clean, so we can catch the change to REV polarity when party answers */
7941  p->polarity = POLARITY_IDLE;
7942  }
7943  }
7944  }
7945  }
7946  break;
7947  case DAHDI_EVENT_ALARM:
7948  switch (p->sig) {
7949 #if defined(HAVE_PRI)
7950  case SIG_PRI_LIB_HANDLE_CASES:
7951  sig_pri_chan_alarm_notify(p->sig_pvt, 0);
7952  break;
7953 #endif /* defined(HAVE_PRI) */
7954 #if defined(HAVE_SS7)
7955  case SIG_SS7:
7956  sig_ss7_set_alarm(p->sig_pvt, 1);
7957  break;
7958 #endif /* defined(HAVE_SS7) */
7959  default:
7960  p->inalarm = 1;
7961  break;
7962  }
7963  res = get_alarms(p);
7964  handle_alarms(p, res);
7965 #ifdef HAVE_PRI
7966  if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
7967  /* fall through intentionally */
7968  } else {
7969  break;
7970  }
7971 #endif
7972 #if defined(HAVE_SS7)
7973  if (p->sig == SIG_SS7)
7974  break;
7975 #endif /* defined(HAVE_SS7) */
7976 #ifdef HAVE_OPENR2
7977  if (p->sig == SIG_MFCR2)
7978  break;
7979 #endif
7980  case DAHDI_EVENT_ONHOOK:
7981  if (p->radio) {
7982  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7984  break;
7985  }
7986  if (p->oprmode < 0)
7987  {
7988  if (p->oprmode != -1) { /* Operator flash recall */
7989  ast_verb(4, "Operator mode enabled on channel %d, holding line for channel %d\n", p->channel, p->oprpeer->channel);
7990  break;
7991  }
7992  /* Otherwise, immediate recall */
7993  if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
7994  {
7995  /* Make sure it starts ringing */
7996  dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
7997  dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
7998  save_conference(p->oprpeer);
7999  tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
8000  ast_verb(4, "Operator recall, channel %d ringing back channel %d\n", p->oprpeer->channel, p->channel);
8001  }
8002  break;
8003  }
8004  switch (p->sig) {
8005  case SIG_FXOLS:
8006  case SIG_FXOGS:
8007  case SIG_FXOKS:
8008  /* Check for some special conditions regarding call waiting */
8009  if (idx == SUB_REAL) {
8010  /* The normal line was hung up */
8011  if (p->subs[SUB_CALLWAIT].owner) {
8012  /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
8013  swap_subs(p, SUB_CALLWAIT, SUB_REAL);
8014  ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
8015  unalloc_sub(p, SUB_CALLWAIT);
8016 #if 0
8017  p->subs[idx].needanswer = 0;
8018  p->subs[idx].needringing = 0;
8019 #endif
8020  p->callwaitingrepeat = 0;
8021  p->cidcwexpire = 0;
8022  p->cid_suppress_expire = 0;
8023  p->owner = NULL;
8024  /* Don't start streaming audio yet if the incoming call isn't up yet */
8025  if (ast_channel_state(p->subs[SUB_REAL].owner) != AST_STATE_UP)
8026  p->dialing = 1;
8027  dahdi_ring_phone(p);
8028  } else if (p->subs[SUB_THREEWAY].owner) {
8029  unsigned int mssinceflash;
8030  /* Here we have to retain the lock on both the main channel, the 3-way channel, and
8031  the private structure -- not especially easy or clean */
8032  while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
8033  /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
8034  DLA_UNLOCK(&p->lock);
8035  CHANNEL_DEADLOCK_AVOIDANCE(ast);
8036  /* We can grab ast and p in that order, without worry. We should make sure
8037  nothing seriously bad has happened though like some sort of bizarre double
8038  masquerade! */
8039  DLA_LOCK(&p->lock);
8040  if (p->owner != ast) {
8041  ast_log(LOG_WARNING, "This isn't good...\n");
8042  return NULL;
8043  }
8044  }
8045  if (!p->subs[SUB_THREEWAY].owner) {
8046  ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
8047  return NULL;
8048  }
8049  mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
8050  ast_debug(1, "Last flash was %u ms ago\n", mssinceflash);
8051  if (mssinceflash < MIN_MS_SINCE_FLASH) {
8052  /* It hasn't been long enough since the last flashook. This is probably a bounce on
8053  hanging up. Hangup both channels now */
8054  if (p->subs[SUB_THREEWAY].owner)
8055  ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
8056  ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
8057  ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
8058  ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
8059  } else if ((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) {
8060  if (p->transfer) {
8061  /* In any case this isn't a threeway call anymore */
8062  p->subs[SUB_REAL].inthreeway = 0;
8063  p->subs[SUB_THREEWAY].inthreeway = 0;
8064  /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
8065  if (!p->transfertobusy && ast_channel_state(ast) == AST_STATE_BUSY) {
8066  ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
8067  /* Swap subs and dis-own channel */
8068  swap_subs(p, SUB_THREEWAY, SUB_REAL);
8069  p->owner = NULL;
8070  /* Ring the phone */
8071  dahdi_ring_phone(p);
8072  } else if (!attempt_transfer(p)) {
8073  /*
8074  * Transfer successful. Don't actually hang up at this point.
8075  * Let our channel legs of the calls die off as the transfer
8076  * percolates through the core.
8077  */
8078  break;
8079  }
8080  } else {
8081  ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
8082  if (p->subs[SUB_THREEWAY].owner)
8083  ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
8084  }
8085  } else {
8086  ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
8087  /* Swap subs and dis-own channel */
8088  swap_subs(p, SUB_THREEWAY, SUB_REAL);
8089  p->owner = NULL;
8090  /* Ring the phone */
8091  dahdi_ring_phone(p);
8092  }
8093  }
8094  } else {
8095  ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
8096  }
8097  /* Fall through */
8098  default:
8099  dahdi_ec_disable(p);
8100  return NULL;
8101  }
8102  break;
8103  case DAHDI_EVENT_RINGOFFHOOK:
8104  if (p->inalarm) break;
8105  if (p->oprmode < 0)
8106  {
8107  if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
8108  {
8109  /* Make sure it stops ringing */
8110  dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
8111  tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
8112  restore_conference(p->oprpeer);
8113  ast_debug(1, "Operator recall by channel %d for channel %d complete\n", p->oprpeer->channel, p->channel);
8114  }
8115  break;
8116  }
8117  if (p->radio)
8118  {
8119  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8121  break;
8122  }
8123  /* for E911, its supposed to wait for offhook then dial
8124  the second half of the dial string */
8125  if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast_channel_state(ast) == AST_STATE_DIALING_OFFHOOK)) {
8126  c = strchr(p->dialdest, '/');
8127  if (c)
8128  c++;
8129  else
8130  c = p->dialdest;
8131 
8132  if (*c) {
8133  int numchars = snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
8134  if (numchars >= sizeof(p->dop.dialstr)) {
8135  ast_log(LOG_WARNING, "Dial string '%s' truncated\n", c);
8136  }
8137  } else {
8138  ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
8139  }
8140 
8141  if (strlen(p->dop.dialstr) > 4) {
8142  memset(p->echorest, 'w', sizeof(p->echorest) - 1);
8143  strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
8144  p->echorest[sizeof(p->echorest) - 1] = '\0';
8145  p->echobreak = 1;
8146  p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
8147  } else
8148  p->echobreak = 0;
8149  if (dahdi_dial_str(p, p->dop.op, p->dop.dialstr)) {
8150  x = DAHDI_ONHOOK;
8151  ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
8152  return NULL;
8153  }
8154  p->dialing = 1;
8155  return &p->subs[idx].f;
8156  }
8157  switch (p->sig) {
8158  case SIG_FXOLS:
8159  case SIG_FXOGS:
8160  case SIG_FXOKS:
8161  switch (ast_channel_state(ast)) {
8162  case AST_STATE_RINGING:
8163  dahdi_ec_enable(p);
8164  dahdi_train_ec(p);
8165  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8167  /* Make sure it stops ringing */
8168  p->subs[SUB_REAL].needringing = 0;
8169  dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
8170  ast_debug(1, "channel %d answered\n", p->channel);
8171 
8172  /* Cancel any running CallerID spill */
8173  ast_free(p->cidspill);
8174  p->cidspill = NULL;
8175  restore_conference(p);
8176 
8177  p->dialing = 0;
8178  p->callwaitcas = 0;
8179  if (p->confirmanswer) {
8180  /* Ignore answer if "confirm answer" is enabled */
8181  p->subs[idx].f.frametype = AST_FRAME_NULL;
8182  p->subs[idx].f.subclass.integer = 0;
8183  } else if (!ast_strlen_zero(p->dop.dialstr)) {
8184  /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
8185  res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8186  if (res) {
8187  p->dop.dialstr[0] = '\0';
8188  return NULL;
8189  } else {
8190  ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
8191  p->subs[idx].f.frametype = AST_FRAME_NULL;
8192  p->subs[idx].f.subclass.integer = 0;
8193  p->dialing = 1;
8194  }
8195  p->dop.dialstr[0] = '\0';
8197  } else
8198  ast_setstate(ast, AST_STATE_UP);
8199  return &p->subs[idx].f;
8200  case AST_STATE_DOWN:
8202  ast_channel_rings_set(ast, 1);
8203  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8205  ast_debug(1, "channel %d picked up\n", p->channel);
8206  return &p->subs[idx].f;
8207  case AST_STATE_UP:
8208  /* Make sure it stops ringing */
8209  dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
8210  /* Okay -- probably call waiting*/
8211  ast_queue_unhold(p->owner);
8212  p->subs[idx].needunhold = 1;
8213  break;
8214  case AST_STATE_RESERVED:
8215  /* Start up dialtone */
8216  if (has_voicemail(p))
8217  res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
8218  else
8219  res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
8220  break;
8221  default:
8222  ast_log(LOG_WARNING, "FXO phone off hook in weird state %u??\n", ast_channel_state(ast));
8223  }
8224  break;
8225  case SIG_FXSLS:
8226  case SIG_FXSGS:
8227  case SIG_FXSKS:
8228  if (ast_channel_state(ast) == AST_STATE_RING) {
8229  p->ringt = p->ringt_base;
8230  }
8231 
8232  /* If we get a ring then we cannot be in
8233  * reversed polarity. So we reset to idle */
8234  ast_debug(1, "Setting IDLE polarity due "
8235  "to ring. Old polarity was %d\n",
8236  p->polarity);
8237  p->polarity = POLARITY_IDLE;
8238 
8239  /* Fall through */
8240  case SIG_EM:
8241  case SIG_EM_E1:
8242  case SIG_EMWINK:
8243  case SIG_FEATD:
8244  case SIG_FEATDMF:
8245  case SIG_FEATDMF_TA:
8246  case SIG_E911:
8247  case SIG_FGC_CAMA:
8248  case SIG_FGC_CAMAMF:
8249  case SIG_FEATB:
8250  case SIG_SF:
8251  case SIG_SFWINK:
8252  case SIG_SF_FEATD:
8253  case SIG_SF_FEATDMF:
8254  case SIG_SF_FEATB:
8258  ast_debug(1, "Ring detected\n");
8259  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8261  } else if (p->outgoing && ((ast_channel_state(ast) == AST_STATE_RINGING) || (ast_channel_state(ast) == AST_STATE_DIALING))) {
8262  ast_debug(1, "Line answered\n");
8263  if (p->confirmanswer) {
8264  p->subs[idx].f.frametype = AST_FRAME_NULL;
8265  p->subs[idx].f.subclass.integer = 0;
8266  } else {
8267  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8269  ast_setstate(ast, AST_STATE_UP);
8270  }
8271  } else if (ast_channel_state(ast) != AST_STATE_RING)
8272  ast_log(LOG_WARNING, "Ring/Off-hook in strange state %u on channel %d\n", ast_channel_state(ast), p->channel);
8273  break;
8274  default:
8275  ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
8276  }
8277  break;
8278  case DAHDI_EVENT_RINGBEGIN:
8279  switch (p->sig) {
8280  case SIG_FXSLS:
8281  case SIG_FXSGS:
8282  case SIG_FXSKS:
8283  if (ast_channel_state(ast) == AST_STATE_RING) {
8284  p->ringt = p->ringt_base;
8285  }
8286  break;
8287  }
8288  break;
8289  case DAHDI_EVENT_RINGERON:
8290  break;
8291  case DAHDI_EVENT_NOALARM:
8292  switch (p->sig) {
8293 #if defined(HAVE_PRI)
8294  case SIG_PRI_LIB_HANDLE_CASES:
8295  sig_pri_chan_alarm_notify(p->sig_pvt, 1);
8296  break;
8297 #endif /* defined(HAVE_PRI) */
8298 #if defined(HAVE_SS7)
8299  case SIG_SS7:
8300  sig_ss7_set_alarm(p->sig_pvt, 0);
8301  break;
8302 #endif /* defined(HAVE_SS7) */
8303  default:
8304  p->inalarm = 0;
8305  break;
8306  }
8307  handle_clear_alarms(p);
8308  break;
8309  case DAHDI_EVENT_WINKFLASH:
8310  if (p->inalarm) break;
8311  if (p->radio) break;
8312  if (p->oprmode < 0) break;
8313  if (p->oprmode > 1)
8314  {
8315  struct dahdi_params par;
8316 
8317  memset(&par, 0, sizeof(par));
8318  if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
8319  {
8320  if (!par.rxisoffhook)
8321  {
8322  /* Make sure it stops ringing */
8323  dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
8324  dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
8325  save_conference(p);
8326  tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
8327  ast_verb(4, "Operator flash recall, channel %d ringing back channel %d\n", p->oprpeer->channel, p->channel);
8328  }
8329  }
8330  break;
8331  }
8332  /* Remember last time we got a flash-hook */
8333  p->flashtime = ast_tvnow();
8334  switch (mysig) {
8335  case SIG_FXOLS:
8336  case SIG_FXOGS:
8337  case SIG_FXOKS:
8338  ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
8339  idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
8340 
8341  /* Cancel any running CallerID spill */
8342  ast_free(p->cidspill);
8343  p->cidspill = NULL;
8344  restore_conference(p);
8345  p->callwaitcas = 0;
8346 
8347  if (idx != SUB_REAL) {
8348  ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
8349  goto winkflashdone;
8350  }
8351 
8352  if (p->subs[SUB_CALLWAIT].owner) {
8353  /* Swap to call-wait */
8354  swap_subs(p, SUB_REAL, SUB_CALLWAIT);
8355  tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
8356  p->owner = p->subs[SUB_REAL].owner;
8357  ast_debug(1, "Making %s the new owner\n", ast_channel_name(p->owner));
8360  p->subs[SUB_REAL].needanswer = 1;
8361  }
8362  p->callwaitingrepeat = 0;
8363  p->cidcwexpire = 0;
8364  p->cid_suppress_expire = 0;
8365  /* Start music on hold if appropriate */
8366  if (!p->subs[SUB_CALLWAIT].inthreeway) {
8367  ast_queue_hold(p->subs[SUB_CALLWAIT].owner, p->mohsuggest);
8368  }
8369  p->subs[SUB_CALLWAIT].needhold = 1;
8370  ast_queue_hold(p->subs[SUB_REAL].owner, p->mohsuggest);
8371  p->subs[SUB_REAL].needunhold = 1;
8372  } else if (!p->subs[SUB_THREEWAY].owner) {
8373  if (!p->threewaycalling) {
8374  /* Just send a flash if no 3-way calling */
8375  p->subs[SUB_REAL].needflash = 1;
8376  goto winkflashdone;
8377  } else if (!check_for_conference(p)) {
8378  ast_callid callid = 0;
8379  int callid_created;
8380  char cid_num[256];
8381  char cid_name[256];
8382 
8383  cid_num[0] = 0;
8384  cid_name[0] = 0;
8385  if (p->dahditrcallerid && p->owner) {
8386  if (ast_channel_caller(p->owner)->id.number.valid
8387  && ast_channel_caller(p->owner)->id.number.str) {
8388  ast_copy_string(cid_num, ast_channel_caller(p->owner)->id.number.str,
8389  sizeof(cid_num));
8390  }
8391  if (ast_channel_caller(p->owner)->id.name.valid
8392  && ast_channel_caller(p->owner)->id.name.str) {
8393  ast_copy_string(cid_name, ast_channel_caller(p->owner)->id.name.str,
8394  sizeof(cid_name));
8395  }
8396  }
8397  /* XXX This section needs much more error checking!!! XXX */
8398  /* Start a 3-way call if feasible */
8399  if (!((ast_channel_pbx(ast)) ||
8400  (ast_channel_state(ast) == AST_STATE_UP) ||
8401  (ast_channel_state(ast) == AST_STATE_RING))) {
8402  ast_debug(1, "Flash when call not up or ringing\n");
8403  goto winkflashdone;
8404  }
8405  if (alloc_sub(p, SUB_THREEWAY)) {
8406  ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
8407  goto winkflashdone;
8408  }
8409  callid_created = ast_callid_threadstorage_auto(&callid);
8410  /*
8411  * Make new channel
8412  *
8413  * We cannot hold the p or ast locks while creating a new
8414  * channel.
8415  */
8416  ast_mutex_unlock(&p->lock);
8417  ast_channel_unlock(ast);
8418  chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL, NULL, callid);
8419  ast_channel_lock(ast);
8420  ast_mutex_lock(&p->lock);
8421  if (p->dahditrcallerid) {
8422  if (!p->origcid_num)
8423  p->origcid_num = ast_strdup(p->cid_num);
8424  if (!p->origcid_name)
8425  p->origcid_name = ast_strdup(p->cid_name);
8426  ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
8427  ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
8428  }
8429  /* Swap things around between the three-way and real call */
8430  swap_subs(p, SUB_THREEWAY, SUB_REAL);
8431  /* Disable echo canceller for better dialing */
8432  dahdi_ec_disable(p);
8433  res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
8434  if (res)
8435  ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
8436  p->owner = chan;
8437  if (!chan) {
8438  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
8439  } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
8440  ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
8441  res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
8442  dahdi_ec_enable(p);
8443  ast_hangup(chan);
8444  } else {
8445  ast_verb(3, "Started three way call on channel %d\n", p->channel);
8446 
8447  /* Start music on hold */
8448  ast_queue_hold(p->subs[SUB_THREEWAY].owner, p->mohsuggest);
8449  p->subs[SUB_THREEWAY].needhold = 1;
8450  }
8451  ast_callid_threadstorage_auto_clean(callid, callid_created);
8452  }
8453  } else {
8454  /* Already have a 3 way call */
8455  if (p->subs[SUB_THREEWAY].inthreeway) {
8456  /* Call is already up, drop the last person */
8457  ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
8458  /* If the primary call isn't answered yet, use it */
8460  /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
8461  swap_subs(p, SUB_THREEWAY, SUB_REAL);
8462  p->owner = p->subs[SUB_REAL].owner;
8463  }
8464  /* Drop the last call and stop the conference */
8465  ast_verb(3, "Dropping three-way call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
8466  ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
8467  p->subs[SUB_REAL].inthreeway = 0;
8468  p->subs[SUB_THREEWAY].inthreeway = 0;
8469  } else {
8470  /* Lets see what we're up to */
8471  if (((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) &&
8472  (p->transfertobusy || (ast_channel_state(ast) != AST_STATE_BUSY))) {
8473  int otherindex = SUB_THREEWAY;
8474 
8475  ast_verb(3, "Building conference call with %s and %s\n",
8476  ast_channel_name(p->subs[SUB_THREEWAY].owner),
8477  ast_channel_name(p->subs[SUB_REAL].owner));
8478  /* Put them in the threeway, and flip */
8479  p->subs[SUB_THREEWAY].inthreeway = 1;
8480  p->subs[SUB_REAL].inthreeway = 1;
8481  if (ast_channel_state(ast) == AST_STATE_UP) {
8482  swap_subs(p, SUB_THREEWAY, SUB_REAL);
8483  otherindex = SUB_REAL;
8484  }
8485  if (p->subs[otherindex].owner) {
8486  ast_queue_unhold(p->subs[otherindex].owner);
8487  }
8488  p->subs[otherindex].needunhold = 1;
8489  p->owner = p->subs[SUB_REAL].owner;
8490  } else {
8491  ast_verb(3, "Dumping incomplete call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
8492  swap_subs(p, SUB_THREEWAY, SUB_REAL);
8493  ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
8494  p->owner = p->subs[SUB_REAL].owner;
8495  if (p->subs[SUB_REAL].owner) {
8496  ast_queue_unhold(p->subs[SUB_REAL].owner);
8497  }
8498  p->subs[SUB_REAL].needunhold = 1;
8499  dahdi_ec_enable(p);
8500  }
8501  }
8502  }
8503 winkflashdone:
8504  dahdi_conf_update(p);
8505  break;
8506  case SIG_EM:
8507  case SIG_EM_E1:
8508  case SIG_FEATD:
8509  case SIG_SF:
8510  case SIG_SFWINK:
8511  case SIG_SF_FEATD:
8512  case SIG_FXSLS:
8513  case SIG_FXSGS:
8514  if (p->dialing)
8515  ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
8516  else
8517  ast_debug(1, "Got wink in weird state %u on channel %d\n", ast_channel_state(ast), p->channel);
8518  break;
8519  case SIG_FEATDMF_TA:
8520  switch (p->whichwink) {
8521  case 0:
8522  ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", ast_channel_caller(p->owner)->ani2,
8523  S_COR(ast_channel_caller(p->owner)->ani.number.valid,
8524  ast_channel_caller(p->owner)->ani.number.str, ""));
8525  snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
8526  ast_channel_caller(p->owner)->ani2,
8527  S_COR(ast_channel_caller(p->owner)->ani.number.valid,
8528  ast_channel_caller(p->owner)->ani.number.str, ""));
8529  break;
8530  case 1:
8531  ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
8532  break;
8533  case 2:
8534  ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
8535  return NULL;
8536  }
8537  p->whichwink++;
8538  /* Fall through */
8539  case SIG_FEATDMF:
8540  case SIG_E911:
8541  case SIG_FGC_CAMAMF:
8542  case SIG_FGC_CAMA:
8543  case SIG_FEATB:
8544  case SIG_SF_FEATDMF:
8545  case SIG_SF_FEATB:
8546  case SIG_EMWINK:
8547  /* FGD MF and EMWINK *Must* wait for wink */
8548  if (!ast_strlen_zero(p->dop.dialstr)) {
8549  res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8550  if (res) {
8551  p->dop.dialstr[0] = '\0';
8552  return NULL;
8553  } else
8554  ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
8555  }
8556  p->dop.dialstr[0] = '\0';
8557  break;
8558  default:
8559  ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
8560  }
8561  break;
8562  case DAHDI_EVENT_HOOKCOMPLETE:
8563  if (p->inalarm) break;
8564  if ((p->radio || (p->oprmode < 0))) break;
8565  if (p->waitingfordt.tv_sec) break;
8566  switch (mysig) {
8567  case SIG_FXSLS: /* only interesting for FXS */
8568  case SIG_FXSGS:
8569  case SIG_FXSKS:
8570  case SIG_EM:
8571  case SIG_EM_E1:
8572  case SIG_EMWINK:
8573  case SIG_FEATD:
8574  case SIG_SF:
8575  case SIG_SFWINK:
8576  case SIG_SF_FEATD:
8577  if (!ast_strlen_zero(p->dop.dialstr)) {
8578  res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8579  if (res) {
8580  p->dop.dialstr[0] = '\0';
8581  return NULL;
8582  } else
8583  ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
8584  }
8585  p->dop.dialstr[0] = '\0';
8586  p->dop.op = DAHDI_DIAL_OP_REPLACE;
8587  break;
8588  case SIG_FEATDMF:
8589  case SIG_FEATDMF_TA:
8590  case SIG_E911:
8591  case SIG_FGC_CAMA:
8592  case SIG_FGC_CAMAMF:
8593  case SIG_FEATB:
8594  case SIG_SF_FEATDMF:
8595  case SIG_SF_FEATB:
8596  ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
8597  break;
8598  default:
8599  break;
8600  }
8601  break;
8602  case DAHDI_EVENT_POLARITY:
8603  /*
8604  * If we get a Polarity Switch event, check to see
8605  * if we should change the polarity state and
8606  * mark the channel as UP or if this is an indication
8607  * of remote end disconnect.
8608  */
8609  if (p->polarity == POLARITY_IDLE) {
8610  p->polarity = POLARITY_REV;
8611  if (p->answeronpolarityswitch &&
8612  ((ast_channel_state(ast) == AST_STATE_DIALING) ||
8613  (ast_channel_state(ast) == AST_STATE_RINGING))) {
8614  ast_debug(1, "Answering on polarity switch!\n");
8616  if (p->hanguponpolarityswitch) {
8617  p->polaritydelaytv = ast_tvnow();
8618  }
8619  } else
8620  ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %u\n", p->channel, ast_channel_state(ast));
8621  }
8622  /* Removed else statement from here as it was preventing hangups from ever happening*/
8623  /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
8624  if (p->hanguponpolarityswitch &&
8625  (p->polarityonanswerdelay > 0) &&
8626  (p->polarity == POLARITY_REV) &&
8627  ((ast_channel_state(ast) == AST_STATE_UP) || (ast_channel_state(ast) == AST_STATE_RING)) ) {
8628  /* Added log_debug information below to provide a better indication of what is going on */
8629  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) );
8630 
8632  ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
8634  p->polarity = POLARITY_IDLE;
8635  } else
8636  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));
8637 
8638  } else {
8639  p->polarity = POLARITY_IDLE;
8640  ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %u\n", p->channel, ast_channel_state(ast));
8641  }
8642  /* Added more log_debug information below to provide a better indication of what is going on */
8643  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) );
8644  break;
8645  default:
8646  ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
8647  }
8648  return &p->subs[idx].f;
8649 }
8650 
8651 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
8652 {
8653  int res;
8654  int idx;
8655  struct ast_frame *f;
8656  int usedindex = -1;
8657  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8658 
8659  if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
8660  idx = SUB_REAL;
8661  }
8662 
8663  p->subs[idx].f.frametype = AST_FRAME_NULL;
8664  p->subs[idx].f.datalen = 0;
8665  p->subs[idx].f.samples = 0;
8666  p->subs[idx].f.mallocd = 0;
8667  p->subs[idx].f.offset = 0;
8668  p->subs[idx].f.subclass.integer = 0;
8669  p->subs[idx].f.delivery = ast_tv(0,0);
8670  p->subs[idx].f.src = "dahdi_exception";
8671  p->subs[idx].f.data.ptr = NULL;
8672 
8673 
8674  if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
8675  /* If nobody owns us, absorb the event appropriately, otherwise
8676  we loop indefinitely. This occurs when, during call waiting, the
8677  other end hangs up our channel so that it no longer exists, but we
8678  have neither FLASH'd nor ONHOOK'd to signify our desire to
8679  change to the other channel. */
8680  if (p->fake_event) {
8681  res = p->fake_event;
8682  p->fake_event = 0;
8683  } else
8684  res = dahdi_get_event(p->subs[SUB_REAL].dfd);
8685  /* Switch to real if there is one and this isn't something really silly... */
8686  if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
8687  (res != DAHDI_EVENT_HOOKCOMPLETE)) {
8688  ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
8689  p->owner = p->subs[SUB_REAL].owner;
8690  if (p->owner) {
8691  ast_queue_unhold(p->owner);
8692  }
8693  p->subs[SUB_REAL].needunhold = 1;
8694  }
8695  switch (res) {
8696  case DAHDI_EVENT_ONHOOK:
8697  dahdi_ec_disable(p);
8698  if (p->owner) {
8699  ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
8700  dahdi_ring_phone(p);
8701  p->callwaitingrepeat = 0;
8702  p->cidcwexpire = 0;
8703  p->cid_suppress_expire = 0;
8704  } else
8705  ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8706  dahdi_conf_update(p);
8707  break;
8708  case DAHDI_EVENT_RINGOFFHOOK:
8709  dahdi_ec_enable(p);
8710  dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
8711  if (p->owner && (ast_channel_state(p->owner) == AST_STATE_RINGING)) {
8712  p->subs[SUB_REAL].needanswer = 1;
8713  p->dialing = 0;
8714  }
8715  break;
8716  case DAHDI_EVENT_HOOKCOMPLETE:
8717  case DAHDI_EVENT_RINGERON:
8718  case DAHDI_EVENT_RINGEROFF:
8719  /* Do nothing */
8720  break;
8721  case DAHDI_EVENT_WINKFLASH:
8722  p->flashtime = ast_tvnow();
8723  if (p->owner) {
8724  ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, ast_channel_name(p->owner));
8725  if (ast_channel_state(p->owner) != AST_STATE_UP) {
8726  /* Answer if necessary */
8727  usedindex = dahdi_get_index(p->owner, p, 0);
8728  if (usedindex > -1) {
8729  p->subs[usedindex].needanswer = 1;
8730  }
8732  }
8733  p->callwaitingrepeat = 0;
8734  p->cidcwexpire = 0;
8735  p->cid_suppress_expire = 0;
8736  ast_queue_unhold(p->owner);
8737  p->subs[SUB_REAL].needunhold = 1;
8738  } else
8739  ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8740  dahdi_conf_update(p);
8741  break;
8742  default:
8743  ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
8744  }
8745  f = &p->subs[idx].f;
8746  return f;
8747  }
8748  if (!(p->radio || (p->oprmode < 0)))
8749  ast_debug(1, "Exception on %d, channel %d\n", ast_channel_fd(ast, 0), p->channel);
8750  /* If it's not us, return NULL immediately */
8751  if (ast != p->owner) {
8752  if (p->owner) {
8753  ast_log(LOG_WARNING, "We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->owner));
8754  }
8755  f = &p->subs[idx].f;
8756  return f;
8757  }
8758 
8759  f = dahdi_handle_event(ast);
8760  if (!f) {
8761  const char *name = ast_strdupa(ast_channel_name(ast));
8762 
8763  /* Tell the CDR this DAHDI device hung up */
8764  ast_mutex_unlock(&p->lock);
8765  ast_channel_unlock(ast);
8766  ast_set_hangupsource(ast, name, 0);
8767  ast_channel_lock(ast);
8768  ast_mutex_lock(&p->lock);
8769  }
8770  return f;
8771 }
8772 
8773 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
8774 {
8775  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8776  struct ast_frame *f;
8777  ast_mutex_lock(&p->lock);
8778  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8779  struct analog_pvt *analog_p = p->sig_pvt;
8780  f = analog_exception(analog_p, ast);
8781  } else {
8782  f = __dahdi_exception(ast);
8783  }
8784  ast_mutex_unlock(&p->lock);
8785  return f;
8786 }
8787 
8788 static struct ast_frame *dahdi_read(struct ast_channel *ast)
8789 {
8790  struct dahdi_pvt *p;
8791  int res;
8792  int idx;
8793  void *readbuf;
8794  struct ast_frame *f;
8795 
8796  /*
8797  * For analog channels, we must do deadlock avoidance because
8798  * analog ports can have more than one Asterisk channel using
8799  * the same private structure.
8800  */
8801  p = ast_channel_tech_pvt(ast);
8802  while (ast_mutex_trylock(&p->lock)) {
8803  CHANNEL_DEADLOCK_AVOIDANCE(ast);
8804 
8805  /*
8806  * Check to see if the channel is still associated with the same
8807  * private structure. While the Asterisk channel was unlocked
8808  * the following events may have occured:
8809  *
8810  * 1) A masquerade may have associated the channel with another
8811  * technology or private structure.
8812  *
8813  * 2) For PRI calls, call signaling could change the channel
8814  * association to another B channel (private structure).
8815  */
8816  if (ast_channel_tech_pvt(ast) != p) {
8817  /* The channel is no longer associated. Quit gracefully. */
8818  return &ast_null_frame;
8819  }
8820  }
8821 
8822  idx = dahdi_get_index(ast, p, 0);
8823 
8824  /* Hang up if we don't really exist */
8825  if (idx < 0) {
8826  ast_log(LOG_WARNING, "We don't exist?\n");
8827  ast_mutex_unlock(&p->lock);
8828  return NULL;
8829  }
8830 
8831  if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
8832  ast_mutex_unlock(&p->lock);
8833  return NULL;
8834  }
8835 
8836  p->subs[idx].f.frametype = AST_FRAME_NULL;
8837  p->subs[idx].f.datalen = 0;
8838  p->subs[idx].f.samples = 0;
8839  p->subs[idx].f.mallocd = 0;
8840  p->subs[idx].f.offset = 0;
8841  p->subs[idx].f.subclass.integer = 0;
8842  p->subs[idx].f.delivery = ast_tv(0,0);
8843  p->subs[idx].f.src = "dahdi_read";
8844  p->subs[idx].f.data.ptr = NULL;
8845 
8846  /* make sure it sends initial key state as first frame */
8847  if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
8848  {
8849  struct dahdi_params ps;
8850 
8851  memset(&ps, 0, sizeof(ps));
8852  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
8853  ast_mutex_unlock(&p->lock);
8854  return NULL;
8855  }
8856  p->firstradio = 1;
8857  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8858  if (ps.rxisoffhook)
8859  {
8861  }
8862  else
8863  {
8865  }
8866  ast_mutex_unlock(&p->lock);
8867  return &p->subs[idx].f;
8868  }
8869  if (p->ringt > 0) {
8870  if (!(--p->ringt)) {
8871  ast_mutex_unlock(&p->lock);
8872  return NULL;
8873  }
8874  }
8875 
8876 #ifdef HAVE_OPENR2
8877  if (p->mfcr2) {
8878  openr2_chan_process_event(p->r2chan);
8879  if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
8880  struct ast_frame fr = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS } };
8881  /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
8882  * now enqueue a progress frame to bridge the media up */
8883  if (p->mfcr2_call_accepted &&
8884  !p->mfcr2_progress_sent &&
8886  ast_debug(1, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
8887  ast_queue_frame(p->owner, &fr);
8888  p->mfcr2_progress_sent = 1;
8889  }
8890  }
8891  }
8892 #endif
8893 
8894  if (p->subs[idx].needringing) {
8895  /* Send ringing frame if requested */
8896  p->subs[idx].needringing = 0;
8897  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8900  ast_mutex_unlock(&p->lock);
8901  return &p->subs[idx].f;
8902  }
8903 
8904  if (p->subs[idx].needbusy) {
8905  /* Send busy frame if requested */
8906  p->subs[idx].needbusy = 0;
8907  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8909  ast_mutex_unlock(&p->lock);
8910  return &p->subs[idx].f;
8911  }
8912 
8913  if (p->subs[idx].needcongestion) {
8914  /* Send congestion frame if requested */
8915  p->subs[idx].needcongestion = 0;
8916  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8918  ast_mutex_unlock(&p->lock);
8919  return &p->subs[idx].f;
8920  }
8921 
8922  if (p->subs[idx].needanswer) {
8923  /* Send answer frame if requested */
8924  p->subs[idx].needanswer = 0;
8925  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8927  ast_mutex_unlock(&p->lock);
8928  return &p->subs[idx].f;
8929  }
8930 #ifdef HAVE_OPENR2
8931  if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
8932  /* openr2 took care of reading and handling any event
8933  (needanswer, needbusy etc), if we continue we will read()
8934  twice, lets just return a null frame. This should only
8935  happen when openr2 is dialing out */
8936  ast_mutex_unlock(&p->lock);
8937  return &ast_null_frame;
8938  }
8939 #endif
8940 
8941  if (p->subs[idx].needflash) {
8942  /* Send answer frame if requested */
8943  p->subs[idx].needflash = 0;
8944  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8946  ast_mutex_unlock(&p->lock);
8947  return &p->subs[idx].f;
8948  }
8949 
8950  if (p->subs[idx].needhold) {
8951  /* Send answer frame if requested */
8952  p->subs[idx].needhold = 0;
8953  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8955  ast_mutex_unlock(&p->lock);
8956  ast_debug(1, "Sending hold on '%s'\n", ast_channel_name(ast));
8957  return &p->subs[idx].f;
8958  }
8959 
8960  if (p->subs[idx].needunhold) {
8961  /* Send answer frame if requested */
8962  p->subs[idx].needunhold = 0;
8963  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8965  ast_mutex_unlock(&p->lock);
8966  ast_debug(1, "Sending unhold on '%s'\n", ast_channel_name(ast));
8967  return &p->subs[idx].f;
8968  }
8969 
8970  /*
8971  * If we have a fake_event, fake an exception to handle it only
8972  * if this channel owns the private.
8973  */
8974  if (p->fake_event && p->owner == ast) {
8975  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8976  struct analog_pvt *analog_p = p->sig_pvt;
8977 
8978  f = analog_exception(analog_p, ast);
8979  } else {
8980  f = __dahdi_exception(ast);
8981  }
8982  ast_mutex_unlock(&p->lock);
8983  return f;
8984  }
8985 
8986  if (ast_format_cmp(ast_channel_rawreadformat(ast), ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
8987  if (!p->subs[idx].linear) {
8988  p->subs[idx].linear = 1;
8989  res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
8990  if (res)
8991  ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
8992  }
8993  } else {
8994  if (p->subs[idx].linear) {
8995  p->subs[idx].linear = 0;
8996  res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
8997  if (res)
8998  ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
8999  }
9000  }
9001  readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
9002  CHECK_BLOCKING(ast);
9003  res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
9004  ast_clear_flag(ast_channel_flags(ast), AST_FLAG_BLOCKING);
9005  /* Check for hangup */
9006  if (res < 0) {
9007  f = NULL;
9008  if (res == -1) {
9009  if (errno == EAGAIN) {
9010  /* Return "NULL" frame if there is nobody there */
9011  ast_mutex_unlock(&p->lock);
9012  return &p->subs[idx].f;
9013  } else if (errno == ELAST) {
9014  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
9015  struct analog_pvt *analog_p = p->sig_pvt;
9016  f = analog_exception(analog_p, ast);
9017  } else {
9018  f = __dahdi_exception(ast);
9019  }
9020  } else
9021  ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
9022  }
9023  ast_mutex_unlock(&p->lock);
9024  return f;
9025  }
9026  if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
9027  ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
9028  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
9029  struct analog_pvt *analog_p = p->sig_pvt;
9030  f = analog_exception(analog_p, ast);
9031  } else {
9032  f = __dahdi_exception(ast);
9033  }
9034  ast_mutex_unlock(&p->lock);
9035  return f;
9036  }
9037  if (p->tdd) { /* if in TDD mode, see if we receive that */
9038  int c;
9039 
9040  c = tdd_feed(p->tdd,readbuf,READ_SIZE);
9041  if (c < 0) {
9042  ast_debug(1,"tdd_feed failed\n");
9043  ast_mutex_unlock(&p->lock);
9044  return NULL;
9045  }
9046  if (c) { /* if a char to return */
9047  p->subs[idx].f.subclass.integer = 0;
9048  p->subs[idx].f.frametype = AST_FRAME_TEXT;
9049  p->subs[idx].f.mallocd = 0;
9050  p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
9051  p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
9052  p->subs[idx].f.datalen = 1;
9053  *((char *) p->subs[idx].f.data.ptr) = c;
9054  ast_mutex_unlock(&p->lock);
9055  return &p->subs[idx].f;
9056  }
9057  }
9058  if (idx == SUB_REAL) {
9059  /* Ensure the CW timers decrement only on a single subchannel */
9060  if (p->cidcwexpire) {
9061  if (!--p->cidcwexpire) {
9062  /* Expired CID/CW */
9063  ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
9064  restore_conference(p);
9065  }
9066  }
9067  if (p->cid_suppress_expire) {
9068  --p->cid_suppress_expire;
9069  }
9070  if (p->callwaitingrepeat) {
9071  if (!--p->callwaitingrepeat) {
9072  /* Expired, Repeat callwaiting tone */
9073  ++p->callwaitrings;
9074  dahdi_callwait(ast);
9075  }
9076  }
9077  }
9078  if (p->subs[idx].linear) {
9079  p->subs[idx].f.datalen = READ_SIZE * 2;
9080  } else
9081  p->subs[idx].f.datalen = READ_SIZE;
9082 
9083  /* Handle CallerID Transmission */
9084  if ((p->owner == ast) && p->cidspill) {
9085  send_callerid(p);
9086  }
9087 
9088  p->subs[idx].f.frametype = AST_FRAME_VOICE;
9089  p->subs[idx].f.subclass.format = ast_channel_rawreadformat(ast);
9090  p->subs[idx].f.samples = READ_SIZE;
9091  p->subs[idx].f.mallocd = 0;
9092  p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
9093  p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
9094 #if 0
9095  ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
9096 #endif
9097  if ((p->dialing && !p->waitingfordt.tv_sec) || p->radio || /* Transmitting something */
9098  (idx && (ast_channel_state(ast) != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
9099  ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
9100  ) {
9101  /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
9102  don't send anything */
9103  p->subs[idx].f.frametype = AST_FRAME_NULL;
9104  p->subs[idx].f.subclass.integer = 0;
9105  p->subs[idx].f.samples = 0;
9106  p->subs[idx].f.mallocd = 0;
9107  p->subs[idx].f.offset = 0;
9108  p->subs[idx].f.data.ptr = NULL;
9109  p->subs[idx].f.datalen= 0;
9110  }
9111  if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec || p->dialtone_detect) && !idx) {
9112  /* Perform busy detection etc on the dahdi line */
9113  int mute;
9114 
9115  if ((p->dsp_features & DSP_FEATURE_FAX_DETECT)
9116  && p->faxdetect_timeout
9118  p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
9120  ast_debug(1, "Channel driver fax CNG detection timeout on %s\n",
9121  ast_channel_name(ast));
9122  }
9123 
9124  f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
9125 
9126  /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
9127  mute = ast_dsp_was_muted(p->dsp);
9128  if (p->muting != mute) {
9129  p->muting = mute;
9130  dahdi_confmute(p, mute);
9131  }
9132 
9133  if (f) {
9135  && !p->outgoing && ast_channel_state(ast) == AST_STATE_UP) {
9139  }
9140  }
9141  if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
9142  if ((ast_channel_state(ast) == AST_STATE_UP) && !p->outgoing) {
9143  /*
9144  * Treat this as a "hangup" instead of a "busy" on the
9145  * assumption that a busy means the incoming call went away.
9146  */
9147  ast_frfree(f);
9148  f = NULL;
9149  }
9150  } else if (p->dialtone_detect && !p->outgoing && f->frametype == AST_FRAME_VOICE) {
9151  if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE) && (ast_dsp_get_tcount(p->dsp) > 9)) {
9152  /* Dialtone detected on inbound call; hangup the channel */
9153  ast_frfree(f);
9154  f = NULL;
9155  }
9156  } else if (f->frametype == AST_FRAME_DTMF_BEGIN
9157  || f->frametype == AST_FRAME_DTMF_END) {
9158 #ifdef HAVE_PRI
9159  if (dahdi_sig_pri_lib_handles(p->sig)
9160  && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
9161  && p->pri
9162  && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
9163  || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
9164  /* Don't accept in-band DTMF when in overlap dial mode */
9165  ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
9166  f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
9167  (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
9168 
9170  f->subclass.integer = 0;
9171  }
9172 #endif
9173  /* DSP clears us of being pulse */
9174  p->pulsedial = 0;
9175  } else if (p->waitingfordt.tv_sec) {
9177  p->waitingfordt.tv_sec = 0;
9178  ast_log(LOG_NOTICE, "Never saw dialtone on channel %d\n", p->channel);
9179  ast_frfree(f);
9180  f = NULL;
9181  } else if (f->frametype == AST_FRAME_VOICE) {
9183  f->subclass.integer = 0;
9184  if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE || ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_RINGING) && ast_dsp_get_tcount(p->dsp) > 9) {
9185  p->waitingfordt.tv_sec = 0;
9188  ast_debug(1, "Got 10 samples of dialtone!\n");
9189  if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
9190  res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
9191  if (res) {
9192  p->dop.dialstr[0] = '\0';
9193  ast_mutex_unlock(&p->lock);
9194  ast_frfree(f);
9195  return NULL;
9196  } else {
9197  ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
9198  p->dialing = 1;
9199  p->dop.dialstr[0] = '\0';
9200  p->dop.op = DAHDI_DIAL_OP_REPLACE;
9202  }
9203  }
9204  }
9205  }
9206  }
9207  }
9208  } else
9209  f = &p->subs[idx].f;
9210 
9211  if (f) {
9212  switch (f->frametype) {
9213  case AST_FRAME_DTMF_BEGIN:
9214  case AST_FRAME_DTMF_END:
9215  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
9216  analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
9217  } else {
9218  dahdi_handle_dtmf(ast, idx, &f);
9219  }
9220  if (!(p->dialmode == ANALOG_DIALMODE_BOTH || p->dialmode == ANALOG_DIALMODE_DTMF)) {
9221  if (f->frametype == AST_FRAME_DTMF_END) { /* only show this message when the key is let go of */
9222  ast_debug(1, "Dropping DTMF digit '%c' because tone dialing is disabled\n", f->subclass.integer);
9223  }
9225  f->subclass.integer = 0;
9226  }
9227  break;
9228  case AST_FRAME_VOICE:
9229  if (p->cidspill || p->cid_suppress_expire) {
9230  /* We are/were sending a caller id spill. Suppress any echo. */
9231  p->subs[idx].f.frametype = AST_FRAME_NULL;
9232  p->subs[idx].f.subclass.integer = 0;
9233  p->subs[idx].f.samples = 0;
9234  p->subs[idx].f.mallocd = 0;
9235  p->subs[idx].f.offset = 0;
9236  p->subs[idx].f.data.ptr = NULL;
9237  p->subs[idx].f.datalen= 0;
9238  }
9239  break;
9240  default:
9241  break;
9242  }
9243  }
9244 
9245  ast_mutex_unlock(&p->lock);
9246  return f;
9247 }
9248 
9249 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
9250 {
9251  int sent=0;
9252  int size;
9253  int res;
9254  int fd;
9255  fd = p->subs[idx].dfd;
9256  while (len) {
9257  size = len;
9258  if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
9259  size = (linear ? READ_SIZE * 2 : READ_SIZE);
9260  res = write(fd, buf, size);
9261  if (res != size) {
9262  ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
9263  return sent;
9264  }
9265  len -= size;
9266  buf += size;
9267  }
9268  return sent;
9269 }
9270 
9271 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
9272 {
9273  struct dahdi_pvt *p;
9274  int res;
9275  int idx;
9276 
9277  /* Write a frame of (presumably voice) data */
9278  if (frame->frametype != AST_FRAME_VOICE) {
9279  if (frame->frametype != AST_FRAME_IMAGE) {
9280  ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n",
9281  frame->frametype);
9282  }
9283  return 0;
9284  }
9285 
9286  /* Return if it's not valid data */
9287  if (!frame->data.ptr || !frame->datalen) {
9288  return 0;
9289  }
9290 
9291  p = ast_channel_tech_pvt(ast);
9292  ast_mutex_lock(&p->lock);
9293 
9294  idx = dahdi_get_index(ast, p, 0);
9295  if (idx < 0) {
9296  ast_mutex_unlock(&p->lock);
9297  ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast_channel_name(ast));
9298  return -1;
9299  }
9300 
9301  if (p->dialing) {
9302  ast_mutex_unlock(&p->lock);
9303  ast_debug(5, "Dropping frame since I'm still dialing on %s...\n",
9304  ast_channel_name(ast));
9305  return 0;
9306  }
9307  if (!p->owner) {
9308  ast_mutex_unlock(&p->lock);
9309  ast_debug(5, "Dropping frame since there is no active owner on %s...\n",
9310  ast_channel_name(ast));
9311  return 0;
9312  }
9313  if (p->cidspill) {
9314  ast_mutex_unlock(&p->lock);
9315  ast_debug(5, "Dropping frame since I've still got a callerid spill on %s...\n",
9316  ast_channel_name(ast));
9317  return 0;
9318  }
9319 
9321  if (!p->subs[idx].linear) {
9322  p->subs[idx].linear = 1;
9323  res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
9324  if (res)
9325  ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
9326  }
9327  res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
9330  /* x-law already */
9331  if (p->subs[idx].linear) {
9332  p->subs[idx].linear = 0;
9333  res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
9334  if (res)
9335  ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
9336  }
9337  res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
9338  } else {
9339  ast_mutex_unlock(&p->lock);
9340  ast_log(LOG_WARNING, "Cannot handle frames in %s format\n",
9342  return -1;
9343  }
9344  ast_mutex_unlock(&p->lock);
9345  if (res < 0) {
9346  ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
9347  return -1;
9348  }
9349  return 0;
9350 }
9351 
9352 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
9353 {
9354  struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
9355  int res=-1;
9356  int idx;
9357  int func = DAHDI_FLASH;
9358 
9359  ast_mutex_lock(&p->lock);
9360  ast_debug(1, "Requested indication %d on channel %s\n", condition, ast_channel_name(chan));
9361  switch (p->sig) {
9362 #if defined(HAVE_PRI)
9363  case SIG_PRI_LIB_HANDLE_CASES:
9364  res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
9365  ast_mutex_unlock(&p->lock);
9366  return res;
9367 #endif /* defined(HAVE_PRI) */
9368 #if defined(HAVE_SS7)
9369  case SIG_SS7:
9370  res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
9371  ast_mutex_unlock(&p->lock);
9372  return res;
9373 #endif /* defined(HAVE_SS7) */
9374  default:
9375  break;
9376  }
9377 #ifdef HAVE_OPENR2
9378  if (p->mfcr2 && !p->mfcr2_call_accepted) {
9379  ast_mutex_unlock(&p->lock);
9380  /* if this is an R2 call and the call is not yet accepted, we don't want the
9381  tone indications to mess up with the MF tones */
9382  return 0;
9383  }
9384 #endif
9385  idx = dahdi_get_index(chan, p, 0);
9386  if (idx == SUB_REAL) {
9387  switch (condition) {
9388  case AST_CONTROL_BUSY:
9389  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
9390  break;
9391  case AST_CONTROL_RINGING:
9392  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
9393 
9394  if (ast_channel_state(chan) != AST_STATE_UP) {
9395  if ((ast_channel_state(chan) != AST_STATE_RING) ||
9396  ((p->sig != SIG_FXSKS) &&
9397  (p->sig != SIG_FXSLS) &&
9398  (p->sig != SIG_FXSGS)))
9400  }
9401  break;
9403  ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", ast_channel_name(chan));
9404  /* act as a progress or proceeding, allowing the caller to enter additional numbers */
9405  res = 0;
9406  break;
9408  ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", ast_channel_name(chan));
9409  /* don't continue in ast_indicate */
9410  res = 0;
9411  break;
9412  case AST_CONTROL_PROGRESS:
9413  ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", ast_channel_name(chan));
9414  /* don't continue in ast_indicate */
9415  res = 0;
9416  break;
9418  /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
9419  switch (ast_channel_hangupcause(chan)) {
9420  case AST_CAUSE_USER_BUSY:
9421  case AST_CAUSE_NORMAL_CLEARING:
9422  case 0:/* Cause has not been set. */
9423  /* Supply a more appropriate cause. */
9424  ast_channel_hangupcause_set(chan, AST_CAUSE_CONGESTION);
9425  break;
9426  default:
9427  break;
9428  }
9429  break;
9430  case AST_CONTROL_HOLD:
9431  ast_moh_start(chan, data, p->mohinterpret);
9432  break;
9433  case AST_CONTROL_UNHOLD:
9434  ast_moh_stop(chan);
9435  break;
9436  case AST_CONTROL_RADIO_KEY:
9437  if (p->radio)
9438  res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
9439  res = 0;
9440  break;
9442  if (p->radio)
9443  res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
9444  res = 0;
9445  break;
9446  case AST_CONTROL_FLASH:
9447  /* flash hookswitch */
9448  if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
9449  /* Clear out the dial buffer */
9450  p->dop.dialstr[0] = '\0';
9451  if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
9452  ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
9453  ast_channel_name(chan), strerror(errno));
9454  } else
9455  res = 0;
9456  } else
9457  res = 0;
9458  break;
9459  case AST_CONTROL_SRCUPDATE:
9460  res = 0;
9461  break;
9462  case -1:
9463  res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9464  break;
9465  }
9466  } else {
9467  res = 0;
9468  }
9469  ast_mutex_unlock(&p->lock);
9470  return res;
9471 }
9472 
9473 #if defined(HAVE_PRI)
9474 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
9475 #else
9476 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
9477 #endif /* defined(HAVE_PRI) */
9478 {
9479  struct ast_str *chan_name;
9480  int x, y;
9481 
9482  /* Create the new channel name tail. */
9483  if (!(chan_name = ast_str_create(32))) {
9484  return NULL;
9485  }
9486  if (i->channel == CHAN_PSEUDO) {
9487  ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
9488 #if defined(HAVE_PRI)
9489  } else if (i->pri) {
9490  ast_mutex_lock(&i->pri->lock);
9491  y = ++i->pri->new_chan_seq;
9492  if (is_outgoing) {
9493  ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y);
9494  address[0] = '\0';
9495  } else if (ast_strlen_zero(i->cid_subaddr)) {
9496  /* Put in caller-id number only since there is no subaddress. */
9497  ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y);
9498  } else {
9499  /* Put in caller-id number and subaddress. */
9500  ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
9501  i->cid_subaddr, (unsigned)y);
9502  }
9503  ast_mutex_unlock(&i->pri->lock);
9504 #endif /* defined(HAVE_PRI) */
9505  } else {
9506  y = 1;
9507  do {
9508  ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
9509  for (x = 0; x < 3; ++x) {
9510  if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
9511  ast_channel_name(i->subs[x].owner) + 6)) {
9512  break;
9513  }
9514  }
9515  ++y;
9516  } while (x < 3);
9517  }
9518  return chan_name;
9519 }
9520 
9521 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)
9522 {
9523  struct ast_channel *new_channel = dahdi_new(i, state, startpbx, idx, law, assignedids, requestor, callid);
9524 
9525  ast_callid_threadstorage_auto_clean(callid, callid_created);
9526 
9527  return new_channel;
9528 }
9529 
9530 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)
9531 {
9532  struct ast_channel *tmp;
9533  struct ast_format_cap *caps;
9534  struct ast_format *deflaw;
9535  int x;
9536  int features;
9537  struct ast_str *chan_name;
9538  struct ast_variable *v;
9539  char *dashptr;
9540  char device_name[AST_CHANNEL_NAME];
9541 
9542  if (i->subs[idx].owner) {
9543  ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
9544  return NULL;
9545  }
9546 
9547 #if defined(HAVE_PRI)
9548  /*
9549  * The dnid has been stuffed with the called-number[:subaddress]
9550  * by dahdi_request() for outgoing calls.
9551  */
9552  chan_name = create_channel_name(i, i->outgoing, i->dnid);
9553 #else
9554  chan_name = create_channel_name(i);
9555 #endif /* defined(HAVE_PRI) */
9556  if (!chan_name) {
9557  return NULL;
9558  }
9559 
9561  if (!caps) {
9562  ast_free(chan_name);
9563  return NULL;
9564  }
9565 
9566  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));
9567  ast_free(chan_name);
9568  if (!tmp) {
9569  ao2_ref(caps, -1);
9570  return NULL;
9571  }
9572 
9574 
9575  if (callid) {
9576  ast_channel_callid_set(tmp, callid);
9577  }
9578 
9579  ast_channel_tech_set(tmp, &dahdi_tech);
9580 #if defined(HAVE_PRI)
9581  if (i->pri) {
9582  ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
9583  }
9584 #endif /* defined(HAVE_PRI) */
9585  ast_channel_cc_params_init(tmp, i->cc_params);
9586  if (law) {
9587  i->law = law;
9588  if (law == DAHDI_LAW_ALAW) {
9589  deflaw = ast_format_alaw;
9590  } else {
9591  deflaw = ast_format_ulaw;
9592  }
9593  } else {
9594  switch (i->sig) {
9595  case SIG_PRI_LIB_HANDLE_CASES:
9596  /* Make sure companding law is known. */
9597  i->law = (i->law_default == DAHDI_LAW_ALAW)
9598  ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
9599  break;
9600  default:
9601  i->law = i->law_default;
9602  break;
9603  }
9604  if (i->law_default == DAHDI_LAW_ALAW) {
9605  deflaw = ast_format_alaw;
9606  } else {
9607  deflaw = ast_format_ulaw;
9608  }
9609  }
9610  ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
9611  ast_format_cap_append(caps, deflaw, 0);
9612  ast_channel_nativeformats_set(tmp, caps);
9613  ao2_ref(caps, -1);
9614  /* Start out assuming ulaw since it's smaller :) */
9615  ast_channel_set_rawreadformat(tmp, deflaw);
9616  ast_channel_set_readformat(tmp, deflaw);
9617  ast_channel_set_rawwriteformat(tmp, deflaw);
9618  ast_channel_set_writeformat(tmp, deflaw);
9619  i->subs[idx].linear = 0;
9620  dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
9621  features = 0;
9622  if (idx == SUB_REAL) {
9623  if (i->busydetect && CANBUSYDETECT(i))
9624  features |= DSP_FEATURE_BUSY_DETECT;
9625  if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
9626  features |= DSP_FEATURE_CALL_PROGRESS;
9627  if ((i->waitfordialtone || i->dialtone_detect) && CANPROGRESSDETECT(i))
9628  features |= DSP_FEATURE_WAITDIALTONE;
9629  if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
9630  (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
9631  features |= DSP_FEATURE_FAX_DETECT;
9632  }
9633  x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
9634  if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
9635  i->hardwaredtmf = 0;
9636  features |= DSP_FEATURE_DIGIT_DETECT;
9637  } else if (NEED_MFDETECT(i)) {
9638  i->hardwaredtmf = 1;
9639  features |= DSP_FEATURE_DIGIT_DETECT;
9640  }
9641  }
9642  if (features) {
9643  if (i->dsp) {
9644  ast_debug(1, "Already have a dsp on %s?\n", ast_channel_name(tmp));
9645  } else {
9646  if (i->channel != CHAN_PSEUDO)
9647  i->dsp = ast_dsp_new();
9648  else
9649  i->dsp = NULL;
9650  if (i->dsp) {
9651  i->dsp_features = features;
9652 #if defined(HAVE_PRI) || defined(HAVE_SS7)
9653  /* We cannot do progress detection until receive PROGRESS message */
9654  if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
9655  /* Remember requested DSP features, don't treat
9656  talking as ANSWER */
9657  i->dsp_features = features & ~DSP_PROGRESS_TALK;
9658  features = 0;
9659  }
9660 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9661  ast_dsp_set_features(i->dsp, features);
9663  if (!ast_strlen_zero(progzone))
9664  ast_dsp_set_call_progress_zone(i->dsp, progzone);
9665  if (i->busydetect && CANBUSYDETECT(i)) {
9668  }
9669  }
9670  }
9671  }
9672 
9674 
9675  if (state == AST_STATE_RING)
9676  ast_channel_rings_set(tmp, 1);
9677  ast_channel_tech_pvt_set(tmp, i);
9678  if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
9679  /* Only FXO signalled stuff can be picked up */
9682  ast_channel_named_callgroups_set(tmp, i->named_callgroups);
9683  ast_channel_named_pickupgroups_set(tmp, i->named_pickupgroups);
9684  }
9685  if (!ast_strlen_zero(i->parkinglot))
9686  ast_channel_parkinglot_set(tmp, i->parkinglot);
9687  if (!ast_strlen_zero(i->language))
9688  ast_channel_language_set(tmp, i->language);
9689  if (!i->owner)
9690  i->owner = tmp;
9691  if (!ast_strlen_zero(i->accountcode))
9692  ast_channel_accountcode_set(tmp, i->accountcode);
9693  if (i->amaflags)
9695  i->subs[idx].owner = tmp;
9696  ast_channel_context_set(tmp, i->context);
9697  if (!dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
9698  ast_channel_call_forward_set(tmp, i->call_forward);
9699  }
9700  /* If we've been told "no ADSI" then enforce it */
9701  if (!i->adsi)
9702  ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
9703  if (!ast_strlen_zero(i->exten))
9704  ast_channel_exten_set(tmp, i->exten);
9705  if (!ast_strlen_zero(i->rdnis)) {
9706  ast_channel_redirecting(tmp)->from.number.valid = 1;
9707  ast_channel_redirecting(tmp)->from.number.str = ast_strdup(i->rdnis);
9708  }
9709  if (!ast_strlen_zero(i->dnid)) {
9710  ast_channel_dialed(tmp)->number.str = ast_strdup(i->dnid);
9711  }
9712 
9713  /* Don't use ast_set_callerid() here because it will
9714  * generate a needless NewCallerID event */
9715 #if defined(HAVE_PRI) || defined(HAVE_SS7)
9716  if (!ast_strlen_zero(i->cid_ani)) {
9717  ast_channel_caller(tmp)->ani.number.valid = 1;
9718  ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_ani);
9719  } else if (!ast_strlen_zero(i->cid_num)) {
9720  ast_channel_caller(tmp)->ani.number.valid = 1;
9721  ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
9722  }
9723 #else
9724  if (!ast_strlen_zero(i->cid_num)) {
9725  ast_channel_caller(tmp)->ani.number.valid = 1;
9726  ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
9727  }
9728 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9729  ast_channel_caller(tmp)->id.name.presentation = i->callingpres;
9730  ast_channel_caller(tmp)->id.number.presentation = i->callingpres;
9731  ast_channel_caller(tmp)->id.number.plan = i->cid_ton;
9732  ast_channel_caller(tmp)->ani2 = i->cid_ani2;
9733  ast_channel_caller(tmp)->id.tag = ast_strdup(i->cid_tag);
9734  /* clear the fake event in case we posted one before we had ast_channel */
9735  i->fake_event = 0;
9736  /* Assure there is no confmute on this channel */
9737  dahdi_confmute(i, 0);
9738  i->muting = 0;
9739  /* Configure the new channel jb */
9740  ast_jb_configure(tmp, &global_jbconf);
9741 
9742  /* Set initial device state */
9743  ast_copy_string(device_name, ast_channel_name(tmp), sizeof(device_name));
9744  dashptr = strrchr(device_name, '-');
9745  if (dashptr) {
9746  *dashptr = '\0';
9747  }
9748  ast_set_flag(ast_channel_flags(tmp), AST_FLAG_DISABLE_DEVSTATE_CACHE);
9750 
9751  for (v = i->vars ; v ; v = v->next)
9752  pbx_builtin_setvar_helper(tmp, v->name, v->value);
9753 
9755 
9756  ast_channel_unlock(tmp);
9757 
9759 
9760  dahdi_ami_channel_event(i, tmp);
9761  if (startpbx) {
9762 #ifdef HAVE_OPENR2
9763  if (i->mfcr2call) {
9764  pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
9765  }
9766 #endif
9767  if (ast_pbx_start(tmp)) {
9768  ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
9769  ast_hangup(tmp);
9770  return NULL;
9771  }
9772  }
9773  return tmp;
9774 }
9775 
9776 
9777 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
9778 {
9779  char c;
9780 
9781  *str = 0; /* start with empty output buffer */
9782  for (;;)
9783  {
9784  /* Wait for the first digit (up to specified ms). */
9785  c = ast_waitfordigit(chan, ms);
9786  /* if timeout, hangup or error, return as such */
9787  if (c < 1)
9788  return c;
9789  *str++ = c;
9790  *str = 0;
9791  if (strchr(term, c))
9792  return 1;
9793  }
9794 }
9795 
9796 static int dahdi_wink(struct dahdi_pvt *p, int idx)
9797 {
9798  int j;
9799  dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
9800  for (;;)
9801  {
9802  /* set bits of interest */
9803  j = DAHDI_IOMUX_SIGEVENT;
9804  /* wait for some happening */
9805  if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
9806  /* exit loop if we have it */
9807  if (j & DAHDI_IOMUX_SIGEVENT) break;
9808  }
9809  /* get the event info */
9810  if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
9811  return 0;
9812 }
9813 
9814 static void publish_dnd_state(int channel, const char *status)
9815 {
9816  RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
9817  RAII_VAR(struct ast_str *, dahdichan, ast_str_create(32), ast_free);
9818  if (!dahdichan) {
9819  return;
9820  }
9821 
9822  ast_str_set(&dahdichan, 0, "%d", channel);
9823 
9824  body = ast_json_pack("{s: s, s: s}",
9825  "DAHDIChannel", ast_str_buffer(dahdichan),
9826  "Status", status);
9827  if (!body) {
9828  return;
9829  }
9830 
9831  ast_manager_publish_event("DNDState", EVENT_FLAG_SYSTEM, body);
9832 }
9833 
9834 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
9835  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
9836  * \param flag on 1 to enable, 0 to disable, -1 return dnd value
9837  *
9838  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
9839  * DAHDI channel). Use this to enable or disable it.
9840  *
9841  * \bug the use of the word "channel" for those dahdichans is really confusing.
9842  */
9843 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
9844 {
9845  if (dahdi_analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
9846  return analog_dnd(dahdichan->sig_pvt, flag);
9847  }
9848 
9849  if (flag == -1) {
9850  return dahdichan->dnd;
9851  }
9852 
9853  /* Do not disturb */
9854  dahdichan->dnd = flag;
9855  ast_verb(3, "%s DND on channel %d\n",
9856  flag? "Enabled" : "Disabled",
9857  dahdichan->channel);
9858  publish_dnd_state(dahdichan->channel, flag ? "enabled" : "disabled");
9859  return 0;
9860 }
9861 
9862 static int canmatch_featurecode(const char *pickupexten, const char *exten)
9863 {
9864  int extlen = strlen(exten);
9865 
9866  if (!extlen) {
9867  return 1;
9868  }
9869 
9870  if (extlen < strlen(pickupexten) && !strncmp(pickupexten, exten, extlen)) {
9871  return 1;
9872  }
9873  /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
9874  if (exten[0] == '*' && extlen < 3) {
9875  if (extlen == 1) {
9876  return 1;
9877  }
9878  /* "*0" should be processed before it gets here */
9879  switch (exten[1]) {
9880  case '6':
9881  case '7':
9882  case '8':
9883  return 1;
9884  }
9885  }
9886  return 0;
9887 }
9888 
9889 static void *analog_ss_thread(void *data)
9890 {
9891  struct ast_channel *chan = data;
9892  struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
9893  char exten[AST_MAX_EXTENSION] = "";
9894  char exten2[AST_MAX_EXTENSION] = "";
9895  unsigned char buf[256];
9896  char dtmfcid[300];
9897  char dtmfbuf[300];
9898  struct callerid_state *cs = NULL;
9899  char *name = NULL, *number = NULL;
9900  int distMatches;
9901  int curRingData[3];
9902  int receivedRingT;
9903  int counter1;
9904  int counter;
9905  int samples = 0;
9906  struct ast_smdi_md_message *smdi_msg = NULL;
9907  int flags = 0;
9908  int i;
9909  int timeout;
9910  int getforward = 0;
9911  char *s1, *s2;
9912  int len = 0;
9913  int res;
9914  int idx;
9915  RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
9916  const char *pickupexten;
9917 
9918  ast_mutex_lock(&ss_thread_lock);
9919  ss_thread_count++;
9920  ast_mutex_unlock(&ss_thread_lock);
9921  /* in the bizarre case where the channel has become a zombie before we
9922  even get started here, abort safely
9923  */
9924  if (!p) {
9925  ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", ast_channel_name(chan));
9926  ast_hangup(chan);
9927  goto quit;
9928  }
9929  ast_verb(3, "Starting simple switch on '%s'\n", ast_channel_name(chan));
9930  idx = dahdi_get_index(chan, p, 1);
9931  if (idx < 0) {
9932  ast_log(LOG_WARNING, "Huh?\n");
9933  ast_hangup(chan);
9934  goto quit;
9935  }
9936 
9937  ast_channel_lock(chan);
9938  pickup_cfg = ast_get_chan_features_pickup_config(chan);
9939  if (!pickup_cfg) {
9940  ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
9941  pickupexten = "";
9942  } else {
9943  pickupexten = ast_strdupa(pickup_cfg->pickupexten);
9944  }
9945  ast_channel_unlock(chan);
9946 
9947  if (p->dsp)
9948  ast_dsp_digitreset(p->dsp);
9949  switch (p->sig) {
9950  case SIG_FEATD:
9951  case SIG_FEATDMF:
9952  case SIG_FEATDMF_TA:
9953  case SIG_E911:
9954  case SIG_FGC_CAMAMF:
9955  case SIG_FEATB:
9956  case SIG_EMWINK:
9957  case SIG_SF_FEATD:
9958  case SIG_SF_FEATDMF:
9959  case SIG_SF_FEATB:
9960  case SIG_SFWINK:
9961  if (dahdi_wink(p, idx))
9962  goto quit;
9963  /* Fall through */
9964  case SIG_EM:
9965  case SIG_EM_E1:
9966  case SIG_SF:
9967  case SIG_FGC_CAMA:
9968  res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9969  if (p->dsp)
9970  ast_dsp_digitreset(p->dsp);
9971  /* set digit mode appropriately */
9972  if (p->dsp) {
9973  if (NEED_MFDETECT(p))
9975  else
9977  }
9978  memset(dtmfbuf, 0, sizeof(dtmfbuf));
9979  /* Wait for the first digit only if immediate=no */
9980  if (!p->immediate)
9981  /* Wait for the first digit (up to 5 seconds). */
9982  res = ast_waitfordigit(chan, 5000);
9983  else
9984  res = 0;
9985  if (res > 0) {
9986  /* save first char */
9987  dtmfbuf[0] = res;
9988  switch (p->sig) {
9989  case SIG_FEATD:
9990  case SIG_SF_FEATD:
9991  res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
9992  if (res > 0)
9993  res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
9994  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9995  break;
9996  case SIG_FEATDMF_TA:
9997  res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9998  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9999  if (dahdi_wink(p, idx)) goto quit;
10000  dtmfbuf[0] = 0;
10001  /* Wait for the first digit (up to 5 seconds). */
10002  res = ast_waitfordigit(chan, 5000);
10003  if (res <= 0) break;
10004  dtmfbuf[0] = res;
10005  /* fall through intentionally */
10006  case SIG_FEATDMF:
10007  case SIG_E911:
10008  case SIG_FGC_CAMAMF:
10009  case SIG_SF_FEATDMF:
10010  res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10011  /* if international caca, do it again to get real ANO */
10012  if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10013  {
10014  if (dahdi_wink(p, idx)) goto quit;
10015  dtmfbuf[0] = 0;
10016  /* Wait for the first digit (up to 5 seconds). */
10017  res = ast_waitfordigit(chan, 5000);
10018  if (res <= 0) break;
10019  dtmfbuf[0] = res;
10020  res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10021  }
10022  if (res > 0) {
10023  /* if E911, take off hook */
10024  if (p->sig == SIG_E911)
10025  dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10026  res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10027  }
10028  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10029  break;
10030  case SIG_FEATB:
10031  case SIG_SF_FEATB:
10032  res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10033  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10034  break;
10035  case SIG_EMWINK:
10036  /* if we received a '*', we are actually receiving Feature Group D
10037  dial syntax, so use that mode; otherwise, fall through to normal
10038  mode
10039  */
10040  if (res == '*') {
10041  res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10042  if (res > 0)
10043  res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10044  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10045  break;
10046  }
10047  default:
10048  /* If we got the first digit, get the rest */
10049  len = 1;
10050  dtmfbuf[len] = '\0';
10051  while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
10052  if (ast_exists_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
10053  timeout = p->matchdigit_timeout;
10054  } else {
10055  timeout = p->interdigit_timeout;
10056  }
10057  res = ast_waitfordigit(chan, timeout);
10058  if (res < 0) {
10059  ast_debug(1, "waitfordigit returned < 0...\n");
10060  ast_hangup(chan);
10061  goto quit;
10062  } else if (res) {
10063  dtmfbuf[len++] = res;
10064  dtmfbuf[len] = '\0';
10065  } else {
10066  break;
10067  }
10068  }
10069  break;
10070  }
10071  }
10072  if (res == -1) {
10073  ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10074  ast_hangup(chan);
10075  goto quit;
10076  } else if (res < 0) {
10077  ast_debug(1, "Got hung up before digits finished\n");
10078  ast_hangup(chan);
10079  goto quit;
10080  }
10081 
10082  if (p->sig == SIG_FGC_CAMA) {
10083  char anibuf[100];
10084 
10085  if (ast_safe_sleep(chan,1000) == -1) {
10086  ast_hangup(chan);
10087  goto quit;
10088  }
10089  dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10091  res = my_getsigstr(chan, anibuf, "#", 10000);
10092  if ((res > 0) && (strlen(anibuf) > 2)) {
10093  if (anibuf[strlen(anibuf) - 1] == '#')
10094  anibuf[strlen(anibuf) - 1] = 0;
10095  ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10096  }
10098  }
10099 
10100  ast_copy_string(exten, dtmfbuf, sizeof(exten));
10101  if (ast_strlen_zero(exten))
10102  ast_copy_string(exten, "s", sizeof(exten));
10103  if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10104  /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
10105  if (exten[0] == '*') {
10106  char *stringp=NULL;
10107  ast_copy_string(exten2, exten, sizeof(exten2));
10108  /* Parse out extension and callerid */
10109  stringp=exten2 +1;
10110  s1 = strsep(&stringp, "*");
10111  s2 = strsep(&stringp, "*");
10112  if (s2) {
10113  if (!ast_strlen_zero(p->cid_num))
10114  ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10115  else
10116  ast_set_callerid(chan, s1, NULL, s1);
10117  ast_copy_string(exten, s2, sizeof(exten));
10118  } else
10119  ast_copy_string(exten, s1, sizeof(exten));
10120  } else if (p->sig == SIG_FEATD)
10121  ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10122  }
10123  if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10124  if (exten[0] == '*') {
10125  char *stringp=NULL;
10126  ast_copy_string(exten2, exten, sizeof(exten2));
10127  /* Parse out extension and callerid */
10128  stringp=exten2 +1;
10129  s1 = strsep(&stringp, "#");
10130  s2 = strsep(&stringp, "#");
10131  if (s2) {
10132  if (!ast_strlen_zero(p->cid_num))
10133  ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10134  else
10135  if (*(s1 + 2))
10136  ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10137  ast_copy_string(exten, s2 + 1, sizeof(exten));
10138  } else
10139  ast_copy_string(exten, s1 + 2, sizeof(exten));
10140  } else
10141  ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10142  }
10143  if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10144  if (exten[0] == '*') {
10145  char *stringp=NULL;
10146  ast_copy_string(exten2, exten, sizeof(exten2));
10147  /* Parse out extension and callerid */
10148  stringp=exten2 +1;
10149  s1 = strsep(&stringp, "#");
10150  s2 = strsep(&stringp, "#");
10151  if (s2 && (*(s2 + 1) == '0')) {
10152  if (*(s2 + 2))
10153  ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10154  }
10155  if (s1) ast_copy_string(exten, s1, sizeof(exten));
10156  else ast_copy_string(exten, "911", sizeof(exten));
10157  } else
10158  ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10159  }
10160  if (p->sig == SIG_FEATB) {
10161  if (exten[0] == '*') {
10162  char *stringp=NULL;
10163  ast_copy_string(exten2, exten, sizeof(exten2));
10164  /* Parse out extension and callerid */
10165  stringp=exten2 +1;
10166  s1 = strsep(&stringp, "#");
10167  ast_copy_string(exten, exten2 + 1, sizeof(exten));
10168  } else
10169  ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10170  }
10171  if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10172  dahdi_wink(p, idx);
10173  /* some switches require a minimum guard time between
10174  the last FGD wink and something that answers
10175  immediately. This ensures it */
10176  if (ast_safe_sleep(chan, 100)) {
10177  ast_hangup(chan);
10178  goto quit;
10179  }
10180  }
10181  dahdi_ec_enable(p);
10182  if (NEED_MFDETECT(p)) {
10183  if (p->dsp) {
10184  if (!p->hardwaredtmf)
10186  else {
10187  ast_dsp_free(p->dsp);
10188  p->dsp = NULL;
10189  }
10190  }
10191  }
10192 
10193  if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1,
10194  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
10195  ast_channel_exten_set(chan, exten);
10196  if (p->dsp) ast_dsp_digitreset(p->dsp);
10197  res = ast_pbx_run(chan);
10198  if (res) {
10199  ast_log(LOG_WARNING, "PBX exited non-zero\n");
10200  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10201  }
10202  goto quit;
10203  } else {
10204  ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, ast_channel_context(chan));
10205  sleep(2);
10206  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10207  if (res < 0)
10208  ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10209  else
10210  sleep(1);
10211  res = ast_streamfile(chan, "ss-noservice", ast_channel_language(chan));
10212  if (res >= 0)
10213  ast_waitstream(chan, "");
10214  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10215  ast_hangup(chan);
10216  goto quit;
10217  }
10218  break;
10219  case SIG_FXOLS:
10220  case SIG_FXOGS:
10221  case SIG_FXOKS:
10222  /* Read the first digit */
10223  timeout = p->firstdigit_timeout;
10224  /* If starting a threeway call, never timeout on the first digit so someone
10225  can use flash-hook as a "hold" feature */
10226  if (p->subs[SUB_THREEWAY].owner)
10227  timeout = INT_MAX;
10228  while (len < AST_MAX_EXTENSION-1) {
10229  int is_exten_parking = 0;
10230 
10231  /* Read digit unless it's supposed to be immediate, in which case the
10232  only answer is 's' */
10233  if (p->immediate)
10234  res = 's';
10235  else
10236  res = ast_waitfordigit(chan, timeout);
10237  timeout = 0;
10238  if (res < 0) {
10239  ast_debug(1, "waitfordigit returned < 0...\n");
10240  res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10241  ast_hangup(chan);
10242  goto quit;
10243  } else if (res) {
10244  ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10245  exten[len++]=res;
10246  exten[len] = '\0';
10247  }
10248  if (!ast_ignore_pattern(ast_channel_context(chan), exten)) {
10249  tone_zone_play_tone(p->subs[idx].dfd, -1);
10250  } else {
10251  tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10252  }
10254  is_exten_parking = ast_parking_is_exten_park(ast_channel_context(chan), exten);
10255  }
10256  if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num) && !is_exten_parking) {
10257  if (!res || !ast_matchmore_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
10258  if (getforward) {
10259  /* Record this as the forwarding extension */
10260  ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10261  ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10262  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10263  if (res)
10264  break;
10265  usleep(500000);
10266  res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10267  sleep(1);
10268  memset(exten, 0, sizeof(exten));
10269  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10270  len = 0;
10271  getforward = 0;
10272  } else {
10273  res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10274  ast_channel_lock(chan);
10275  ast_channel_exten_set(chan, exten);
10276  if (!ast_strlen_zero(p->cid_num)) {
10277  if (!p->hidecallerid)
10278  ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10279  else
10280  ast_set_callerid(chan, NULL, NULL, p->cid_num);
10281  }
10282  if (!ast_strlen_zero(p->cid_name)) {
10283  if (!p->hidecallerid)
10284  ast_set_callerid(chan, NULL, p->cid_name, NULL);
10285  }
10287  ast_channel_unlock(chan);
10288  dahdi_ec_enable(p);
10289  res = ast_pbx_run(chan);
10290  if (res) {
10291  ast_log(LOG_WARNING, "PBX exited non-zero\n");
10292  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10293  }
10294  goto quit;
10295  }
10296  } else {
10297  /* It's a match, but they just typed a digit, and there is an ambiguous match,
10298  so just set the timeout to matchdigit_timeout and wait some more */
10299  timeout = p->matchdigit_timeout;
10300  }
10301  } else if (res == 0) {
10302  ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10303  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10304  dahdi_wait_event(p->subs[idx].dfd);
10305  ast_hangup(chan);
10306  goto quit;
10307  } else if (p->callwaiting && !strcmp(exten, "*70")) {
10308  ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan));
10309  /* Disable call waiting if enabled */
10310  p->callwaiting = 0;
10311  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10312  if (res) {
10313  ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10314  ast_channel_name(chan), strerror(errno));
10315  }
10316  len = 0;
10317  ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10318  memset(exten, 0, sizeof(exten));
10319  timeout = p->firstdigit_timeout;
10320 
10321  } else if (!strcmp(exten, pickupexten)) {
10322  /* Scan all channels and see if there are any
10323  * ringing channels that have call groups
10324  * that equal this channels pickup group
10325  */
10326  if (idx == SUB_REAL) {
10327  /* Switch us from Third call to Call Wait */
10328  if (p->subs[SUB_THREEWAY].owner) {
10329  /* If you make a threeway call and the *8# a call, it should actually
10330  look like a callwait */
10331  alloc_sub(p, SUB_CALLWAIT);
10332  swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10333  unalloc_sub(p, SUB_THREEWAY);
10334  }
10335  dahdi_ec_enable(p);
10336  if (ast_pickup_call(chan)) {
10337  ast_debug(1, "No call pickup possible...\n");
10338  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10339  dahdi_wait_event(p->subs[idx].dfd);
10340  }
10341  ast_hangup(chan);
10342  goto quit;
10343  } else {
10344  ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10345  ast_hangup(chan);
10346  goto quit;
10347  }
10348 
10349  } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10350  ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan));
10351  /* Disable Caller*ID if enabled */
10352  p->hidecallerid = 1;
10353  ast_party_number_free(&ast_channel_caller(chan)->id.number);
10354  ast_party_number_init(&ast_channel_caller(chan)->id.number);
10355  ast_party_name_free(&ast_channel_caller(chan)->id.name);
10356  ast_party_name_init(&ast_channel_caller(chan)->id.name);
10357  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10358  if (res) {
10359  ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10360  ast_channel_name(chan), strerror(errno));
10361  }
10362  len = 0;
10363  memset(exten, 0, sizeof(exten));
10364  timeout = p->firstdigit_timeout;
10365  } else if (p->callreturn && !strcmp(exten, "*69")) {
10366  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10367  break;
10368  } else if (!strcmp(exten, "*78")) {
10369  dahdi_dnd(p, 1);
10370  /* Do not disturb */
10371  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10372  getforward = 0;
10373  memset(exten, 0, sizeof(exten));
10374  len = 0;
10375  } else if (!strcmp(exten, "*79")) {
10376  dahdi_dnd(p, 0);
10377  /* Do not disturb */
10378  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10379  getforward = 0;
10380  memset(exten, 0, sizeof(exten));
10381  len = 0;
10382  } else if (p->cancallforward && !strcmp(exten, "*72")) {
10383  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10384  getforward = 1;
10385  memset(exten, 0, sizeof(exten));
10386  len = 0;
10387  } else if (p->cancallforward && !strcmp(exten, "*73")) {
10388  ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10389  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10390  memset(p->call_forward, 0, sizeof(p->call_forward));
10391  getforward = 0;
10392  memset(exten, 0, sizeof(exten));
10393  len = 0;
10394  } else if ((p->transfer || p->canpark) && is_exten_parking
10395  && p->subs[SUB_THREEWAY].owner) {
10396  struct ast_bridge_channel *bridge_channel;
10397 
10398  /*
10399  * This is a three way call, the main call being a real channel,
10400  * and we're parking the first call.
10401  */
10402  ast_channel_lock(p->subs[SUB_THREEWAY].owner);
10403  bridge_channel = ast_channel_get_bridge_channel(p->subs[SUB_THREEWAY].owner);
10404  ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
10405  if (bridge_channel) {
10406  if (!ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), exten, NULL, NULL)) {
10407  /*
10408  * Swap things around between the three-way and real call so we
10409  * can hear where the channel got parked.
10410  */
10411  ast_mutex_lock(&p->lock);
10412  p->owner = p->subs[SUB_THREEWAY].owner;
10413  swap_subs(p, SUB_THREEWAY, SUB_REAL);
10414  ast_mutex_unlock(&p->lock);
10415 
10416  ast_verb(3, "%s: Parked call\n", ast_channel_name(chan));
10417  ast_hangup(chan);
10418  ao2_ref(bridge_channel, -1);
10419  goto quit;
10420  }
10421  ao2_ref(bridge_channel, -1);
10422  }
10423  break;
10424  } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10425  ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan));
10426  /* Enable Caller*ID if enabled */
10427  p->hidecallerid = 0;
10428  ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10429  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10430  if (res) {
10431  ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10432  ast_channel_name(chan), strerror(errno));
10433  }
10434  len = 0;
10435  memset(exten, 0, sizeof(exten));
10436  timeout = p->firstdigit_timeout;
10437  } else if (!strcmp(exten, "*0")) {
10438  struct ast_channel *nbridge =
10439  p->subs[SUB_THREEWAY].owner;
10440  struct dahdi_pvt *pbridge = NULL;
10441  RAII_VAR(struct ast_channel *, bridged, nbridge ? ast_channel_bridge_peer(nbridge) : NULL, ast_channel_cleanup);
10442 
10443  /* set up the private struct of the bridged one, if any */
10444  if (nbridge && bridged) {
10445  pbridge = ast_channel_tech_pvt(bridged);
10446  }
10447  if (nbridge && pbridge &&
10448  (ast_channel_tech(nbridge) == &dahdi_tech) &&
10449  (ast_channel_tech(bridged) == &dahdi_tech) &&
10450  ISTRUNK(pbridge)) {
10451  int func = DAHDI_FLASH;
10452  /* Clear out the dial buffer */
10453  p->dop.dialstr[0] = '\0';
10454  /* flash hookswitch */
10455  if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10456  ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10457  ast_channel_name(nbridge), strerror(errno));
10458  }
10459  swap_subs(p, SUB_REAL, SUB_THREEWAY);
10460  unalloc_sub(p, SUB_THREEWAY);
10461  p->owner = p->subs[SUB_REAL].owner;
10462  ast_queue_unhold(p->subs[SUB_REAL].owner);
10463  ast_hangup(chan);
10464  goto quit;
10465  } else {
10466  tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10467  dahdi_wait_event(p->subs[idx].dfd);
10468  tone_zone_play_tone(p->subs[idx].dfd, -1);
10469  swap_subs(p, SUB_REAL, SUB_THREEWAY);
10470  unalloc_sub(p, SUB_THREEWAY);
10471  p->owner = p->subs[SUB_REAL].owner;
10472  ast_hangup(chan);
10473  goto quit;
10474  }
10475  } else if (!ast_canmatch_extension(chan, ast_channel_context(chan), exten, 1,
10476  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
10477  && !canmatch_featurecode(pickupexten, exten)) {
10478  ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10479  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<Unknown Caller>"),
10480  ast_channel_context(chan));
10481  break;
10482  }
10483  if (!timeout)
10484  timeout = p->interdigit_timeout;
10485  if (len && !ast_ignore_pattern(ast_channel_context(chan), exten))
10486  tone_zone_play_tone(p->subs[idx].dfd, -1);
10487  }
10488  break;
10489  case SIG_FXSLS:
10490  case SIG_FXSGS:
10491  case SIG_FXSKS:
10492  /* check for SMDI messages */
10493  if (p->use_smdi && p->smdi_iface) {
10494  smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10495 
10496  if (smdi_msg != NULL) {
10497  ast_channel_exten_set(chan, smdi_msg->fwd_st);
10498 
10499  if (smdi_msg->type == 'B')
10500  pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10501  else if (smdi_msg->type == 'N')
10502  pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10503 
10504  ast_debug(1, "Received SMDI message on %s\n", ast_channel_name(chan));
10505  } else {
10506  ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10507  }
10508  }
10509 
10510  if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10511  number = smdi_msg->calling_st;
10512 
10513  /* If we want caller id, we're in a prering state due to a polarity reversal
10514  * and we're set to use a polarity reversal to trigger the start of caller id,
10515  * grab the caller id and wait for ringing to start... */
10516  } else if (p->use_callerid && (ast_channel_state(chan) == AST_STATE_PRERING &&
10517  (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10518  /* If set to use DTMF CID signalling, listen for DTMF */
10519  if (p->cid_signalling == CID_SIG_DTMF) {
10520  int k = 0;
10521  int off_ms;
10522  struct timeval start = ast_tvnow();
10523  int ms;
10524  cs = NULL;
10525  ast_debug(1, "Receiving DTMF cid on channel %s\n", ast_channel_name(chan));
10526  dahdi_setlinear(p->subs[idx].dfd, 0);
10527  /*
10528  * We are the only party interested in the Rx stream since
10529  * we have not answered yet. We don't need or even want DTMF
10530  * emulation. The DTMF digits can come so fast that emulation
10531  * can drop some of them.
10532  */
10533  ast_channel_lock(chan);
10534  ast_set_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
10535  ast_channel_unlock(chan);
10536  off_ms = 4000;/* This is a typical OFF time between rings. */
10537  for (;;) {
10538  struct ast_frame *f;
10539 
10540  ms = ast_remaining_ms(start, off_ms);
10541  res = ast_waitfor(chan, ms);
10542  if (res <= 0) {
10543  /*
10544  * We do not need to restore the dahdi_setlinear()
10545  * or AST_FLAG_END_DTMF_ONLY flag settings since we
10546  * are hanging up the channel.
10547  */
10548  ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10549  "Exiting simple switch\n");
10550  ast_hangup(chan);
10551  goto quit;
10552  }
10553  f = ast_read(chan);
10554  if (!f)
10555  break;
10556  if (f->frametype == AST_FRAME_DTMF) {
10557  if (k < ARRAY_LEN(dtmfbuf) - 1) {
10558  dtmfbuf[k++] = f->subclass.integer;
10559  }
10560  ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10561  start = ast_tvnow();
10562  }
10563  ast_frfree(f);
10564  if (ast_channel_state(chan) == AST_STATE_RING ||
10566  break; /* Got ring */
10567  }
10568  ast_channel_lock(chan);
10569  ast_clear_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
10570  ast_channel_unlock(chan);
10571  dtmfbuf[k] = '\0';
10572  dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10573  /* Got cid and ring. */
10574  ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10575  callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10576  ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10577  /* If first byte is NULL, we have no cid */
10578  if (!ast_strlen_zero(dtmfcid))
10579  number = dtmfcid;
10580  else
10581  number = NULL;
10582  /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10583  } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10584  cs = callerid_new(p->cid_signalling);
10585  if (cs) {
10586  int off_ms;
10587  struct timeval start;
10588  int ms;
10589  samples = 0;
10590 #if 1
10591  bump_gains(p);
10592 #endif
10593  /* Take out of linear mode for Caller*ID processing */
10594  dahdi_setlinear(p->subs[idx].dfd, 0);
10595 
10596  /* First we wait and listen for the Caller*ID */
10597  for (;;) {
10598  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10599  if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10600  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10601  callerid_free(cs);
10602  ast_hangup(chan);
10603  goto quit;
10604  }
10605  if (i & DAHDI_IOMUX_SIGEVENT) {
10606  res = dahdi_get_event(p->subs[idx].dfd);
10607  ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10608  if (res == DAHDI_EVENT_NOALARM) {
10609  p->inalarm = 0;
10610  }
10611 
10612  if (p->cid_signalling == CID_SIG_V23_JP) {
10613  if (res == DAHDI_EVENT_RINGBEGIN) {
10614  res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10615  usleep(1);
10616  }
10617  } else {
10618  res = 0;
10619  break;
10620  }
10621  } else if (i & DAHDI_IOMUX_READ) {
10622  res = read(p->subs[idx].dfd, buf, sizeof(buf));
10623  if (res < 0) {
10624  if (errno != ELAST) {
10625  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10626  callerid_free(cs);
10627  ast_hangup(chan);
10628  goto quit;
10629  }
10630  break;
10631  }
10632  samples += res;
10633 
10634  if (p->cid_signalling == CID_SIG_V23_JP) {
10635  res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10636  } else {
10637  res = callerid_feed(cs, buf, res, AST_LAW(p));
10638  }
10639  if (res < 0) {
10640  /*
10641  * The previous diagnostic message output likely
10642  * explains why it failed.
10643  */
10644  ast_log(LOG_WARNING,
10645  "Failed to decode CallerID on channel '%s'\n",
10646  ast_channel_name(chan));
10647  break;
10648  } else if (res)
10649  break;
10650  else if (samples > (8000 * 10))
10651  break;
10652  }
10653  }
10654  if (res == 1) {
10655  callerid_get(cs, &name, &number, &flags);
10656  ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10657  }
10658 
10659  if (p->cid_signalling == CID_SIG_V23_JP) {
10660  res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10661  usleep(1);
10662  }
10663 
10664  /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10665  start = ast_tvnow();
10666  off_ms = 4000;/* This is a typical OFF time between rings. */
10667  for (;;) {
10668  struct ast_frame *f;
10669 
10670  ms = ast_remaining_ms(start, off_ms);
10671  res = ast_waitfor(chan, ms);
10672  if (res <= 0) {
10673  ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10674  "Exiting simple switch\n");
10675  ast_hangup(chan);
10676  goto quit;
10677  }
10678  if (!(f = ast_read(chan))) {
10679  ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10680  ast_hangup(chan);
10681  goto quit;
10682  }
10683  ast_frfree(f);
10684  if (ast_channel_state(chan) == AST_STATE_RING ||
10686  break; /* Got ring */
10687  }
10688 
10689  /* We must have a ring by now, so, if configured, lets try to listen for
10690  * distinctive ringing */
10691  if (p->usedistinctiveringdetection) {
10692  len = 0;
10693  distMatches = 0;
10694  /* Clear the current ring data array so we don't have old data in it. */
10695  for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10696  curRingData[receivedRingT] = 0;
10697  receivedRingT = 0;
10698  counter = 0;
10699  counter1 = 0;
10700  /* Check to see if context is what it should be, if not set to be. */
10701  if (strcmp(p->context,p->defcontext) != 0) {
10702  ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10703  ast_channel_context_set(chan, p->defcontext);
10704  }
10705 
10706  for (;;) {
10707  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10708  if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10709  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10710  callerid_free(cs);
10711  ast_hangup(chan);
10712  goto quit;
10713  }
10714  if (i & DAHDI_IOMUX_SIGEVENT) {
10715  res = dahdi_get_event(p->subs[idx].dfd);
10716  ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10717  if (res == DAHDI_EVENT_NOALARM) {
10718  p->inalarm = 0;
10719  }
10720  res = 0;
10721  /* Let us detect distinctive ring */
10722 
10723  curRingData[receivedRingT] = p->ringt;
10724 
10725  if (p->ringt < p->ringt_base/2)
10726  break;
10727  /* Increment the ringT counter so we can match it against
10728  values in chan_dahdi.conf for distinctive ring */
10729  if (++receivedRingT == ARRAY_LEN(curRingData))
10730  break;
10731  } else if (i & DAHDI_IOMUX_READ) {
10732  res = read(p->subs[idx].dfd, buf, sizeof(buf));
10733  if (res < 0) {
10734  if (errno != ELAST) {
10735  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10736  callerid_free(cs);
10737  ast_hangup(chan);
10738  goto quit;
10739  }
10740  break;
10741  }
10742  if (p->ringt > 0) {
10743  if (!(--p->ringt)) {
10744  res = -1;
10745  break;
10746  }
10747  }
10748  }
10749  }
10750  /* this only shows up if you have n of the dring patterns filled in */
10751  ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10752  for (counter = 0; counter < 3; counter++) {
10753  /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10754  channel */
10755  distMatches = 0;
10756  for (counter1 = 0; counter1 < 3; counter1++) {
10757  ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10758  if (p->drings.ringnum[counter].ring[counter1] == -1) {
10759  ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10760  curRingData[counter1]);
10761  distMatches++;
10762  } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10763  curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10764  ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10765  (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10766  (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10767  distMatches++;
10768  }
10769  }
10770 
10771  if (distMatches == 3) {
10772  /* The ring matches, set the context to whatever is for distinctive ring.. */
10773  ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10774  ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext));
10775  ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10776  break;
10777  }
10778  }
10779  }
10780  /* Restore linear mode (if appropriate) for Caller*ID processing */
10781  dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10782 #if 1
10783  restore_gains(p);
10784 #endif
10785  } else
10786  ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10787  } else {
10788  ast_log(LOG_WARNING, "Channel %s in prering "
10789  "state, but I have nothing to do. "
10790  "Terminating simple switch, should be "
10791  "restarted by the actual ring.\n",
10792  ast_channel_name(chan));
10793  ast_hangup(chan);
10794  goto quit;
10795  }
10796  } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10797  if (p->cid_signalling == CID_SIG_DTMF) {
10798  int k = 0;
10799  int off_ms;
10800  struct timeval start;
10801  int ms;
10802  cs = NULL;
10803  dahdi_setlinear(p->subs[idx].dfd, 0);
10804  off_ms = 2000;
10805  start = ast_tvnow();
10806  for (;;) {
10807  struct ast_frame *f;
10808 
10809  ms = ast_remaining_ms(start, off_ms);
10810  res = ast_waitfor(chan, ms);
10811  if (res <= 0) {
10812  ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10813  "Exiting simple switch\n");
10814  ast_hangup(chan);
10815  goto quit;
10816  }
10817  f = ast_read(chan);
10818  if (!f) {
10819  /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10820  ast_hangup(chan);
10821  goto quit;
10822  }
10823  if (f->frametype == AST_FRAME_DTMF) {
10824  dtmfbuf[k++] = f->subclass.integer;
10825  ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10826  start = ast_tvnow();
10827  }
10828  ast_frfree(f);
10829 
10830  if (p->ringt_base == p->ringt)
10831  break;
10832  }
10833  dtmfbuf[k] = '\0';
10834  dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10835  /* Got cid and ring. */
10836  callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10837  ast_debug(1, "CID is '%s', flags %d\n",
10838  dtmfcid, flags);
10839  /* If first byte is NULL, we have no cid */
10840  if (!ast_strlen_zero(dtmfcid))
10841  number = dtmfcid;
10842  else
10843  number = NULL;
10844  /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10845  } else {
10846  /* FSK Bell202 callerID */
10847  cs = callerid_new(p->cid_signalling);
10848  if (cs) {
10849 #if 1
10850  bump_gains(p);
10851 #endif
10852  samples = 0;
10853  len = 0;
10854  distMatches = 0;
10855  /* Clear the current ring data array so we don't have old data in it. */
10856  for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10857  curRingData[receivedRingT] = 0;
10858  receivedRingT = 0;
10859  counter = 0;
10860  counter1 = 0;
10861  /* Check to see if context is what it should be, if not set to be. */
10862  if (strcmp(p->context,p->defcontext) != 0) {
10863  ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10864  ast_channel_context_set(chan, p->defcontext);
10865  }
10866 
10867  /* Take out of linear mode for Caller*ID processing */
10868  dahdi_setlinear(p->subs[idx].dfd, 0);
10869  for (;;) {
10870  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10871  if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10872  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10873  callerid_free(cs);
10874  ast_hangup(chan);
10875  goto quit;
10876  }
10877  if (i & DAHDI_IOMUX_SIGEVENT) {
10878  res = dahdi_get_event(p->subs[idx].dfd);
10879  ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10880  if (res == DAHDI_EVENT_NOALARM) {
10881  p->inalarm = 0;
10882  }
10883  /* If we get a PR event, they hung up while processing calerid */
10884  if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10885  ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10886  p->polarity = POLARITY_IDLE;
10887  callerid_free(cs);
10888  ast_hangup(chan);
10889  goto quit;
10890  }
10891  res = 0;
10892  /* Let us detect callerid when the telco uses distinctive ring */
10893 
10894  curRingData[receivedRingT] = p->ringt;
10895 
10896  if (p->ringt < p->ringt_base/2)
10897  break;
10898  /* Increment the ringT counter so we can match it against
10899  values in chan_dahdi.conf for distinctive ring */
10900  if (++receivedRingT == ARRAY_LEN(curRingData))
10901  break;
10902  } else if (i & DAHDI_IOMUX_READ) {
10903  res = read(p->subs[idx].dfd, buf, sizeof(buf));
10904  if (res < 0) {
10905  if (errno != ELAST) {
10906  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10907  callerid_free(cs);
10908  ast_hangup(chan);
10909  goto quit;
10910  }
10911  break;
10912  }
10913  if (p->ringt > 0) {
10914  if (!(--p->ringt)) {
10915  res = -1;
10916  break;
10917  }
10918  }
10919  samples += res;
10920  res = callerid_feed(cs, buf, res, AST_LAW(p));
10921  if (res < 0) {
10922  /*
10923  * The previous diagnostic message output likely
10924  * explains why it failed.
10925  */
10926  ast_log(LOG_WARNING,
10927  "Failed to decode CallerID on channel '%s'\n",
10928  ast_channel_name(chan));
10929  break;
10930  } else if (res)
10931  break;
10932  else if (samples > (8000 * 10))
10933  break;
10934  }
10935  }
10936  if (res == 1) {
10937  callerid_get(cs, &name, &number, &flags);
10938  ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10939  }
10940  if (distinctiveringaftercid == 1) {
10941  /* Clear the current ring data array so we don't have old data in it. */
10942  for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10943  curRingData[receivedRingT] = 0;
10944  }
10945  receivedRingT = 0;
10946  ast_verb(3, "Detecting post-CID distinctive ring\n");
10947  for (;;) {
10948  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10949  if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10950  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10951  callerid_free(cs);
10952  ast_hangup(chan);
10953  goto quit;
10954  }
10955  if (i & DAHDI_IOMUX_SIGEVENT) {
10956  res = dahdi_get_event(p->subs[idx].dfd);
10957  ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10958  if (res == DAHDI_EVENT_NOALARM) {
10959  p->inalarm = 0;
10960  }
10961  res = 0;
10962  /* Let us detect callerid when the telco uses distinctive ring */
10963 
10964  curRingData[receivedRingT] = p->ringt;
10965 
10966  if (p->ringt < p->ringt_base/2)
10967  break;
10968  /* Increment the ringT counter so we can match it against
10969  values in chan_dahdi.conf for distinctive ring */
10970  if (++receivedRingT == ARRAY_LEN(curRingData))
10971  break;
10972  } else if (i & DAHDI_IOMUX_READ) {
10973  res = read(p->subs[idx].dfd, buf, sizeof(buf));
10974  if (res < 0) {
10975  if (errno != ELAST) {
10976  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10977  callerid_free(cs);
10978  ast_hangup(chan);
10979  goto quit;
10980  }
10981  break;
10982  }
10983  if (p->ringt > 0) {
10984  if (!(--p->ringt)) {
10985  res = -1;
10986  break;
10987  }
10988  }
10989  }
10990  }
10991  }
10992  if (p->usedistinctiveringdetection) {
10993  /* this only shows up if you have n of the dring patterns filled in */
10994  ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10995 
10996  for (counter = 0; counter < 3; counter++) {
10997  /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10998  channel */
10999  /* this only shows up if you have n of the dring patterns filled in */
11000  ast_verb(3, "Checking %d,%d,%d\n",
11001  p->drings.ringnum[counter].ring[0],
11002  p->drings.ringnum[counter].ring[1],
11003  p->drings.ringnum[counter].ring[2]);
11004  distMatches = 0;
11005  for (counter1 = 0; counter1 < 3; counter1++) {
11006  ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
11007  if (p->drings.ringnum[counter].ring[counter1] == -1) {
11008  ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
11009  curRingData[counter1]);
11010  distMatches++;
11011  }
11012  else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
11013  curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
11014  ast_verb(3, "Ring pattern matched in range: %d to %d\n",
11015  (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
11016  (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
11017  distMatches++;
11018  }
11019  }
11020  if (distMatches == 3) {
11021  /* The ring matches, set the context to whatever is for distinctive ring.. */
11022  ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11023  ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext));
11024  ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11025  break;
11026  }
11027  }
11028  }
11029  /* Restore linear mode (if appropriate) for Caller*ID processing */
11030  dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11031 #if 1
11032  restore_gains(p);
11033 #endif
11034  if (res < 0) {
11035  ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", ast_channel_name(chan));
11036  }
11037  } else
11038  ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11039  }
11040  } else
11041  cs = NULL;
11042 
11043  if (number)
11044  ast_shrink_phone_number(number);
11045  ast_set_callerid(chan, number, name, number);
11046 
11047  ao2_cleanup(smdi_msg);
11048 
11049  if (cs)
11050  callerid_free(cs);
11051 
11052  my_handle_notify_message(chan, p, flags, -1);
11053 
11054  ast_channel_lock(chan);
11056  ast_channel_rings_set(chan, 1);
11057  ast_channel_unlock(chan);
11058  p->ringt = p->ringt_base;
11059  res = ast_pbx_run(chan);
11060  if (res) {
11061  ast_hangup(chan);
11062  ast_log(LOG_WARNING, "PBX exited non-zero\n");
11063  }
11064  goto quit;
11065  default:
11066  ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11067  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11068  if (res < 0)
11069  ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11070  }
11071  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11072  if (res < 0)
11073  ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11074  ast_hangup(chan);
11075 quit:
11076  ast_mutex_lock(&ss_thread_lock);
11077  ss_thread_count--;
11078  ast_cond_signal(&ss_thread_complete);
11079  ast_mutex_unlock(&ss_thread_lock);
11080  return NULL;
11081 }
11082 
11084  struct dahdi_pvt *pvt;
11085  unsigned char buf[READ_SIZE];
11086  size_t len;
11087 };
11088 
11089 static int calc_energy(const unsigned char *buf, int len, struct ast_format *law)
11090 {
11091  int x;
11092  int sum = 0;
11093 
11094  if (!len)
11095  return 0;
11096 
11097  for (x = 0; x < len; x++)
11098  sum += abs(law == ast_format_ulaw ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11099 
11100  return sum / len;
11101 }
11102 
11103 static void *mwi_thread(void *data)
11104 {
11105  struct mwi_thread_data *mtd = data;
11106  struct callerid_state *cs;
11107  pthread_t threadid;
11108  int samples = 0;
11109  char *name, *number;
11110  int flags;
11111  int i, res;
11112  unsigned int spill_done = 0;
11113  int spill_result = -1;
11114 
11115  if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11116  goto quit_no_clean;
11117  }
11118 
11119  callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11120 
11121  bump_gains(mtd->pvt);
11122 
11123  for (;;) {
11124  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11125  if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11126  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11127  goto quit;
11128  }
11129 
11130  if (i & DAHDI_IOMUX_SIGEVENT) {
11131  struct ast_channel *chan;
11132  ast_callid callid = 0;
11133  int callid_created;
11134 
11135  /* If we get an event, screen out events that we do not act on.
11136  * Otherwise, cancel and go to the simple switch to let it deal with it.
11137  */
11138  res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11139 
11140  switch (res) {
11141  case DAHDI_EVENT_NEONMWI_ACTIVE:
11142  case DAHDI_EVENT_NEONMWI_INACTIVE:
11143  case DAHDI_EVENT_NONE:
11144  case DAHDI_EVENT_BITSCHANGED:
11145  break;
11146  case DAHDI_EVENT_NOALARM:
11147  if (dahdi_analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11148  struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11149 
11150  analog_p->inalarm = 0;
11151  }
11152  mtd->pvt->inalarm = 0;
11153  handle_clear_alarms(mtd->pvt);
11154  break;
11155  case DAHDI_EVENT_ALARM:
11156  if (dahdi_analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11157  struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11158 
11159  analog_p->inalarm = 1;
11160  }
11161  mtd->pvt->inalarm = 1;
11162  res = get_alarms(mtd->pvt);
11163  handle_alarms(mtd->pvt, res);
11164  break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
11165  default:
11166  callid_created = ast_callid_threadstorage_auto(&callid);
11167  ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
11168  callerid_free(cs);
11169 
11170  restore_gains(mtd->pvt);
11171  mtd->pvt->ringt = mtd->pvt->ringt_base;
11172 
11173  if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL, NULL, callid))) {
11174  int result;
11175 
11176  if (dahdi_analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11177  result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11178  } else {
11179  result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11180  }
11181  if (result) {
11182  ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11183  res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11184  if (res < 0)
11185  ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11186  ast_hangup(chan);
11187  }
11188  } else {
11189  ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11190  }
11191 
11192  ast_callid_threadstorage_auto_clean(callid, callid_created);
11193  goto quit_no_clean;
11194  }
11195  } else if (i & DAHDI_IOMUX_READ) {
11196  if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11197  if (errno != ELAST) {
11198  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11199  goto quit;
11200  }
11201  break;
11202  }
11203  samples += res;
11204  if (!spill_done) {
11205  if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11206  /*
11207  * The previous diagnostic message output likely
11208  * explains why it failed.
11209  */
11210  ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11211  break;
11212  } else if (spill_result) {
11213  spill_done = 1;
11214  }
11215  } else {
11216  /* keep reading data until the energy level drops below the threshold
11217  so we don't get another 'trigger' on the remaining carrier signal
11218  */
11219  if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11220  break;
11221  }
11222  if (samples > (8000 * 4)) /*Termination case - time to give up*/
11223  break;
11224  }
11225  }
11226 
11227  if (spill_result == 1) {
11228  callerid_get(cs, &name, &number, &flags);
11229  if (flags & CID_MSGWAITING) {
11230  ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11231  notify_message(mtd->pvt->mailbox, 1);
11232  } else if (flags & CID_NOMSGWAITING) {
11233  ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11234  notify_message(mtd->pvt->mailbox, 0);
11235  } else {
11236  ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11237  }
11238  }
11239 
11240 
11241 quit:
11242  callerid_free(cs);
11243 
11244  restore_gains(mtd->pvt);
11245 
11246 quit_no_clean:
11247  mtd->pvt->mwimonitoractive = 0;
11248  ast_free(mtd);
11249 
11250  return NULL;
11251 }
11252 
11253 /*
11254 * The following three functions (mwi_send_init, mwi_send_process_buffer,
11255 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
11256 * that are sent out via FXS port on voicemail state change. The execution of
11257 * the mwi send is state driven and can either generate a ring pulse prior to
11258 * sending the fsk spill or simply send an fsk spill.
11259 */
11260 static int mwi_send_init(struct dahdi_pvt * pvt)
11261 {
11262  int x;
11263 
11264 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11265  /* Determine how this spill is to be sent */
11266  if (pvt->mwisend_rpas) {
11267  pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11268  pvt->mwisendactive = 1;
11269  } else if (pvt->mwisend_fsk) {
11270  pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11271  pvt->mwisendactive = 1;
11272  } else {
11273  pvt->mwisendactive = 0;
11274  return 0;
11275  }
11276 #else
11277  if (mwisend_rpas) {
11278  pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11279  } else {
11280  pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11281  }
11282  pvt->mwisendactive = 1;
11283 #endif
11284 
11285  if (pvt->cidspill) {
11286  ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11287  ast_free(pvt->cidspill);
11288  pvt->cidspill = NULL;
11289  pvt->cidpos = 0;
11290  pvt->cidlen = 0;
11291  }
11292  pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11293  if (!pvt->cidspill) {
11294  pvt->mwisendactive = 0;
11295  return -1;
11296  }
11297  x = DAHDI_FLUSH_BOTH;
11298  ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11299  x = 3000;
11300  ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11301 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11302  if (pvt->mwisend_fsk) {
11303 #endif
11305  CID_MWI_TYPE_MDMF_FULL, AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11306  pvt->cidpos = 0;
11307 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11308  }
11309 #endif
11310  return 0;
11311 }
11312 
11313 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11314 {
11315  struct timeval now;
11316  int res;
11317 
11318  /* sanity check to catch if this had been interrupted previously
11319  * i.e. state says there is more to do but there is no spill allocated
11320  */
11321  if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11322  pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11323  } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11324  /* Normal processing -- Perform mwi send action */
11325  switch ( pvt->mwisend_data.mwisend_current) {
11326  case MWI_SEND_SA:
11327  /* Send the Ring Pulse Signal Alert */
11328  res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11329  if (res) {
11330  ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11331  goto quit;
11332  }
11333  res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11334  pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11335  break;
11336  case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */
11337  break;
11338  case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/
11339 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11340  if (pvt->mwisend_fsk) {
11341 #endif
11342  gettimeofday(&now, NULL);
11343  if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11344  pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11345  }
11346 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11347  } else { /* support for mwisendtype=nofsk */
11348  pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11349  }
11350 #endif
11351  break;
11352  case MWI_SEND_SPILL:
11353  /* We read some number of bytes. Write an equal amount of data */
11354  if (0 < num_read) {
11355  if (num_read > pvt->cidlen - pvt->cidpos) {
11356  num_read = pvt->cidlen - pvt->cidpos;
11357  }
11358  res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11359  if (res > 0) {
11360  pvt->cidpos += res;
11361  if (pvt->cidpos >= pvt->cidlen) {
11362  pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11363  }
11364  } else {
11365  ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11366  goto quit;
11367  }
11368  }
11369  break;
11370  case MWI_SEND_CLEANUP:
11371  /* For now, do nothing */
11372  pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11373  break;
11374  default:
11375  /* Should not get here, punt*/
11376  goto quit;
11377  }
11378  }
11379 
11380  if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11381  if (pvt->cidspill) {
11382  ast_free(pvt->cidspill);
11383  pvt->cidspill = NULL;
11384  pvt->cidpos = 0;
11385  pvt->cidlen = 0;
11386  }
11387  pvt->mwisendactive = 0;
11388  }
11389  return 0;
11390 quit:
11391  if (pvt->cidspill) {
11392  ast_free(pvt->cidspill);
11393  pvt->cidspill = NULL;
11394  pvt->cidpos = 0;
11395  pvt->cidlen = 0;
11396  }
11397  pvt->mwisendactive = 0;
11398  return -1;
11399 }
11400 
11401 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11402 {
11403  int handled = 0;
11404 
11405  if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11406  switch (event) {
11407  case DAHDI_EVENT_RINGEROFF:
11408  if (pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11409  handled = 1;
11410 
11411  if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11412  ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11413  ast_free(pvt->cidspill);
11414  pvt->cidspill = NULL;
11415  pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11416  pvt->mwisendactive = 0;
11417  } else {
11418  pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11419  gettimeofday(&pvt->mwisend_data.pause, NULL);
11420  }
11421  }
11422  break;
11423  /* Going off hook, I need to punt this spill */
11424  case DAHDI_EVENT_RINGOFFHOOK:
11425  if (pvt->cidspill) {
11426  ast_free(pvt->cidspill);
11427  pvt->cidspill = NULL;
11428  pvt->cidpos = 0;
11429  pvt->cidlen = 0;
11430  }
11431  pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11432  pvt->mwisendactive = 0;
11433  break;
11434  case DAHDI_EVENT_RINGERON:
11435  case DAHDI_EVENT_HOOKCOMPLETE:
11436  break;
11437  default:
11438  break;
11439  }
11440  }
11441  return handled;
11442 }
11443 
11444 /* destroy a range DAHDI channels, identified by their number */
11445 static void dahdi_destroy_channel_range(int start, int end)
11446 {
11447  struct dahdi_pvt *cur;
11448  struct dahdi_pvt *next;
11449  int destroyed_first = 0;
11450  int destroyed_last = 0;
11451 
11452  ast_mutex_lock(&iflock);
11453  ast_debug(1, "range: %d-%d\n", start, end);
11454  for (cur = iflist; cur; cur = next) {
11455  next = cur->next;
11456  if (cur->channel >= start && cur->channel <= end) {
11457  int x = DAHDI_FLASH;
11458 
11459  if (cur->channel > destroyed_last) {
11460  destroyed_last = cur->channel;
11461  }
11462  if (destroyed_first < 1 || cur->channel < destroyed_first) {
11463  destroyed_first = cur->channel;
11464  }
11465  ast_debug(3, "Destroying %d\n", cur->channel);
11466  /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11467  ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11468 
11469  destroy_channel(cur, 1);
11471  }
11472  }
11473  ast_mutex_unlock(&iflock);
11474  if (destroyed_first > start || destroyed_last < end) {
11475  ast_debug(1, "Asked to destroy %d-%d, destroyed %d-%d,\n",
11476  start, end, destroyed_first, destroyed_last);
11477  }
11478 }
11479 
11480 #ifdef HAVE_OPENR2
11481 static void dahdi_r2_destroy_nodev(void)
11482 {
11483  struct r2link_entry *cur;
11484  AST_LIST_LOCK(&nodev_r2links);
11485  AST_LIST_TRAVERSE_SAFE_BEGIN(&nodev_r2links, cur, list) {
11486  int i;
11487  struct dahdi_mfcr2 *r2 = &cur->mfcr2;
11488  ast_debug(3, "About to destroy %d DAHDI channels of MFC/R2 link.\n", r2->numchans);
11489  for (i = 0; i < r2->numchans; i++) {
11490  int channel;
11491  struct dahdi_pvt *pvt = r2->pvts[i];
11492  if (!pvt) {
11493  continue;
11494  }
11495  channel = pvt->channel;
11496  ast_debug(3, "About to destroy B-channel %d.\n", channel);
11497  dahdi_destroy_channel_range(channel, channel);
11498  }
11499  ast_debug(3, "Destroying R2 link\n");
11500  AST_LIST_REMOVE(&nodev_r2links, cur, list);
11501  if (r2->r2master != AST_PTHREADT_NULL) {
11502  pthread_cancel(r2->r2master);
11503  pthread_join(r2->r2master, NULL);
11504  r2->r2master = AST_PTHREADT_NULL;
11505  openr2_context_delete(r2->protocol_context);
11506  }
11507  ast_free(cur);
11508  }
11510  AST_LIST_UNLOCK(&nodev_r2links);
11511 }
11512 #endif
11513 
11514 static int setup_dahdi(int reload);
11515 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf);
11516 
11517 /*!
11518  * \internal
11519  * \brief create a range of new DAHDI channels
11520  *
11521  * \param start first channel in the range
11522  * \param end last channel in the range
11523  *
11524  * \retval RESULT_SUCCESS on success.
11525  * \retval RESULT_FAILURE on error.
11526  */
11527 static int dahdi_create_channel_range(int start, int end)
11528 {
11529  struct dahdi_pvt *cur;
11530  struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
11531  struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
11533  int ret = RESULT_FAILURE; /* be pessimistic */
11534 
11535  ast_debug(1, "channel range caps: %d - %d\n", start, end);
11536  ast_mutex_lock(&iflock);
11537  for (cur = iflist; cur; cur = cur->next) {
11538  if (cur->channel >= start && cur->channel <= end) {
11539  ast_log(LOG_ERROR,
11540  "channel range %d-%d is occupied\n",
11541  start, end);
11542  goto out;
11543  }
11544  }
11545 #ifdef HAVE_PRI
11546  {
11547  int i, x;
11548  for (x = 0; x < NUM_SPANS; x++) {
11549  struct dahdi_pri *pri = pris + x;
11550 
11551  if (!pris[x].pri.pvts[0]) {
11552  break;
11553  }
11554  for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
11555  int channo = pri->dchannels[i];
11556 
11557  if (!channo) {
11558  break;
11559  }
11560  if (!pri->pri.fds[i]) {
11561  break;
11562  }
11563  if (channo >= start && channo <= end) {
11564  ast_log(LOG_ERROR,
11565  "channel range %d-%d is occupied by span %d\n",
11566  start, end, x + 1);
11567  goto out;
11568  }
11569  }
11570  }
11571  }
11572 #endif
11573  if (!default_conf.chan.cc_params || !base_conf.chan.cc_params ||
11574  !conf.chan.cc_params) {
11575  goto out;
11576  }
11577  default_conf.wanted_channels_start = start;
11578  base_conf.wanted_channels_start = start;
11579  conf.wanted_channels_start = start;
11580  default_conf.wanted_channels_end = end;
11581  base_conf.wanted_channels_end = end;
11582  conf.wanted_channels_end = end;
11583  if (setup_dahdi_int(0, &default_conf, &base_conf, &conf) == 0) {
11584  ret = RESULT_SUCCESS;
11585  }
11586 out:
11587  ast_cc_config_params_destroy(default_conf.chan.cc_params);
11588  ast_cc_config_params_destroy(base_conf.chan.cc_params);
11589  ast_cc_config_params_destroy(conf.chan.cc_params);
11590  ast_mutex_unlock(&iflock);
11591  return ret;
11592 }
11593 
11594 
11595 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11596 {
11597  int res;
11598  pthread_t threadid;
11599  struct ast_channel *chan;
11600  ast_callid callid = 0;
11601  int callid_created;
11602 
11603  /* Handle an event on a given channel for the monitor thread. */
11604 
11605  switch (event) {
11606  case DAHDI_EVENT_NONE:
11607  case DAHDI_EVENT_BITSCHANGED:
11608  break;
11609  case DAHDI_EVENT_WINKFLASH:
11610  case DAHDI_EVENT_RINGOFFHOOK:
11611  if (i->inalarm) break;
11612  if (i->radio) break;
11613  /* Got a ring/answer. What kind of channel are we? */
11614  switch (i->sig) {
11615  case SIG_FXOLS:
11616  case SIG_FXOGS:
11617  case SIG_FXOKS:
11618  res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11619  if (res && (errno == EBUSY)) {
11620  break;
11621  }
11622 
11623  callid_created = ast_callid_threadstorage_auto(&callid);
11624 
11625  /* Cancel VMWI spill */
11626  ast_free(i->cidspill);
11627  i->cidspill = NULL;
11628  restore_conference(i);
11629 
11630  if (i->immediate) {
11631  dahdi_ec_enable(i);
11632  /* The channel is immediately up. Start right away */
11633  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11634  chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL, NULL, callid);
11635  if (!chan) {
11636  ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11637  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11638  if (res < 0)
11639  ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11640  }
11641  } else {
11642  /* Check for callerid, digits, etc */
11643  chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL, NULL, callid);
11644  if (chan) {
11645  if (has_voicemail(i))
11646  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11647  else
11648  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11649  if (res < 0)
11650  ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11651  if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11652  ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11653  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11654  if (res < 0)
11655  ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11656  ast_hangup(chan);
11657  }
11658  } else
11659  ast_log(LOG_WARNING, "Unable to create channel\n");
11660  }
11661 
11662  ast_callid_threadstorage_auto_clean(callid, callid_created);
11663  break;
11664  case SIG_FXSLS:
11665  case SIG_FXSGS:
11666  case SIG_FXSKS:
11667  i->ringt = i->ringt_base;
11668  /* Fall through */
11669  case SIG_EMWINK:
11670  case SIG_FEATD:
11671  case SIG_FEATDMF:
11672  case SIG_FEATDMF_TA:
11673  case SIG_E911:
11674  case SIG_FGC_CAMA:
11675  case SIG_FGC_CAMAMF:
11676  case SIG_FEATB:
11677  case SIG_EM:
11678  case SIG_EM_E1:
11679  case SIG_SFWINK:
11680  case SIG_SF_FEATD:
11681  case SIG_SF_FEATDMF:
11682  case SIG_SF_FEATB:
11683  case SIG_SF:
11684  /* Check for callerid, digits, etc */
11685  callid_created = ast_callid_threadstorage_auto(&callid);
11686  if (i->cid_start == CID_START_POLARITY_IN) {
11687  chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
11688  } else {
11689  chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL, NULL, callid);
11690  }
11691 
11692  if (!chan) {
11693  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11694  } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11695  ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11696  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11697  if (res < 0) {
11698  ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11699  }
11700  ast_hangup(chan);
11701  }
11702 
11703  ast_callid_threadstorage_auto_clean(callid, callid_created);
11704  break;
11705  default:
11706  ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11707  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11708  if (res < 0)
11709  ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11710  return NULL;
11711  }
11712  break;
11713  case DAHDI_EVENT_NOALARM:
11714  switch (i->sig) {
11715 #if defined(HAVE_PRI)
11716  case SIG_PRI_LIB_HANDLE_CASES:
11717  ast_mutex_lock(&i->lock);
11718  sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11719  ast_mutex_unlock(&i->lock);
11720  break;
11721 #endif /* defined(HAVE_PRI) */
11722 #if defined(HAVE_SS7)
11723  case SIG_SS7:
11724  sig_ss7_set_alarm(i->sig_pvt, 0);
11725  break;
11726 #endif /* defined(HAVE_SS7) */
11727  default:
11728  i->inalarm = 0;
11729  break;
11730  }
11731  handle_clear_alarms(i);
11732  break;
11733  case DAHDI_EVENT_ALARM:
11734  switch (i->sig) {
11735 #if defined(HAVE_PRI)
11736  case SIG_PRI_LIB_HANDLE_CASES:
11737  ast_mutex_lock(&i->lock);
11738  sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11739  ast_mutex_unlock(&i->lock);
11740  break;
11741 #endif /* defined(HAVE_PRI) */
11742 #if defined(HAVE_SS7)
11743  case SIG_SS7:
11744  sig_ss7_set_alarm(i->sig_pvt, 1);
11745  break;
11746 #endif /* defined(HAVE_SS7) */
11747  default:
11748  i->inalarm = 1;
11749  break;
11750  }
11751  res = get_alarms(i);
11752  handle_alarms(i, res);
11753  /* fall thru intentionally */
11754  case DAHDI_EVENT_ONHOOK:
11755  if (i->radio)
11756  break;
11757  /* Back on hook. Hang up. */
11758  switch (i->sig) {
11759  case SIG_FXOLS:
11760  case SIG_FXOGS:
11761  case SIG_FEATD:
11762  case SIG_FEATDMF:
11763  case SIG_FEATDMF_TA:
11764  case SIG_E911:
11765  case SIG_FGC_CAMA:
11766  case SIG_FGC_CAMAMF:
11767  case SIG_FEATB:
11768  case SIG_EM:
11769  case SIG_EM_E1:
11770  case SIG_EMWINK:
11771  case SIG_SF_FEATD:
11772  case SIG_SF_FEATDMF:
11773  case SIG_SF_FEATB:
11774  case SIG_SF:
11775  case SIG_SFWINK:
11776  case SIG_FXSLS:
11777  case SIG_FXSGS:
11778  case SIG_FXSKS:
11779  case SIG_FXOKS:
11780  dahdi_ec_disable(i);
11781  /* Diddle the battery for the zhone */
11782 #ifdef ZHONE_HACK
11783  dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11784  usleep(1);
11785 #endif
11786  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11787  dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11788  break;
11789  case SIG_SS7:
11790  case SIG_PRI_LIB_HANDLE_CASES:
11791  dahdi_ec_disable(i);
11792  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11793  break;
11794  default:
11795  ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11796  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11797  return NULL;
11798  }
11799  break;
11800  case DAHDI_EVENT_POLARITY:
11801  switch (i->sig) {
11802  case SIG_FXSLS:
11803  case SIG_FXSKS:
11804  case SIG_FXSGS:
11805  /* We have already got a PR before the channel was
11806  created, but it wasn't handled. We need polarity
11807  to be REV for remote hangup detection to work.
11808  At least in Spain */
11809  callid_created = ast_callid_threadstorage_auto(&callid);
11810  if (i->hanguponpolarityswitch)
11811  i->polarity = POLARITY_REV;
11812  if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11813  i->polarity = POLARITY_REV;
11814  ast_verb(2, "Starting post polarity "
11815  "CID detection on channel %d\n",
11816  i->channel);
11817  chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
11818  if (!chan) {
11819  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11820  } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11821  ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11822  ast_hangup(chan);
11823  }
11824  }
11825  ast_callid_threadstorage_auto_clean(callid, callid_created);
11826  break;
11827  default:
11828  ast_log(LOG_WARNING, "handle_init_event detected "
11829  "polarity reversal on non-FXO (SIG_FXS) "
11830  "interface %d\n", i->channel);
11831  }
11832  break;
11833  case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11834  ast_log(LOG_NOTICE,
11835  "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11836  i->channel);
11837  return i;
11838  case DAHDI_EVENT_NEONMWI_ACTIVE:
11839  if (i->mwimonitor_neon) {
11840  notify_message(i->mailbox, 1);
11841  ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11842  }
11843  break;
11844  case DAHDI_EVENT_NEONMWI_INACTIVE:
11845  if (i->mwimonitor_neon) {
11846  notify_message(i->mailbox, 0);
11847  ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11848  }
11849  break;
11850  }
11851  return NULL;
11852 }
11853 
11854 static void monitor_pfds_clean(void *arg) {
11855  struct pollfd **pfds = arg;
11856  ast_free(*pfds);
11857 }
11858 
11859 static void *do_monitor(void *data)
11860 {
11861  int count, res, res2, spoint, pollres=0;
11862  struct dahdi_pvt *i;
11863  struct dahdi_pvt *last = NULL;
11864  struct dahdi_pvt *doomed;
11865  time_t thispass = 0, lastpass = 0;
11866  int found;
11867  char buf[1024];
11868  struct pollfd *pfds=NULL;
11869  int lastalloc = -1;
11870  /* This thread monitors all the frame relay interfaces which are not yet in use
11871  (and thus do not have a separate thread) indefinitely */
11872  /* From here on out, we die whenever asked */
11873 #if 0
11874  if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11875  ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11876  return NULL;
11877  }
11878  ast_debug(1, "Monitor starting...\n");
11879 #endif
11880  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11881 
11882  pthread_cleanup_push(monitor_pfds_clean, &pfds);
11883  for (;;) {
11884  /* Lock the interface list */
11885  ast_mutex_lock(&iflock);
11886  if (!pfds || (lastalloc != ifcount)) {
11887  if (pfds) {
11888  ast_free(pfds);
11889  pfds = NULL;
11890  }
11891  if (ifcount) {
11892  if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11893  ast_mutex_unlock(&iflock);
11894  return NULL;
11895  }
11896  }
11897  lastalloc = ifcount;
11898  }
11899  /* Build the stuff we're going to poll on, that is the socket of every
11900  dahdi_pvt that does not have an associated owner channel */
11901  count = 0;
11902  for (i = iflist; i; i = i->next) {
11903  ast_mutex_lock(&i->lock);
11904  if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11905  if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11906  struct analog_pvt *p = i->sig_pvt;
11907 
11908  if (!p) {
11909  ast_log(LOG_ERROR, "No sig_pvt?\n");
11910  } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11911  /* This needs to be watched, as it lacks an owner */
11912  pfds[count].fd = i->subs[SUB_REAL].dfd;
11913  pfds[count].events = POLLPRI;
11914  pfds[count].revents = 0;
11915  /* Message waiting or r2 channels also get watched for reading */
11916  if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11917  (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11918  pfds[count].events |= POLLIN;
11919  }
11920  count++;
11921  }
11922  } else {
11923  if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11924  /* This needs to be watched, as it lacks an owner */
11925  pfds[count].fd = i->subs[SUB_REAL].dfd;
11926  pfds[count].events = POLLPRI;
11927  pfds[count].revents = 0;
11928  /* If we are monitoring for VMWI or sending CID, we need to
11929  read from the channel as well */
11930  if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11931  (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11932  pfds[count].events |= POLLIN;
11933  }
11934  count++;
11935  }
11936  }
11937  }
11938  ast_mutex_unlock(&i->lock);
11939  }
11940  /* Okay, now that we know what to do, release the interface lock */
11941  ast_mutex_unlock(&iflock);
11942 
11943  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11944  pthread_testcancel();
11945  /* Wait at least a second for something to happen */
11946  res = poll(pfds, count, 1000);
11947  pthread_testcancel();
11948  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11949 
11950  /* Okay, poll has finished. Let's see what happened. */
11951  if (res < 0) {
11952  if ((errno != EAGAIN) && (errno != EINTR))
11953  ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11954  continue;
11955  }
11956  /* Alright, lock the interface list again, and let's look and see what has
11957  happened */
11958  ast_mutex_lock(&iflock);
11959  found = 0;
11960  spoint = 0;
11961  lastpass = thispass;
11962  thispass = time(NULL);
11963  doomed = NULL;
11964  for (i = iflist;; i = i->next) {
11965  if (doomed) {
11966  dahdi_destroy_channel_range(doomed->channel, doomed->channel);
11967  doomed = NULL;
11968  }
11969  if (!i) {
11970  break;
11971  }
11972 
11973  if (thispass != lastpass) {
11974  if (!found && ((i == last) || ((i == iflist) && !last))) {
11975  last = i;
11976  if (last) {
11977  struct analog_pvt *analog_p = last->sig_pvt;
11978  /* Only allow MWI to be initiated on a quiescent fxs port */
11979  if (analog_p
11980  && !last->mwisendactive
11981  && (last->sig & __DAHDI_SIG_FXO)
11982  && !analog_p->fxsoffhookstate
11983  && !last->owner
11984  && (!ast_strlen_zero(last->mailbox) || last->mwioverride_active)
11985  && !analog_p->subs[SUB_REAL].owner /* could be a recall ring from a flash hook hold */
11986  && (thispass - analog_p->onhooktime > 3)) {
11987  res = has_voicemail(last);
11988  if (analog_p->msgstate != res) {
11989  /* Set driver resources for signalling VMWI */
11990  res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11991  if (res2) {
11992  /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11993  ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11994  }
11995  /* If enabled for FSK spill then initiate it */
11996  if (mwi_send_init(last)) {
11997  ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11998  }
11999  analog_p->msgstate = res;
12000  found ++;
12001  }
12002  }
12003  last = last->next;
12004  }
12005  }
12006  }
12007  if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
12008  if (i->radio && !i->owner)
12009  {
12010  res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12011  if (res)
12012  {
12013  ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
12014  /* Don't hold iflock while handling init events */
12015  ast_mutex_unlock(&iflock);
12016  if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode))
12017  doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12018  else
12019  doomed = handle_init_event(i, res);
12020  ast_mutex_lock(&iflock);
12021  }
12022  continue;
12023  }
12024  pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
12025  if (pollres & POLLIN) {
12026  if (i->owner || i->subs[SUB_REAL].owner) {
12027 #ifdef HAVE_PRI
12028  if (!i->pri)
12029 #endif
12030  ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
12031  continue;
12032  }
12033  if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
12034  ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
12035  continue;
12036  }
12037  res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
12038  if (res > 0) {
12039  if (i->mwimonitor_fsk) {
12040  if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
12041  pthread_attr_t attr;
12042  pthread_t threadid;
12043  struct mwi_thread_data *mtd;
12044 
12045  pthread_attr_init(&attr);
12046  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
12047 
12048  ast_debug(1, "Maybe some MWI on port %d!\n", i->channel);
12049  if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
12050  mtd->pvt = i;
12051  memcpy(mtd->buf, buf, res);
12052  mtd->len = res;
12053  i->mwimonitoractive = 1;
12054  if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
12055  ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
12056  i->mwimonitoractive = 0;
12057  ast_free(mtd);
12058  }
12059  }
12060  }
12061  /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
12062  } else if (i->cid_start == CID_START_DTMF_NOALERT) {
12063  int energy;
12064  struct timeval now;
12065  /* State machine dtmfcid_holdoff_state allows for the line to settle
12066  * before checking agin for dtmf energy. Presently waits for 500 mS before checking again
12067  */
12068  if (1 == i->dtmfcid_holdoff_state) {
12069  gettimeofday(&i->dtmfcid_delay, NULL);
12070  i->dtmfcid_holdoff_state = 2;
12071  } else if (2 == i->dtmfcid_holdoff_state) {
12072  gettimeofday(&now, NULL);
12073  if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
12074  i->dtmfcid_holdoff_state = 0;
12075  }
12076  } else {
12077  energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
12078  if (!i->mwisendactive && energy > dtmfcid_level) {
12079  pthread_t threadid;
12080  struct ast_channel *chan;
12081  ast_mutex_unlock(&iflock);
12082  if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
12083  /* just in case this event changes or somehow destroys a channel, set doomed here too */
12084  doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
12085  i->dtmfcid_holdoff_state = 1;
12086  } else {
12087  ast_callid callid = 0;
12088  int callid_created = ast_callid_threadstorage_auto(&callid);
12089  chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
12090  if (!chan) {
12091  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
12092  } else {
12093  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
12094  if (res) {
12095  ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
12096  ast_hangup(chan);
12097  } else {
12098  i->dtmfcid_holdoff_state = 1;
12099  }
12100  }
12101  ast_callid_threadstorage_auto_clean(callid, callid_created);
12102  }
12103  ast_mutex_lock(&iflock);
12104  }
12105  }
12106  }
12107  if (i->mwisendactive) {
12108  mwi_send_process_buffer(i, res);
12109  }
12110  } else {
12111  ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
12112  }
12113  }
12114  if (pollres & POLLPRI) {
12115  if (i->owner || i->subs[SUB_REAL].owner) {
12116 #ifdef HAVE_PRI
12117  if (!i->pri)
12118 #endif
12119  ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
12120  continue;
12121  }
12122  res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12123  ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
12124  /* Don't hold iflock while handling init events */
12125  ast_mutex_unlock(&iflock);
12126  if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
12127  if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode))
12128  doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12129  else
12130  doomed = handle_init_event(i, res);
12131  }
12132  if (i->doreoriginate && res == DAHDI_EVENT_HOOKCOMPLETE) {
12133  /* Actually automatically reoriginate this FXS line, if directed to.
12134  * We should get a DAHDI_EVENT_HOOKCOMPLETE from the loop disconnect
12135  * doing its thing (one reason why this is for FXOKS only: FXOLS
12136  * hangups don't give us any DAHDI events to piggyback off of)*/
12137  i->doreoriginate = 0;
12138  /* Double check the channel is still off-hook. There's only about a millisecond
12139  * between when doreoriginate is set high and we see that here, but just to be safe. */
12140  if (!my_is_off_hook(i)) {
12141  ast_debug(1, "Woah! Went back on hook before reoriginate could happen on channel %d\n", i->channel);
12142  } else {
12143  ast_verb(3, "Automatic reorigination on channel %d\n", i->channel);
12144  res = DAHDI_EVENT_RINGOFFHOOK; /* Pretend that the physical channel just went off hook */
12145  if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
12146  doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12147  } else {
12148  doomed = handle_init_event(i, res);
12149  }
12150  }
12151  }
12152  ast_mutex_lock(&iflock);
12153  }
12154  }
12155  }
12156  ast_mutex_unlock(&iflock);
12157  release_doomed_pris();
12158 #ifdef HAVE_OPENR2
12159  dahdi_r2_destroy_nodev();
12160 #endif
12161  }
12162  /* Never reached */
12163  pthread_cleanup_pop(1);
12164  return NULL;
12165 
12166 }
12167 
12168 static int restart_monitor(void)
12169 {
12170  /* If we're supposed to be stopped -- stay stopped */
12171  if (monitor_thread == AST_PTHREADT_STOP)
12172  return 0;
12173  ast_mutex_lock(&monlock);
12174  if (monitor_thread == pthread_self()) {
12175  ast_mutex_unlock(&monlock);
12176  ast_log(LOG_WARNING, "Cannot kill myself\n");
12177  return -1;
12178  }
12179  if (monitor_thread != AST_PTHREADT_NULL) {
12180  /* Wake up the thread */
12181  pthread_kill(monitor_thread, SIGURG);
12182  } else {
12183  /* Start a new monitor */
12184  if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
12185  ast_mutex_unlock(&monlock);
12186  ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12187  return -1;
12188  }
12189  }
12190  ast_mutex_unlock(&monlock);
12191  return 0;
12192 }
12193 
12194 #if defined(HAVE_PRI)
12195 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
12196 {
12197  int x;
12198  int trunkgroup;
12199  /* Get appropriate trunk group if there is one */
12200  trunkgroup = pris[*span].mastertrunkgroup;
12201  if (trunkgroup) {
12202  /* Select a specific trunk group */
12203  for (x = 0; x < NUM_SPANS; x++) {
12204  if (pris[x].pri.trunkgroup == trunkgroup) {
12205  *span = x;
12206  return 0;
12207  }
12208  }
12209  ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12210  *span = -1;
12211  } else {
12212  if (pris[*span].pri.trunkgroup) {
12213  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);
12214  *span = -1;
12215  } else if (pris[*span].mastertrunkgroup) {
12216  ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12217  *span = -1;
12218  } else {
12219  if (si->totalchans == 31) {
12220  /* E1 */
12221  pris[*span].dchannels[0] = 16 + offset;
12222  } else if (si->totalchans == 24) {
12223  /* T1 or J1 */
12224  pris[*span].dchannels[0] = 24 + offset;
12225  } else if (si->totalchans == 3) {
12226  /* BRI */
12227  pris[*span].dchannels[0] = 3 + offset;
12228  } else {
12229  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);
12230  *span = -1;
12231  return 0;
12232  }
12233  pris[*span].pri.span = *span + 1;
12234  }
12235  }
12236  return 0;
12237 }
12238 #endif /* defined(HAVE_PRI) */
12239 
12240 #if defined(HAVE_PRI)
12241 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12242 {
12243  struct dahdi_spaninfo si;
12244  struct dahdi_params p;
12245  int fd;
12246  int span;
12247  int ospan=0;
12248  int x,y;
12249  for (x = 0; x < NUM_SPANS; x++) {
12250  if (pris[x].pri.trunkgroup == trunkgroup) {
12251  ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12252  return -1;
12253  }
12254  }
12255  for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12256  if (!channels[y])
12257  break;
12258  memset(&si, 0, sizeof(si));
12259  memset(&p, 0, sizeof(p));
12260  fd = open("/dev/dahdi/channel", O_RDWR);
12261  if (fd < 0) {
12262  ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12263  return -1;
12264  }
12265  x = channels[y];
12266  if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12267  ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12268  close(fd);
12269  return -1;
12270  }
12271  if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12272  ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12273  close(fd);
12274  return -1;
12275  }
12276  if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12277  ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12278  close(fd);
12279  return -1;
12280  }
12281  span = p.spanno - 1;
12282  if (pris[span].pri.trunkgroup) {
12283  ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12284  close(fd);
12285  return -1;
12286  }
12287  if (pris[span].pri.pvts[0]) {
12288  ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12289  close(fd);
12290  return -1;
12291  }
12292  if (!y) {
12293  pris[span].pri.trunkgroup = trunkgroup;
12294  ospan = span;
12295  }
12296  pris[ospan].dchannels[y] = channels[y];
12297  pris[span].pri.span = span + 1;
12298  close(fd);
12299  }
12300  return 0;
12301 }
12302 #endif /* defined(HAVE_PRI) */
12303 
12304 #if defined(HAVE_PRI)
12305 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12306 {
12307  if (pris[span].mastertrunkgroup) {
12308  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);
12309  return -1;
12310  }
12311  pris[span].mastertrunkgroup = trunkgroup;
12312  pris[span].prilogicalspan = logicalspan;
12313  return 0;
12314 }
12315 #endif /* defined(HAVE_PRI) */
12316 
12317 #if defined(HAVE_SS7)
12318 static unsigned int parse_pointcode(const char *pcstring)
12319 {
12320  unsigned int code1, code2, code3;
12321  int numvals;
12322 
12323  numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12324  if (numvals == 1)
12325  return code1;
12326  if (numvals == 3)
12327  return (code1 << 16) | (code2 << 8) | code3;
12328 
12329  return 0;
12330 }
12331 #endif /* defined(HAVE_SS7) */
12332 
12333 #if defined(HAVE_SS7)
12334 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12335 {
12336  if ((linkset < 0) || (linkset >= NUM_SPANS))
12337  return NULL;
12338  else
12339  return &linksets[linkset - 1];
12340 }
12341 #endif /* defined(HAVE_SS7) */
12342 
12343 #ifdef HAVE_OPENR2
12344 static void dahdi_r2_destroy_links(void)
12345 {
12346  struct r2link_entry *cur;
12347 
12348  /* Queue everything for removal */
12349  AST_LIST_LOCK(&r2links);
12350  AST_LIST_TRAVERSE_SAFE_BEGIN(&r2links, cur, list) {
12351  ast_debug(3, "MFC/R2 link #%d queued for destruction\n", cur->mfcr2.index);
12352  AST_LIST_MOVE_CURRENT(&nodev_r2links, list);
12353  }
12355  AST_LIST_UNLOCK(&r2links);
12356  /* Now destroy properly */
12357  dahdi_r2_destroy_nodev();
12358 }
12359 
12360 /* This is an artificial convenient capacity, to keep at most a full E1 of channels in a single thread */
12361 #define R2_LINK_CAPACITY 30
12362 static struct r2link_entry *dahdi_r2_get_link(const struct dahdi_chan_conf *conf)
12363 {
12364  struct r2link_entry *cur = NULL;
12365  /* Only create a new R2 link if
12366  1. This is the first link requested
12367  2. Configuration changed
12368  3. We got more channels than supported per link */
12369  AST_LIST_LOCK(&r2links);
12370  if (! AST_LIST_EMPTY(&r2links)) {
12371  cur = AST_LIST_LAST(&r2links);
12372  if (memcmp(&conf->mfcr2, &cur->mfcr2.conf, sizeof(conf->mfcr2))) {
12373  ast_debug(3, "Need new R2 link because of: Configuration change\n");
12374  cur = NULL;
12375  } else if (cur->mfcr2.numchans == R2_LINK_CAPACITY) {
12376  ast_debug(3, "Need new R2 link because of: Capacity (%d)\n", R2_LINK_CAPACITY);
12377  cur = NULL;
12378  }
12379  }
12380  if (!cur) {
12381  struct r2link_entry *tmp = NULL;
12382  int new_idx = r2links_count + 1;
12383  int i;
12384  for (i = 1; i <= r2links_count; i++) {
12385  int i_unused = 1;
12386  AST_LIST_TRAVERSE(&r2links, tmp, list) {
12387  if (i == tmp->mfcr2.index) {
12388  i_unused = 0;
12389  break;
12390  }
12391  }
12392  if (i_unused) {
12393  new_idx = i;
12394  break;
12395  }
12396  }
12397  cur = ast_calloc(1, sizeof(*cur));
12398  if (!cur) {
12399  ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12400  return NULL;
12401  }
12402  cur->mfcr2.index = new_idx;
12403  cur->mfcr2.r2master = AST_PTHREADT_NULL;
12404  r2links_count++;
12405  ast_debug(3, "Created new R2 link #%d (now have %d)\n", new_idx, r2links_count);
12406  AST_LIST_INSERT_TAIL(&r2links, cur, list);
12407  }
12408  AST_LIST_UNLOCK(&r2links);
12409  return cur;
12410 }
12411 
12412 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12413 {
12414  char tmplogdir[] = "/tmp";
12415  char logdir[OR2_MAX_PATH];
12416  int threshold = 0;
12417  int snres = 0;
12418  r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12419  &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12420  conf->mfcr2.max_dnis);
12421  if (!r2_link->protocol_context) {
12422  return -1;
12423  }
12424  openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12425  openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12426 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12427  openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12428 #endif
12429  openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12430  openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12431  openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12432  openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12433  openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12434 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12435  openr2_context_set_dtmf_dialing(r2_link->protocol_context, conf->mfcr2.dtmf_dialing, conf->mfcr2.dtmf_time_on, conf->mfcr2.dtmf_time_off);
12436  openr2_context_set_dtmf_detection(r2_link->protocol_context, conf->mfcr2.dtmf_detection);
12437 #endif
12438 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
12439  openr2_context_set_dtmf_detection_end_timeout(r2_link->protocol_context, conf->mfcr2.dtmf_end_timeout);
12440 #endif
12441  if (ast_strlen_zero(conf->mfcr2.logdir)) {
12442  if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12443  ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12444  }
12445  } else {
12446  snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12447  if (snres >= sizeof(logdir)) {
12448  ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12449  if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12450  ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12451  }
12452  } else {
12453  if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12454  ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12455  }
12456  }
12457  }
12458  if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12459  if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12460  ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12461  }
12462  }
12463  /* Save the configuration used to setup this link */
12464  memcpy(&r2_link->conf, &conf->mfcr2, sizeof(r2_link->conf));
12465  return 0;
12466 }
12467 #endif
12468 
12469 /* converts a DAHDI sigtype to signalling as can be configured from
12470  * chan_dahdi.conf.
12471  * While both have basically the same values, this will later be the
12472  * place to add filters and sanity checks
12473  */
12474 static int sigtype_to_signalling(int sigtype)
12475 {
12476  return sigtype;
12477 }
12478 
12479 /*!
12480  * \internal
12481  * \brief Initialize/create a channel interface.
12482  *
12483  * \param channel Channel interface number to initialize/create.
12484  * \param conf Configuration parameters to initialize interface with.
12485  * \param reloading What we are doing now:
12486  * 0 - initial module load,
12487  * 1 - module reload,
12488  * 2 - module restart
12489  *
12490  * \retval Interface-pointer initialized/created
12491  * \retval NULL if error
12492  */
12493 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12494 {
12495  /* Make a dahdi_pvt structure for this interface */
12496  struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12497  char fn[80];
12498  struct dahdi_bufferinfo bi;
12499 
12500  int res;
12501 #if defined(HAVE_PRI)
12502  int span = 0;
12503 #endif /* defined(HAVE_PRI) */
12504  int here = 0;/*!< TRUE if the channel interface already exists. */
12505  int x;
12506  struct analog_pvt *analog_p = NULL;
12507  struct dahdi_params p;
12508 #if defined(HAVE_PRI)
12509  struct dahdi_spaninfo si;
12510  struct sig_pri_chan *pri_chan = NULL;
12511 #endif /* defined(HAVE_PRI) */
12512 #if defined(HAVE_SS7)
12513  struct sig_ss7_chan *ss7_chan = NULL;
12514 #endif /* defined(HAVE_SS7) */
12515 
12516  /* Search channel interface list to see if it already exists. */
12517  for (tmp = iflist; tmp; tmp = tmp->next) {
12518  if (!tmp->destroy) {
12519  if (tmp->channel == channel) {
12520  /* The channel interface already exists. */
12521  here = 1;
12522  break;
12523  }
12524  if (tmp->channel > channel) {
12525  /* No way it can be in the sorted list. */
12526  tmp = NULL;
12527  break;
12528  }
12529  }
12530  }
12531 
12532  if (!here && reloading != 1) {
12533  tmp = ast_calloc(1, sizeof(*tmp));
12534  if (!tmp) {
12535  return NULL;
12536  }
12537  tmp->cc_params = ast_cc_config_params_init();
12538  if (!tmp->cc_params) {
12539  ast_free(tmp);
12540  return NULL;
12541  }
12542  ast_mutex_init(&tmp->lock);
12543  ifcount++;
12544  for (x = 0; x < 3; x++)
12545  tmp->subs[x].dfd = -1;
12546  tmp->channel = channel;
12547  tmp->priindication_oob = conf->chan.priindication_oob;
12548  }
12549 
12550  if (tmp) {
12551  int chan_sig = conf->chan.sig;
12552 
12553  /* If there are variables in tmp before it is updated to match the new config, clear them */
12554  if (reloading && tmp->vars) {
12556  tmp->vars = NULL;
12557  }
12558 
12559  if (!here) {
12560  /* Can only get here if this is a new channel interface being created. */
12561  if ((channel != CHAN_PSEUDO)) {
12562  int count = 0;
12563 
12564  snprintf(fn, sizeof(fn), "%d", channel);
12565  /* Open non-blocking */
12566  tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12567  /* Retry open on restarts, but don't keep retrying if the channel doesn't exist (e.g. not configured) */
12568  while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000 && errno != ENXIO) { /* the kernel may not call dahdi_release fast enough for the open flagbit to be cleared in time */
12569  usleep(1);
12570  tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12571  count++;
12572  }
12573  /* Allocate a DAHDI structure */
12574  if (tmp->subs[SUB_REAL].dfd < 0) {
12575  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);
12576  destroy_dahdi_pvt(tmp);
12577  return NULL;
12578  }
12579  memset(&p, 0, sizeof(p));
12580  res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12581  if (res < 0) {
12582  ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12583  destroy_dahdi_pvt(tmp);
12584  return NULL;
12585  }
12586  if (conf->is_sig_auto)
12587  chan_sig = sigtype_to_signalling(p.sigtype);
12588  if (p.sigtype != (chan_sig & 0x3ffff)) {
12589  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));
12590  destroy_dahdi_pvt(tmp);
12591  return NULL;
12592  }
12593  tmp->law_default = p.curlaw;
12594  tmp->law = p.curlaw;
12595  tmp->span = p.spanno;
12596 #if defined(HAVE_PRI)
12597  span = p.spanno - 1;
12598 #endif /* defined(HAVE_PRI) */
12599  } else {
12600  chan_sig = 0;
12601  }
12602  tmp->sig = chan_sig;
12603  tmp->outsigmod = conf->chan.outsigmod;
12604 
12605  if (dahdi_analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12606  analog_p = analog_new(dahdisig_to_analogsig(chan_sig), tmp);
12607  if (!analog_p) {
12608  destroy_dahdi_pvt(tmp);
12609  return NULL;
12610  }
12611  tmp->sig_pvt = analog_p;
12612  }
12613 #if defined(HAVE_SS7)
12614  if (chan_sig == SIG_SS7) {
12615  struct dahdi_ss7 *ss7;
12616  int clear = 0;
12617 
12618  if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12619  ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12620  destroy_dahdi_pvt(tmp);
12621  return NULL;
12622  }
12623 
12624  ss7 = ss7_resolve_linkset(cur_linkset);
12625  if (!ss7) {
12626  ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12627  destroy_dahdi_pvt(tmp);
12628  return NULL;
12629  }
12630  ss7->ss7.span = cur_linkset;
12631  if (cur_cicbeginswith < 0) {
12632  ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12633  destroy_dahdi_pvt(tmp);
12634  return NULL;
12635  }
12636  ss7_chan = sig_ss7_chan_new(tmp, &ss7->ss7);
12637  if (!ss7_chan) {
12638  destroy_dahdi_pvt(tmp);
12639  return NULL;
12640  }
12641  tmp->sig_pvt = ss7_chan;
12642  tmp->ss7 = &ss7->ss7;
12643 
12644  ss7_chan->channel = tmp->channel;
12645  ss7_chan->cic = cur_cicbeginswith++;
12646 
12647  /* DB: Add CIC's DPC information */
12648  ss7_chan->dpc = cur_defaultdpc;
12649 
12650  ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12651 
12652  ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12653  ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12654  ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12655  ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12656  ast_copy_string(ss7->ss7.networkroutedprefix, conf->ss7.ss7.networkroutedprefix, sizeof(ss7->ss7.networkroutedprefix));
12657 
12658  ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12659  ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12660  }
12661 #endif /* defined(HAVE_SS7) */
12662 #ifdef HAVE_OPENR2
12663  if (chan_sig == SIG_MFCR2) {
12664  struct dahdi_mfcr2 *r2_link;
12665  struct r2link_entry *r2_le = dahdi_r2_get_link(conf);
12666  r2_link = &r2_le->mfcr2;
12667  if (!r2_link) {
12668  ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12669  destroy_dahdi_pvt(tmp);
12670  return NULL;
12671  }
12672  if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12673  ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12674  destroy_dahdi_pvt(tmp);
12675  return NULL;
12676  }
12677  if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12678  ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12679  destroy_dahdi_pvt(tmp);
12680  return NULL;
12681  }
12682  r2_link->pvts[r2_link->numchans++] = tmp;
12683  tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12684  tmp->subs[SUB_REAL].dfd,
12685  NULL, NULL);
12686  if (!tmp->r2chan) {
12687  openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12688  ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12689  destroy_dahdi_pvt(tmp);
12690  return NULL;
12691  }
12692  r2_link->live_chans++;
12693  tmp->mfcr2 = r2_link;
12694  if (conf->mfcr2.call_files) {
12695  openr2_chan_enable_call_files(tmp->r2chan);
12696  }
12697  openr2_chan_set_client_data(tmp->r2chan, tmp);
12698  /* cast seems to be needed to get rid of the annoying warning regarding format attribute */
12699  openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12700  openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12701  tmp->mfcr2_category = conf->mfcr2.category;
12702  tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12703  tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12704  tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12705  tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12706  tmp->mfcr2call = 0;
12707  tmp->mfcr2_dnis_index = 0;
12708  tmp->mfcr2_ani_index = 0;
12709  }
12710 #endif
12711 #ifdef HAVE_PRI
12712  if (dahdi_sig_pri_lib_handles(chan_sig)) {
12713  int offset;
12714  int matchesdchan;
12715  int x,y;
12716  int myswitchtype = 0;
12717 
12718  offset = 0;
12719  if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12720  ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12721  destroy_dahdi_pvt(tmp);
12722  return NULL;
12723  }
12724  if (span >= NUM_SPANS) {
12725  ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12726  destroy_dahdi_pvt(tmp);
12727  return NULL;
12728  } else {
12729  si.spanno = 0;
12730  if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12731  ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12732  destroy_dahdi_pvt(tmp);
12733  return NULL;
12734  }
12735  /* Store the logical span first based upon the real span */
12736  tmp->logicalspan = pris[span].prilogicalspan;
12737  pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12738  if (span < 0) {
12739  ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12740  destroy_dahdi_pvt(tmp);
12741  return NULL;
12742  }
12743  myswitchtype = conf->pri.pri.switchtype;
12744  /* Make sure this isn't a d-channel */
12745  matchesdchan=0;
12746  for (x = 0; x < NUM_SPANS; x++) {
12747  for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12748  if (pris[x].dchannels[y] == tmp->channel) {
12749  matchesdchan = 1;
12750  break;
12751  }
12752  }
12753  }
12754  if (!matchesdchan) {
12755  if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12756  ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12757  destroy_dahdi_pvt(tmp);
12758  return NULL;
12759  }
12760  if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12761  ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12762  destroy_dahdi_pvt(tmp);
12763  return NULL;
12764  }
12765  if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12766  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));
12767  destroy_dahdi_pvt(tmp);
12768  return NULL;
12769  }
12770  if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12771  ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12772  destroy_dahdi_pvt(tmp);
12773  return NULL;
12774  }
12775  if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12776  ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12777  destroy_dahdi_pvt(tmp);
12778  return NULL;
12779  }
12780  if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12781  ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12782  destroy_dahdi_pvt(tmp);
12783  return NULL;
12784  }
12785  if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12786  ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12787  destroy_dahdi_pvt(tmp);
12788  return NULL;
12789  }
12790  if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12791  ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12792  pris[span].pri.trunkgroup);
12793  destroy_dahdi_pvt(tmp);
12794  return NULL;
12795  }
12796 
12797  pri_chan = sig_pri_chan_new(tmp, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12798  if (!pri_chan) {
12799  destroy_dahdi_pvt(tmp);
12800  return NULL;
12801  }
12802  tmp->sig_pvt = pri_chan;
12803  tmp->pri = &pris[span].pri;
12804 
12805  tmp->priexclusive = conf->chan.priexclusive;
12806 
12807  if (!tmp->pri->cc_params) {
12808  tmp->pri->cc_params = ast_cc_config_params_init();
12809  if (!tmp->pri->cc_params) {
12810  destroy_dahdi_pvt(tmp);
12811  return NULL;
12812  }
12813  }
12815  conf->chan.cc_params);
12816 
12817  pris[span].pri.sig = chan_sig;
12818  pris[span].pri.nodetype = conf->pri.pri.nodetype;
12819  pris[span].pri.switchtype = myswitchtype;
12820  pris[span].pri.nsf = conf->pri.pri.nsf;
12821  pris[span].pri.dialplan = conf->pri.pri.dialplan;
12822  pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12823  pris[span].pri.cpndialplan = conf->pri.pri.cpndialplan;
12824  pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12825  pris[span].pri.minunused = conf->pri.pri.minunused;
12826  pris[span].pri.minidle = conf->pri.pri.minidle;
12827  pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12828  pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12829  pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12830 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12831  pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12832 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12833 #ifdef HAVE_PRI_INBANDDISCONNECT
12834  pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12835 #endif
12836 #if defined(HAVE_PRI_CALL_HOLD)
12837  pris[span].pri.hold_disconnect_transfer =
12838  conf->pri.pri.hold_disconnect_transfer;
12839 #endif /* defined(HAVE_PRI_CALL_HOLD) */
12840 #if defined(HAVE_PRI_CCSS)
12841  pris[span].pri.cc_ptmp_recall_mode =
12842  conf->pri.pri.cc_ptmp_recall_mode;
12843  pris[span].pri.cc_qsig_signaling_link_req =
12844  conf->pri.pri.cc_qsig_signaling_link_req;
12845  pris[span].pri.cc_qsig_signaling_link_rsp =
12846  conf->pri.pri.cc_qsig_signaling_link_rsp;
12847 #endif /* defined(HAVE_PRI_CCSS) */
12848 #if defined(HAVE_PRI_CALL_WAITING)
12849  pris[span].pri.max_call_waiting_calls =
12850  conf->pri.pri.max_call_waiting_calls;
12851  pris[span].pri.allow_call_waiting_calls =
12852  conf->pri.pri.allow_call_waiting_calls;
12853 #endif /* defined(HAVE_PRI_CALL_WAITING) */
12854  pris[span].pri.transfer = conf->chan.transfer;
12855  pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12856 #if defined(HAVE_PRI_L2_PERSISTENCE)
12857  pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12858 #endif /* defined(HAVE_PRI_L2_PERSISTENCE) */
12859  pris[span].pri.colp_send = conf->pri.pri.colp_send;
12860 #if defined(HAVE_PRI_AOC_EVENTS)
12861  pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12862  pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12863 #endif /* defined(HAVE_PRI_AOC_EVENTS) */
12864  if (chan_sig == SIG_BRI_PTMP) {
12865  pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12866  } else {
12867  /* Option does not apply to this line type. */
12868  pris[span].pri.layer1_ignored = 0;
12869  }
12870  pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12871  pris[span].pri.inband_on_setup_ack = conf->pri.pri.inband_on_setup_ack;
12872  pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
12873  ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12874  ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12875 #if defined(HAVE_PRI_MWI)
12876  ast_copy_string(pris[span].pri.mwi_mailboxes,
12877  conf->pri.pri.mwi_mailboxes,
12878  sizeof(pris[span].pri.mwi_mailboxes));
12879  ast_copy_string(pris[span].pri.mwi_vm_boxes,
12880  conf->pri.pri.mwi_vm_boxes,
12881  sizeof(pris[span].pri.mwi_vm_boxes));
12882  ast_copy_string(pris[span].pri.mwi_vm_numbers,
12883  conf->pri.pri.mwi_vm_numbers,
12884  sizeof(pris[span].pri.mwi_vm_numbers));
12885 #endif /* defined(HAVE_PRI_MWI) */
12886  ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12887  ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12888  ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12889  ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12890  ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12891  ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12892  ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12893  pris[span].pri.moh_signaling = conf->pri.pri.moh_signaling;
12894  pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12895 #if defined(HAVE_PRI_DISPLAY_TEXT)
12896  pris[span].pri.display_flags_send = conf->pri.pri.display_flags_send;
12897  pris[span].pri.display_flags_receive = conf->pri.pri.display_flags_receive;
12898 #endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
12899 #if defined(HAVE_PRI_MCID)
12900  pris[span].pri.mcid_send = conf->pri.pri.mcid_send;
12901 #endif /* defined(HAVE_PRI_MCID) */
12903 #if defined(HAVE_PRI_DATETIME_SEND)
12904  pris[span].pri.datetime_send = conf->pri.pri.datetime_send;
12905 #endif /* defined(HAVE_PRI_DATETIME_SEND) */
12906 
12907  for (x = 0; x < PRI_MAX_TIMERS; x++) {
12908  pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12909  }
12910 
12911 #if defined(HAVE_PRI_CALL_WAITING)
12912  /* Channel initial config parameters. */
12913  pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12914  pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12915  pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12916  pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12917  pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12918  pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12919  pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12920  pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12921  ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12922  ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12923 #endif /* defined(HAVE_PRI_CALL_WAITING) */
12924  } else {
12925  ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12926  destroy_dahdi_pvt(tmp);
12927  return NULL;
12928  }
12929  }
12930  }
12931 #endif
12932  } else {
12933  /* already exists in interface list */
12934  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));
12935  chan_sig = tmp->sig;
12936  if (tmp->subs[SUB_REAL].dfd > -1) {
12937  memset(&p, 0, sizeof(p));
12938  res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12939  }
12940  }
12941  /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12942  switch (chan_sig) {
12943  case SIG_FXSKS:
12944  case SIG_FXSLS:
12945  case SIG_EM:
12946  case SIG_EM_E1:
12947  case SIG_EMWINK:
12948  case SIG_FEATD:
12949  case SIG_FEATDMF:
12950  case SIG_FEATDMF_TA:
12951  case SIG_FEATB:
12952  case SIG_E911:
12953  case SIG_SF:
12954  case SIG_SFWINK:
12955  case SIG_FGC_CAMA:
12956  case SIG_FGC_CAMAMF:
12957  case SIG_SF_FEATD:
12958  case SIG_SF_FEATDMF:
12959  case SIG_SF_FEATB:
12960  p.starttime = 250;
12961  break;
12962  }
12963 
12964  if (tmp->radio) {
12965  /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12966  p.channo = channel;
12967  p.rxwinktime = 1;
12968  p.rxflashtime = 1;
12969  p.starttime = 1;
12970  p.debouncetime = 5;
12971  } else {
12972  p.channo = channel;
12973  /* Override timing settings based on config file */
12974  if (conf->timing.prewinktime >= 0)
12975  p.prewinktime = conf->timing.prewinktime;
12976  if (conf->timing.preflashtime >= 0)
12977  p.preflashtime = conf->timing.preflashtime;
12978  if (conf->timing.winktime >= 0)
12979  p.winktime = conf->timing.winktime;
12980  if (conf->timing.flashtime >= 0)
12981  p.flashtime = conf->timing.flashtime;
12982  if (conf->timing.starttime >= 0)
12983  p.starttime = conf->timing.starttime;
12984  if (conf->timing.rxwinktime >= 0)
12985  p.rxwinktime = conf->timing.rxwinktime;
12986  if (conf->timing.rxflashtime >= 0)
12987  p.rxflashtime = conf->timing.rxflashtime;
12988  if (conf->timing.debouncetime >= 0)
12989  p.debouncetime = conf->timing.debouncetime;
12990  }
12991 
12992  /* don't set parms on a pseudo-channel */
12993  if (tmp->subs[SUB_REAL].dfd >= 0)
12994  {
12995  res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12996  if (res < 0) {
12997  ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12998  destroy_dahdi_pvt(tmp);
12999  return NULL;
13000  }
13001  }
13002 #if 1
13003  if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
13004  memset(&bi, 0, sizeof(bi));
13005  res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13006  if (!res) {
13007  bi.txbufpolicy = conf->chan.buf_policy;
13008  bi.rxbufpolicy = conf->chan.buf_policy;
13009  bi.numbufs = conf->chan.buf_no;
13010  res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13011  if (res < 0) {
13012  ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
13013  }
13014  } else {
13015  ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
13016  }
13017  tmp->buf_policy = conf->chan.buf_policy;
13018  tmp->buf_no = conf->chan.buf_no;
13019  tmp->usefaxbuffers = conf->chan.usefaxbuffers;
13020  tmp->faxbuf_policy = conf->chan.faxbuf_policy;
13021  tmp->faxbuf_no = conf->chan.faxbuf_no;
13022  /* This is not as gnarly as it may first appear. If the ioctl above failed, we'd be setting
13023  * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
13024  * The reason the ioctl call above failed should to be determined before worrying about the
13025  * faxbuffer-related ioctl calls */
13026  tmp->bufsize = bi.bufsize;
13027  }
13028 #endif
13029  tmp->immediate = conf->chan.immediate;
13030  tmp->immediatering = conf->chan.immediatering;
13031  tmp->transfertobusy = conf->chan.transfertobusy;
13032  tmp->dialmode = conf->chan.dialmode;
13033  if (chan_sig & __DAHDI_SIG_FXS) {
13034  tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
13035  tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
13036  tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
13037  }
13038  tmp->ringt_base = ringt_base;
13039  tmp->firstradio = 0;
13040  if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
13041  tmp->permcallwaiting = conf->chan.callwaiting;
13042  else
13043  tmp->permcallwaiting = 0;
13044  /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
13045  tmp->destroy = 0;
13046  tmp->drings = conf->chan.drings;
13047 
13048  /* 10 is a nice default. */
13049  if (tmp->drings.ringnum[0].range == 0)
13050  tmp->drings.ringnum[0].range = 10;
13051  if (tmp->drings.ringnum[1].range == 0)
13052  tmp->drings.ringnum[1].range = 10;
13053  if (tmp->drings.ringnum[2].range == 0)
13054  tmp->drings.ringnum[2].range = 10;
13055 
13056  tmp->usedistinctiveringdetection = usedistinctiveringdetection;
13057  tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
13058  tmp->threewaycalling = conf->chan.threewaycalling;
13059  tmp->threewaysilenthold = conf->chan.threewaysilenthold;
13060  tmp->calledsubscriberheld = conf->chan.calledsubscriberheld; /* Not used in chan_dahdi.c, just analog pvt, but must exist on the DAHDI pvt anyways */
13061  tmp->adsi = conf->chan.adsi;
13062  tmp->use_smdi = conf->chan.use_smdi;
13063  tmp->permhidecallerid = conf->chan.hidecallerid;
13064  tmp->hidecalleridname = conf->chan.hidecalleridname;
13065  tmp->callreturn = conf->chan.callreturn;
13066  tmp->echocancel = conf->chan.echocancel;
13067  tmp->echotraining = conf->chan.echotraining;
13068  tmp->pulse = conf->chan.pulse;
13069  if (tmp->echocancel.head.tap_length) {
13070  tmp->echocanbridged = conf->chan.echocanbridged;
13071  } else {
13072  if (conf->chan.echocanbridged)
13073  ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
13074  tmp->echocanbridged = 0;
13075  }
13076  tmp->busydetect = conf->chan.busydetect;
13077  tmp->busycount = conf->chan.busycount;
13078  tmp->busy_cadence = conf->chan.busy_cadence;
13079  tmp->callprogress = conf->chan.callprogress;
13080  tmp->waitfordialtone = conf->chan.waitfordialtone;
13081  tmp->dialtone_detect = conf->chan.dialtone_detect;
13082  tmp->faxdetect_timeout = conf->chan.faxdetect_timeout;
13083  tmp->firstdigit_timeout = conf->chan.firstdigit_timeout;
13084  tmp->interdigit_timeout = conf->chan.interdigit_timeout;
13085  tmp->matchdigit_timeout = conf->chan.matchdigit_timeout;
13086  tmp->cancallforward = conf->chan.cancallforward;
13087  tmp->dtmfrelax = conf->chan.dtmfrelax;
13088  tmp->callwaiting = tmp->permcallwaiting;
13089  tmp->hidecallerid = tmp->permhidecallerid;
13090  tmp->channel = channel;
13091  tmp->stripmsd = conf->chan.stripmsd;
13092  tmp->use_callerid = conf->chan.use_callerid;
13093  tmp->cid_signalling = conf->chan.cid_signalling;
13094  tmp->cid_start = conf->chan.cid_start;
13095  tmp->dahditrcallerid = conf->chan.dahditrcallerid;
13096  tmp->restrictcid = conf->chan.restrictcid;
13097  tmp->use_callingpres = conf->chan.use_callingpres;
13098  if (tmp->usedistinctiveringdetection) {
13099  if (!tmp->use_callerid) {
13100  ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
13101  tmp->use_callerid = 1;
13102  }
13103  }
13104 
13105  if (tmp->cid_signalling == CID_SIG_SMDI) {
13106  if (!tmp->use_smdi) {
13107  ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
13108  tmp->use_smdi = 1;
13109  }
13110  }
13111  if (tmp->use_smdi) {
13113  if (!(tmp->smdi_iface)) {
13114  ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
13115  tmp->use_smdi = 0;
13116  }
13117  }
13118 
13119  ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
13120  tmp->amaflags = conf->chan.amaflags;
13121  if (!here) {
13122  tmp->confno = -1;
13123  tmp->propconfno = -1;
13124  }
13125  tmp->canpark = conf->chan.canpark;
13126  tmp->transfer = conf->chan.transfer;
13127  ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
13128  ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
13129  ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
13130  ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
13131  ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
13132  ast_copy_string(tmp->description, conf->chan.description, sizeof(tmp->description));
13133  ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
13134  tmp->cid_ton = 0;
13135  if (dahdi_analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
13136  ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
13137  ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
13138  } else {
13139  tmp->cid_num[0] = '\0';
13140  tmp->cid_name[0] = '\0';
13141  }
13142 #if defined(HAVE_PRI)
13143  if (dahdi_sig_pri_lib_handles(tmp->sig)) {
13144  tmp->cid_tag[0] = '\0';
13145  } else
13146 #endif /* defined(HAVE_PRI) */
13147  {
13148  ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
13149  }
13150  tmp->cid_subaddr[0] = '\0';
13151  ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
13152  if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
13153  /* This module does not handle MWI in an event-based manner. However, it
13154  * subscribes to MWI for each mailbox that is configured so that the core
13155  * knows that we care about it. Then, chan_dahdi will get the MWI from the
13156  * event cache instead of checking the mailbox directly. */
13158  }
13159 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13160  tmp->mwisend_setting = conf->chan.mwisend_setting;
13161  tmp->mwisend_fsk = conf->chan.mwisend_fsk;
13162  tmp->mwisend_rpas = conf->chan.mwisend_rpas;
13163 #endif
13164 
13165  tmp->group = conf->chan.group;
13166  tmp->callgroup = conf->chan.callgroup;
13167  tmp->pickupgroup= conf->chan.pickupgroup;
13168  ast_unref_namedgroups(tmp->named_callgroups);
13169  tmp->named_callgroups = ast_ref_namedgroups(conf->chan.named_callgroups);
13170  ast_unref_namedgroups(tmp->named_pickupgroups);
13171  tmp->named_pickupgroups = ast_ref_namedgroups(conf->chan.named_pickupgroups);
13172  if (conf->chan.vars) {
13173  struct ast_variable *v, *tmpvar;
13174  for (v = conf->chan.vars ; v ; v = v->next) {
13175  if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
13176  if (ast_variable_list_replace(&tmp->vars, tmpvar)) {
13177  tmpvar->next = tmp->vars;
13178  tmp->vars = tmpvar;
13179  }
13180  }
13181  }
13182  }
13183  tmp->hwrxgain_enabled = conf->chan.hwrxgain_enabled;
13184  tmp->hwtxgain_enabled = conf->chan.hwtxgain_enabled;
13185  tmp->hwrxgain = conf->chan.hwrxgain;
13186  tmp->hwtxgain = conf->chan.hwtxgain;
13187  tmp->cid_rxgain = conf->chan.cid_rxgain;
13188  tmp->rxgain = conf->chan.rxgain;
13189  tmp->txgain = conf->chan.txgain;
13190  tmp->txdrc = conf->chan.txdrc;
13191  tmp->rxdrc = conf->chan.rxdrc;
13192  tmp->tonezone = conf->chan.tonezone;
13193  if (tmp->subs[SUB_REAL].dfd > -1) {
13194  if (tmp->hwrxgain_enabled) {
13195  tmp->hwrxgain_enabled = !set_hwgain(tmp->subs[SUB_REAL].dfd, tmp->hwrxgain, 0);
13196  }
13197  if (tmp->hwtxgain_enabled) {
13198  tmp->hwtxgain_enabled = !set_hwgain(tmp->subs[SUB_REAL].dfd, tmp->hwtxgain, 1);
13199  }
13200  set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
13201  if (tmp->dsp)
13203  dahdi_conf_update(tmp);
13204  if (!here) {
13205  switch (chan_sig) {
13206  case SIG_PRI_LIB_HANDLE_CASES:
13207  case SIG_SS7:
13208  case SIG_MFCR2:
13209  break;
13210  default:
13211  /* Hang it up to be sure it's good */
13212  dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13213  break;
13214  }
13215  }
13216  ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13217  if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13218  /* the dchannel is down so put the channel in alarm */
13219  switch (tmp->sig) {
13220 #ifdef HAVE_PRI
13221  case SIG_PRI_LIB_HANDLE_CASES:
13222  sig_pri_set_alarm(tmp->sig_pvt, 1);
13223  break;
13224 #endif
13225 #if defined(HAVE_SS7)
13226  case SIG_SS7:
13227  sig_ss7_set_alarm(tmp->sig_pvt, 1);
13228  break;
13229 #endif /* defined(HAVE_SS7) */
13230  default:
13231  /* The only sig submodule left should be sig_analog. */
13232  analog_p = tmp->sig_pvt;
13233  if (analog_p) {
13234  analog_p->inalarm = 1;
13235  }
13236  tmp->inalarm = 1;
13237  break;
13238  }
13239  handle_alarms(tmp, res);
13240  }
13241  }
13242 
13243  tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13245  tmp->ani_info_digits = conf->chan.ani_info_digits;
13246  tmp->ani_wink_time = conf->chan.ani_wink_time;
13247  tmp->ani_timeout = conf->chan.ani_timeout;
13249  tmp->reoriginate = conf->chan.reoriginate;
13250  tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13251  ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13252 
13253  if (!here) {
13254  tmp->locallyblocked = 0;
13255  tmp->remotelyblocked = 0;
13256  switch (tmp->sig) {
13257 #if defined(HAVE_PRI)
13258  case SIG_PRI_LIB_HANDLE_CASES:
13259  tmp->inservice = 1;/* Inservice until actually implemented. */
13260 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13261  ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13262  if (chan_sig == SIG_PRI) {
13263  char db_chan_name[20];
13264  char db_answer[5];
13265 
13266  /*
13267  * Initialize the active out-of-service status
13268  * and delete any record if the feature is not enabled.
13269  */
13270  snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13271  if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13272  unsigned *why;
13273 
13274  why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13275  if (tmp->pri->enable_service_message_support) {
13276  char state;
13277 
13278  sscanf(db_answer, "%1c:%30u", &state, why);
13279 
13280  /* Ensure that only the implemented bits could be set.*/
13281  *why &= (SRVST_NEAREND | SRVST_FAREND);
13282  }
13283  if (!*why) {
13284  ast_db_del(db_chan_name, SRVST_DBKEY);
13285  }
13286  }
13287  }
13288 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
13289  break;
13290 #endif /* defined(HAVE_PRI) */
13291 #if defined(HAVE_SS7)
13292  case SIG_SS7:
13293  tmp->inservice = 0;
13294  if (tmp->ss7->flags & LINKSET_FLAG_INITIALHWBLO) {
13295  tmp->remotelyblocked |= SS7_BLOCKED_HARDWARE;
13296  }
13297  break;
13298 #endif /* defined(HAVE_SS7) */
13299  default:
13300  /* We default to in service on protocols that don't have a reset */
13301  tmp->inservice = 1;
13302  break;
13303  }
13304  }
13305 
13306  switch (tmp->sig) {
13307 #if defined(HAVE_PRI)
13308  case SIG_PRI_LIB_HANDLE_CASES:
13309  if (pri_chan) {
13310  pri_chan->channel = tmp->channel;
13311  pri_chan->hidecallerid = tmp->hidecallerid;
13312  pri_chan->hidecalleridname = tmp->hidecalleridname;
13313  pri_chan->immediate = tmp->immediate;
13314  pri_chan->inalarm = tmp->inalarm;
13315  pri_chan->priexclusive = tmp->priexclusive;
13316  pri_chan->priindication_oob = tmp->priindication_oob;
13317  pri_chan->use_callerid = tmp->use_callerid;
13318  pri_chan->use_callingpres = tmp->use_callingpres;
13319  ast_copy_string(pri_chan->context, tmp->context,
13320  sizeof(pri_chan->context));
13321  ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13322  sizeof(pri_chan->mohinterpret));
13323  pri_chan->stripmsd = tmp->stripmsd;
13324  }
13325  break;
13326 #endif /* defined(HAVE_PRI) */
13327 #if defined(HAVE_SS7)
13328  case SIG_SS7:
13329  if (ss7_chan) {
13330  ss7_chan->inalarm = tmp->inalarm;
13331  ss7_chan->inservice = tmp->inservice;
13332 
13333  ss7_chan->stripmsd = tmp->stripmsd;
13334  ss7_chan->hidecallerid = tmp->hidecallerid;
13335  ss7_chan->use_callerid = tmp->use_callerid;
13336  ss7_chan->use_callingpres = tmp->use_callingpres;
13337  ss7_chan->immediate = tmp->immediate;
13338  ss7_chan->locallyblocked = tmp->locallyblocked;
13339  ss7_chan->remotelyblocked = tmp->remotelyblocked;
13340  ast_copy_string(ss7_chan->context, tmp->context,
13341  sizeof(ss7_chan->context));
13342  ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13343  sizeof(ss7_chan->mohinterpret));
13344  }
13345  break;
13346 #endif /* defined(HAVE_SS7) */
13347  default:
13348  /* The only sig submodule left should be sig_analog. */
13349  analog_p = tmp->sig_pvt;
13350  if (analog_p) {
13351  analog_p->channel = tmp->channel;
13352  analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13353  analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13354  analog_p->ani_info_digits = conf->chan.ani_info_digits;
13355  analog_p->ani_timeout = conf->chan.ani_timeout;
13356  analog_p->ani_wink_time = conf->chan.ani_wink_time;
13357  analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13358  analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13359  analog_p->calledsubscriberheld = conf->chan.calledsubscriberheld; /* Only actually used in analog pvt, not DAHDI pvt */
13360  analog_p->callreturn = conf->chan.callreturn;
13361  analog_p->cancallforward = conf->chan.cancallforward;
13362  analog_p->canpark = conf->chan.canpark;
13363  analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13364  analog_p->immediate = conf->chan.immediate;
13365  analog_p->immediatering = conf->chan.immediatering;
13366  analog_p->permhidecallerid = conf->chan.hidecallerid; /* hidecallerid is the config setting, not permhidecallerid (~permcallwaiting above) */
13367  /* It's not necessary to set analog_p->hidecallerid here, sig_analog will set hidecallerid=permhidecaller before each call */
13368  analog_p->pulse = conf->chan.pulse;
13369  analog_p->threewaycalling = conf->chan.threewaycalling;
13370  analog_p->transfer = conf->chan.transfer;
13371  analog_p->transfertobusy = conf->chan.transfertobusy;
13372  analog_p->dialmode = conf->chan.dialmode;
13373  analog_p->use_callerid = tmp->use_callerid;
13374  analog_p->usedistinctiveringdetection = tmp->usedistinctiveringdetection;
13375  analog_p->use_smdi = tmp->use_smdi;
13376  analog_p->smdi_iface = tmp->smdi_iface;
13377  analog_p->outsigmod = ANALOG_SIG_NONE;
13378  analog_p->echotraining = conf->chan.echotraining;
13379  analog_p->cid_signalling = conf->chan.cid_signalling;
13380  analog_p->stripmsd = conf->chan.stripmsd;
13381  switch (conf->chan.cid_start) {
13382  case CID_START_POLARITY:
13383  analog_p->cid_start = ANALOG_CID_START_POLARITY;
13384  break;
13385  case CID_START_POLARITY_IN:
13386  analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13387  break;
13388  case CID_START_DTMF_NOALERT:
13389  analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13390  break;
13391  default:
13392  analog_p->cid_start = ANALOG_CID_START_RING;
13393  break;
13394  }
13395  analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13396  analog_p->ringt = conf->chan.ringt;
13397  analog_p->ringt_base = ringt_base;
13398  analog_p->onhooktime = time(NULL);
13399  if (chan_sig & __DAHDI_SIG_FXO) {
13400  memset(&p, 0, sizeof(p));
13401  res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13402  if (!res) {
13403  analog_p->fxsoffhookstate = p.rxisoffhook;
13404  }
13405 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13406  res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13407 #endif
13408  }
13409  analog_p->msgstate = -1;
13410 
13411  ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13412  ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13413  ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13414 
13415  analog_config_complete(analog_p);
13416  }
13417  break;
13418  }
13419 #if defined(HAVE_PRI)
13420  if (tmp->channel == CHAN_PSEUDO) {
13421  /*
13422  * Save off pseudo channel buffer policy values for dynamic creation of
13423  * no B channel interfaces.
13424  */
13425  dahdi_pseudo_parms.buf_no = tmp->buf_no;
13426  dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13427  dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13428  dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13429  }
13430 #endif /* defined(HAVE_PRI) */
13431  }
13432  if (tmp && !here) {
13433  /* Add the new channel interface to the sorted channel interface list. */
13434  dahdi_iflist_insert(tmp);
13435  }
13436  return tmp;
13437 }
13438 
13439 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13440 {
13441 #if defined(HAVE_PRI)
13442  if (0 < span) {
13443  /* The channel must be on the specified PRI span. */
13444  if (!p->pri || p->pri->span != span) {
13445  return 0;
13446  }
13447  if (!groupmatch && channelmatch == -1) {
13448  /* Match any group since it only needs to be on the PRI span. */
13449  *groupmatched = 1;
13450  return 1;
13451  }
13452  }
13453 #endif /* defined(HAVE_PRI) */
13454  /* check group matching */
13455  if (groupmatch) {
13456  if ((p->group & groupmatch) != groupmatch)
13457  /* Doesn't match the specified group, try the next one */
13458  return 0;
13459  *groupmatched = 1;
13460  }
13461  /* Check to see if we have a channel match */
13462  if (channelmatch != -1) {
13463  if (p->channel != channelmatch)
13464  /* Doesn't match the specified channel, try the next one */
13465  return 0;
13466  *channelmatched = 1;
13467  }
13468 
13469  return 1;
13470 }
13471 
13472 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13473 {
13474  struct dahdi_pvt *p = *pvt;
13475 
13476  if (p->inalarm)
13477  return 0;
13478 
13479  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode))
13480  return analog_available(p->sig_pvt);
13481 
13482  switch (p->sig) {
13483 #if defined(HAVE_PRI)
13484  case SIG_PRI_LIB_HANDLE_CASES:
13485  {
13486  struct sig_pri_chan *pvt_chan;
13487  int res;
13488 
13489  pvt_chan = p->sig_pvt;
13490  res = sig_pri_available(&pvt_chan, is_specific_channel);
13491  *pvt = pvt_chan->chan_pvt;
13492  return res;
13493  }
13494 #endif /* defined(HAVE_PRI) */
13495 #if defined(HAVE_SS7)
13496  case SIG_SS7:
13497  return sig_ss7_available(p->sig_pvt);
13498 #endif /* defined(HAVE_SS7) */
13499  default:
13500  break;
13501  }
13502 
13503  if (p->locallyblocked || p->remotelyblocked) {
13504  return 0;
13505  }
13506 
13507  /* If no owner definitely available */
13508  if (!p->owner) {
13509 #ifdef HAVE_OPENR2
13510  /* Trust MFC/R2 */
13511  if (p->mfcr2) {
13512  if (p->mfcr2call) {
13513  return 0;
13514  } else {
13515  return 1;
13516  }
13517  }
13518 #endif
13519  return 1;
13520  }
13521 
13522  return 0;
13523 }
13524 
13525 #if defined(HAVE_PRI)
13526 #if defined(HAVE_PRI_CALL_WAITING)
13527 /*!
13528  * \internal
13529  * \brief Init the private channel configuration using the span controller.
13530  * \since 1.8
13531  *
13532  * \param priv Channel to init the configuration.
13533  * \param pri sig_pri PRI control structure.
13534  *
13535  * \note Assumes the pri->lock is already obtained.
13536  */
13537 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13538 {
13539  struct dahdi_pvt *pvt = priv;
13540 
13541  pvt->stripmsd = pri->ch_cfg.stripmsd;
13542  pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13543  pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13544  pvt->immediate = pri->ch_cfg.immediate;
13545  pvt->priexclusive = pri->ch_cfg.priexclusive;
13546  pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13547  pvt->use_callerid = pri->ch_cfg.use_callerid;
13548  pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13549  ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13550  ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13551 }
13552 #endif /* defined(HAVE_PRI_CALL_WAITING) */
13553 #endif /* defined(HAVE_PRI) */
13554 
13555 #if defined(HAVE_PRI)
13556 /*!
13557  * \internal
13558  * \brief Create a no B channel interface.
13559  * \since 1.8
13560  *
13561  * \param pri sig_pri span controller to add interface.
13562  *
13563  * \note Assumes the pri->lock is already obtained.
13564  *
13565  * \retval array-index into private pointer array on success.
13566  * \retval -1 on error.
13567  */
13568 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13569 {
13570  int pvt_idx;
13571  int res;
13572  unsigned idx;
13573  struct dahdi_pvt *pvt;
13574  struct sig_pri_chan *chan;
13575  struct dahdi_bufferinfo bi;
13576 
13577  static int nobch_channel = CHAN_PSEUDO;
13578 
13579  /* Find spot in the private pointer array for new interface. */
13580  for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13581  if (!pri->pvts[pvt_idx]) {
13582  break;
13583  }
13584  }
13585  if (pri->numchans == pvt_idx) {
13586  if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13587  ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13588  return -1;
13589  }
13590 
13591  /* Add new spot to the private pointer array. */
13592  pri->pvts[pvt_idx] = NULL;
13593  ++pri->numchans;
13594  }
13595 
13596  pvt = ast_calloc(1, sizeof(*pvt));
13597  if (!pvt) {
13598  return -1;
13599  }
13600  pvt->cc_params = ast_cc_config_params_init();
13601  if (!pvt->cc_params) {
13602  ast_free(pvt);
13603  return -1;
13604  }
13605  ast_mutex_init(&pvt->lock);
13606  for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13607  pvt->subs[idx].dfd = -1;
13608  }
13609  pvt->buf_no = dahdi_pseudo_parms.buf_no;
13610  pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13611  pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13612  pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13613 
13614  chan = sig_pri_chan_new(pvt, pri, 0, 0, 0);
13615  if (!chan) {
13616  destroy_dahdi_pvt(pvt);
13617  return -1;
13618  }
13619  chan->no_b_channel = 1;
13620 
13621  /*
13622  * Pseudo channel companding law.
13623  * Needed for outgoing call waiting calls.
13624  * XXX May need to make this determined by switchtype or user option.
13625  */
13626  pvt->law_default = DAHDI_LAW_ALAW;
13627 
13628  pvt->sig = pri->sig;
13629  pvt->outsigmod = -1;
13630  pvt->pri = pri;
13631  pvt->sig_pvt = chan;
13632  pri->pvts[pvt_idx] = chan;
13633 
13634  pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13635  if (pvt->subs[SUB_REAL].dfd < 0) {
13636  ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13637  strerror(errno));
13638  destroy_dahdi_pvt(pvt);
13639  return -1;
13640  }
13641  memset(&bi, 0, sizeof(bi));
13642  res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13643  if (!res) {
13644  pvt->bufsize = bi.bufsize;
13645  bi.txbufpolicy = pvt->buf_policy;
13646  bi.rxbufpolicy = pvt->buf_policy;
13647  bi.numbufs = pvt->buf_no;
13648  res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13649  if (res < 0) {
13650  ast_log(LOG_WARNING,
13651  "Unable to set buffer policy on no B channel interface: %s\n",
13652  strerror(errno));
13653  }
13654  } else
13655  ast_log(LOG_WARNING,
13656  "Unable to check buffer policy on no B channel interface: %s\n",
13657  strerror(errno));
13658 
13659  --nobch_channel;
13660  if (CHAN_PSEUDO < nobch_channel) {
13661  nobch_channel = CHAN_PSEUDO - 1;
13662  }
13663  pvt->channel = nobch_channel;
13664  pvt->span = pri->span;
13665  chan->channel = pvt->channel;
13666 
13667  dahdi_nobch_insert(pri, pvt);
13668 
13669  return pvt_idx;
13670 }
13671 #endif /* defined(HAVE_PRI) */
13672 
13673 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
13674  structures; it makes no attempt to safely copy regular channel private
13675  structures that might contain reference-counted object pointers and other
13676  scary bits
13677 */
13678 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13679 {
13680  struct dahdi_pvt *p;
13681  struct dahdi_bufferinfo bi;
13682  int res;
13683 
13684  p = ast_malloc(sizeof(*p));
13685  if (!p) {
13686  return NULL;
13687  }
13688  *p = *src;
13689 
13690  /* Must deep copy the cc_params. */
13691  p->cc_params = ast_cc_config_params_init();
13692  if (!p->cc_params) {
13693  ast_free(p);
13694  return NULL;
13695  }
13696  ast_cc_copy_config_params(p->cc_params, src->cc_params);
13697 
13699  p->next = NULL;
13700  p->prev = NULL;
13701  ast_mutex_init(&p->lock);
13702  p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13703  if (p->subs[SUB_REAL].dfd < 0) {
13704  ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13705  destroy_dahdi_pvt(p);
13706  return NULL;
13707  }
13708  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13709  if (!res) {
13710  bi.txbufpolicy = src->buf_policy;
13711  bi.rxbufpolicy = src->buf_policy;
13712  bi.numbufs = src->buf_no;
13713  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13714  if (res < 0) {
13715  ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13716  }
13717  } else
13718  ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13719  p->destroy = 1;
13720  dahdi_iflist_insert(p);
13721  return p;
13722 }
13723 
13725  /*! Group matching mask. Zero if not specified. */
13726  ast_group_t groupmatch;
13727  /*! DAHDI channel to match with. -1 if not specified. */
13729  /*! Round robin saved search location index. (Valid if roundrobin TRUE) */
13731  /*! ISDN span where channels can be picked (Zero if not specified) */
13732  int span;
13733  /*! Analog channel distinctive ring cadence index. */
13734  int cadence;
13735  /*! Dialing option. c/r/d if present and valid. */
13736  char opt;
13737  /*! TRUE if to search the channel list backwards. */
13739  /*! TRUE if search is done with round robin sequence. */
13741 };
13742 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13743 {
13744  char *dest;
13745  char *s;
13746  int x;
13747  int res = 0;
13748  struct dahdi_pvt *p;
13749  char *subdir = NULL;
13750  AST_DECLARE_APP_ARGS(args,
13751  AST_APP_ARG(group); /* channel/group token */
13752  //AST_APP_ARG(ext); /* extension token */
13753  //AST_APP_ARG(opts); /* options token */
13754  AST_APP_ARG(other); /* Any remining unused arguments */
13755  );
13756 
13757  /*
13758  * data is ---v
13759  * Dial(DAHDI/pseudo[/extension[/options]])
13760  * Dial(DAHDI/<channel#>[c|r<cadence#>|d][/extension[/options]])
13761  * Dial(DAHDI/<subdir>!<channel#>[c|r<cadence#>|d][/extension[/options]])
13762  * Dial(DAHDI/i<span>[/extension[/options]])
13763  * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadence#>|d][/extension[/options]])
13764  *
13765  * i - ISDN span channel restriction.
13766  * Used by CC to ensure that the CC recall goes out the same span.
13767  * Also to make ISDN channel names dialable when the sequence number
13768  * is stripped off. (Used by DTMF attended transfer feature.)
13769  *
13770  * g - channel group allocation search forward
13771  * G - channel group allocation search backward
13772  * r - channel group allocation round robin search forward
13773  * R - channel group allocation round robin search backward
13774  *
13775  * c - Wait for DTMF digit to confirm answer
13776  * r<cadence#> - Set distinctive ring cadence number
13777  * d - Force bearer capability for ISDN/SS7 call to digital.
13778  */
13779 
13780  if (data) {
13781  dest = ast_strdupa(data);
13782  } else {
13783  ast_log(LOG_WARNING, "Channel requested with no data\n");
13784  return NULL;
13785  }
13786  AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13787  if (!args.argc || ast_strlen_zero(args.group)) {
13788  ast_log(LOG_WARNING, "No channel/group specified\n");
13789  return NULL;
13790  }
13791 
13792  /* Initialize the output parameters */
13793  memset(param, 0, sizeof(*param));
13794  param->channelmatch = -1;
13795 
13796  if (strchr(args.group, '!') != NULL) {
13797  char *prev = args.group;
13798  while ((s = strchr(prev, '!')) != NULL) {
13799  *s++ = '/';
13800  prev = s;
13801  }
13802  *(prev - 1) = '\0';
13803  subdir = args.group;
13804  args.group = prev;
13805  } else if (args.group[0] == 'i') {
13806  /* Extract the ISDN span channel restriction specifier. */
13807  res = sscanf(args.group + 1, "%30d", &x);
13808  if (res < 1) {
13809  ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13810  return NULL;
13811  }
13812  param->span = x;
13813 
13814  /* Remove the ISDN span channel restriction specifier. */
13815  s = strchr(args.group, '-');
13816  if (!s) {
13817  /* Search all groups since we are ISDN span restricted. */
13818  return iflist;
13819  }
13820  args.group = s + 1;
13821  res = 0;
13822  }
13823  if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13824  /* Retrieve the group number */
13825  s = args.group + 1;
13826  res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadence);
13827  if (res < 1) {
13828  ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13829  return NULL;
13830  }
13831  param->groupmatch = ((ast_group_t) 1 << x);
13832 
13833  if (toupper(args.group[0]) == 'G') {
13834  if (args.group[0] == 'G') {
13835  param->backwards = 1;
13836  p = ifend;
13837  } else
13838  p = iflist;
13839  } else {
13840  if (ARRAY_LEN(round_robin) <= x) {
13841  ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13842  x, data);
13843  return NULL;
13844  }
13845  if (args.group[0] == 'R') {
13846  param->backwards = 1;
13847  p = round_robin[x] ? round_robin[x]->prev : ifend;
13848  if (!p)
13849  p = ifend;
13850  } else {
13851  p = round_robin[x] ? round_robin[x]->next : iflist;
13852  if (!p)
13853  p = iflist;
13854  }
13855  param->roundrobin = 1;
13856  param->rr_starting_point = x;
13857  }
13858  } else {
13859  s = args.group;
13860  if (!strcasecmp(s, "pseudo")) {
13861  /* Special case for pseudo */
13862  x = CHAN_PSEUDO;
13863  param->channelmatch = x;
13864  } else {
13865  res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadence);
13866  if (res < 1) {
13867  ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13868  return NULL;
13869  } else {
13870  param->channelmatch = x;
13871  }
13872  }
13873  if (subdir) {
13874  char path[PATH_MAX];
13875  struct stat stbuf;
13876 
13877  snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13878  subdir, param->channelmatch);
13879  if (stat(path, &stbuf) < 0) {
13880  ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13881  path, strerror(errno));
13882  return NULL;
13883  }
13884  if (!S_ISCHR(stbuf.st_mode)) {
13885  ast_log(LOG_ERROR, "%s: Not a character device file\n",
13886  path);
13887  return NULL;
13888  }
13889  param->channelmatch = minor(stbuf.st_rdev);
13890  }
13891 
13892  p = iflist;
13893  }
13894 
13895  if (param->opt == 'r' && res < 3) {
13896  ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13897  param->opt = '\0';
13898  }
13899 
13900  return p;
13901 }
13902 
13903 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap,
13904  const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor,
13905  const char *data, int *cause)
13906 {
13907  int callwait = 0;
13908  struct dahdi_pvt *p;
13909  struct ast_channel *tmp = NULL;
13910  struct dahdi_pvt *exitpvt;
13911  int channelmatched = 0;
13912  int foundowner = 0;
13913  int groupmatched = 0;
13914 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13915  int transcapdigital = 0;
13916 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13917  struct dahdi_starting_point start;
13918  ast_callid callid = 0;
13919  int callid_created = ast_callid_threadstorage_auto(&callid);
13920 
13921  ast_mutex_lock(&iflock);
13922  p = determine_starting_point(data, &start);
13923  if (!p) {
13924  /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13925  ast_mutex_unlock(&iflock);
13926  ast_callid_threadstorage_auto_clean(callid, callid_created);
13927  return NULL;
13928  }
13929 
13930  /* Search for an unowned channel */
13931  exitpvt = p;
13932  while (p && !tmp) {
13933  if (start.roundrobin)
13934  round_robin[start.rr_starting_point] = p;
13935 
13936  if (p->owner) {
13937  foundowner++;
13938  }
13939 
13940  if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13941  && available(&p, channelmatched)) {
13942  ast_debug(1, "Using channel %d\n", p->channel);
13943 
13944  callwait = (p->owner != NULL);
13945 #ifdef HAVE_OPENR2
13946  if (p->mfcr2) {
13947  ast_mutex_lock(&p->lock);
13948  if (p->mfcr2call) {
13949  ast_mutex_unlock(&p->lock);
13950  ast_debug(1, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13951  goto next;
13952  }
13953  p->mfcr2call = 1;
13954  ast_mutex_unlock(&p->lock);
13955  }
13956 #endif
13957  if (p->channel == CHAN_PSEUDO) {
13958  p = duplicate_pseudo(p);
13959  if (!p) {
13960  break;
13961  }
13962  }
13963 
13964  p->distinctivering = 0;
13965  /* Make special notes */
13966  switch (start.opt) {
13967  case '\0':
13968  /* No option present. */
13969  break;
13970  case 'c':
13971  /* Confirm answer */
13972  p->confirmanswer = 1;
13973  break;
13974  case 'r':
13975  /* Distinctive ring */
13976  p->distinctivering = start.cadence;
13977  break;
13978  case 'd':
13979 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13980  /* If this is an ISDN call, make it digital */
13981  transcapdigital = AST_TRANS_CAP_DIGITAL;
13982 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13983  break;
13984  default:
13985  ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, data);
13986  break;
13987  }
13988 
13989  p->outgoing = 1;
13990  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13991  tmp = analog_request(p->sig_pvt, &callwait, requestor);
13992 #ifdef HAVE_PRI
13993  } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13994  /*
13995  * We already have the B channel reserved for this call. We
13996  * just need to make sure that dahdi_hangup() has completed
13997  * cleaning up before continuing.
13998  */
13999  ast_mutex_lock(&p->lock);
14000  ast_mutex_unlock(&p->lock);
14001 
14002  sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
14003  sizeof(p->dnid));
14004  tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, assignedids, requestor, transcapdigital);
14005 #endif
14006 #if defined(HAVE_SS7)
14007  } else if (p->sig == SIG_SS7) {
14008  tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, assignedids, requestor, transcapdigital);
14009 #endif /* defined(HAVE_SS7) */
14010  } else {
14011  tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, assignedids, requestor, callid);
14012  }
14013  if (!tmp) {
14014  p->outgoing = 0;
14015 #if defined(HAVE_PRI)
14016  switch (p->sig) {
14017  case SIG_PRI_LIB_HANDLE_CASES:
14018 #if defined(HAVE_PRI_CALL_WAITING)
14019  if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
14020  ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
14022  }
14023 #endif /* defined(HAVE_PRI_CALL_WAITING) */
14024  /*
14025  * This should be the last thing to clear when we are done with
14026  * the channel.
14027  */
14028  ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
14029  break;
14030  default:
14031  break;
14032  }
14033 #endif /* defined(HAVE_PRI) */
14034  } else {
14035  snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", data);
14036  }
14037  break;
14038  }
14039 #ifdef HAVE_OPENR2
14040 next:
14041 #endif
14042  if (start.backwards) {
14043  p = p->prev;
14044  if (!p)
14045  p = ifend;
14046  } else {
14047  p = p->next;
14048  if (!p)
14049  p = iflist;
14050  }
14051  /* stop when you roll to the one that we started from */
14052  if (p == exitpvt)
14053  break;
14054  }
14055  ast_mutex_unlock(&iflock);
14056  restart_monitor();
14057  if (cause && !tmp) {
14058  if (callwait || (channelmatched && foundowner)) {
14059  *cause = AST_CAUSE_BUSY;
14060  } else if (groupmatched) {
14061  *cause = AST_CAUSE_CONGESTION;
14062  } else {
14063  /*
14064  * We did not match any channel requested.
14065  * Dialplan error requesting non-existant channel?
14066  */
14067  }
14068  }
14069 
14070  ast_callid_threadstorage_auto_clean(callid, callid_created);
14071  return tmp;
14072 }
14073 
14074 /*!
14075  * \internal
14076  * \brief Determine the device state for a given DAHDI device if we can.
14077  * \since 1.8
14078  *
14079  * \param data DAHDI device name after "DAHDI/".
14080  *
14081  * \retval device_state enum ast_device_state value.
14082  * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
14083  */
14084 static int dahdi_devicestate(const char *data)
14085 {
14086 #if defined(HAVE_PRI)
14087  const char *device;
14088  unsigned span;
14089  int res;
14090 
14091  device = data;
14092 
14093  if (*device != 'I') {
14094  /* The request is not for an ISDN span device. */
14095  return AST_DEVICE_UNKNOWN;
14096  }
14097  res = sscanf(device, "I%30u", &span);
14098  if (res != 1 || !span || NUM_SPANS < span) {
14099  /* Bad format for ISDN span device name. */
14100  return AST_DEVICE_UNKNOWN;
14101  }
14102  device = strchr(device, '/');
14103  if (!device) {
14104  /* Bad format for ISDN span device name. */
14105  return AST_DEVICE_UNKNOWN;
14106  }
14107 
14108  /*
14109  * Since there are currently no other span devstate's defined,
14110  * it must be congestion.
14111  */
14112 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14113  ++device;
14114  if (!strcmp(device, "congestion"))
14115 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
14116  {
14117  return pris[span - 1].pri.congestion_devstate;
14118  }
14119 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14120  else if (!strcmp(device, "threshold")) {
14121  return pris[span - 1].pri.threshold_devstate;
14122  }
14123  return AST_DEVICE_UNKNOWN;
14124 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
14125 #else
14126  return AST_DEVICE_UNKNOWN;
14127 #endif /* defined(HAVE_PRI) */
14128 }
14129 
14130 /*!
14131  * \brief Callback made when dial failed to get a channel out of dahdi_request().
14132  * \since 1.8
14133  *
14134  * \param inbound Incoming asterisk channel.
14135  * \param dest Same dial string passed to dahdi_request().
14136  * \param callback Callback into CC core to announce a busy channel available for CC.
14137  *
14138  * \details
14139  * This callback acts like a forked dial with all prongs of the fork busy.
14140  * Essentially, for each channel that could have taken the call, indicate that
14141  * it is busy.
14142  *
14143  * \retval 0 on success.
14144  * \retval -1 on error.
14145  */
14146 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
14147 {
14148  struct dahdi_pvt *p;
14149  struct dahdi_pvt *exitpvt;
14150  struct dahdi_starting_point start;
14151  int groupmatched = 0;
14152  int channelmatched = 0;
14153 
14154  ast_mutex_lock(&iflock);
14155  p = determine_starting_point(dest, &start);
14156  if (!p) {
14157  ast_mutex_unlock(&iflock);
14158  return -1;
14159  }
14160  exitpvt = p;
14161  for (;;) {
14162  if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
14163  /* We found a potential match. call the callback */
14164  struct ast_str *device_name;
14165  char *dash;
14166  const char *monitor_type;
14167  char dialstring[AST_CHANNEL_NAME];
14168  char full_device_name[AST_CHANNEL_NAME];
14169 
14170  switch (ast_get_cc_monitor_policy(p->cc_params)) {
14171  case AST_CC_MONITOR_NEVER:
14172  break;
14173  case AST_CC_MONITOR_NATIVE:
14174  case AST_CC_MONITOR_ALWAYS:
14176 #if defined(HAVE_PRI)
14177  if (dahdi_sig_pri_lib_handles(p->sig)) {
14178  /*
14179  * ISDN is in a trunk busy condition so we need to monitor
14180  * the span congestion device state.
14181  */
14182  snprintf(full_device_name, sizeof(full_device_name),
14183  "DAHDI/I%d/congestion", p->pri->span);
14184  } else
14185 #endif /* defined(HAVE_PRI) */
14186  {
14187 #if defined(HAVE_PRI)
14188  device_name = create_channel_name(p, 1, "");
14189 #else
14190  device_name = create_channel_name(p);
14191 #endif /* defined(HAVE_PRI) */
14192  snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
14193  device_name ? ast_str_buffer(device_name) : "");
14194  ast_free(device_name);
14195  /*
14196  * The portion after the '-' in the channel name is either a random
14197  * number, a sequence number, or a subchannel number. None are
14198  * necessary so strip them off.
14199  */
14200  dash = strrchr(full_device_name, '-');
14201  if (dash) {
14202  *dash = '\0';
14203  }
14204  }
14205  snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
14206 
14207  /*
14208  * Analog can only do generic monitoring.
14209  * ISDN is in a trunk busy condition and any "device" is going
14210  * to be busy until a B channel becomes available. The generic
14211  * monitor can do this task.
14212  */
14213  monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
14214  callback(inbound,
14215 #if defined(HAVE_PRI)
14216  p->pri ? p->pri->cc_params : p->cc_params,
14217 #else
14218  p->cc_params,
14219 #endif /* defined(HAVE_PRI) */
14220  monitor_type, full_device_name, dialstring, NULL);
14221  break;
14222  }
14223  }
14224  p = start.backwards ? p->prev : p->next;
14225  if (!p) {
14226  p = start.backwards ? ifend : iflist;
14227  }
14228  if (p == exitpvt) {
14229  break;
14230  }
14231  }
14232  ast_mutex_unlock(&iflock);
14233  return 0;
14234 }
14235 
14236 #if defined(HAVE_SS7)
14237 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
14238 {
14239  int i;
14240 
14241  if (ss7) {
14242  for (i = 0; i < NUM_SPANS; i++) {
14243  if (linksets[i].ss7.ss7 == ss7) {
14244  ast_verbose_callid(0, "[%d] %s", i + 1, s);
14245  return;
14246  }
14247  }
14248  }
14249  ast_verbose_callid(0, "%s", s);
14250 }
14251 #endif /* defined(HAVE_SS7) */
14252 
14253 #if defined(HAVE_SS7)
14254 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
14255 {
14256  int i;
14257 
14258  if (ss7) {
14259  for (i = 0; i < NUM_SPANS; i++) {
14260  if (linksets[i].ss7.ss7 == ss7) {
14261  ast_log_callid(LOG_ERROR, 0, "[%d] %s", i + 1, s);
14262  return;
14263  }
14264  }
14265  }
14266  ast_log_callid(LOG_ERROR, 0, "%s", s);
14267 }
14268 #endif /* defined(HAVE_SS7) */
14269 
14270 #if defined(HAVE_OPENR2)
14271 static void *mfcr2_monitor(void *data)
14272 {
14273  struct dahdi_mfcr2 *mfcr2 = data;
14274  struct dahdi_pvt *pvt;
14275 
14276  /* we should be using pthread_key_create
14277  and allocate pollers dynamically.
14278  I think do_monitor() could be leaking, since it
14279  could be cancelled at any time and is not
14280  using thread keys, why?, */
14281  struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14282  int res = 0;
14283  int i = 0;
14284  int oldstate = 0;
14285  int quit_loop = 0;
14286  int maxsleep = 20;
14287  int was_idle = 0;
14288  int pollsize = 0;
14289  /* now that we're ready to get calls, unblock our side and
14290  get current line state */
14291  for (i = 0; i < mfcr2->numchans; i++) {
14292  pvt = mfcr2->pvts[i];
14293  if (!pvt) {
14294  continue;
14295  }
14296  openr2_chan_set_idle(pvt->r2chan);
14297  openr2_chan_handle_cas(pvt->r2chan);
14298  }
14299  while (1) {
14300  /* we trust here that the mfcr2 channel list will not ever change once
14301  the module is loaded */
14302  pollsize = 0;
14303  for (i = 0; i < mfcr2->numchans; i++) {
14304  pollers[i].revents = 0;
14305  pollers[i].events = 0;
14306  pvt = mfcr2->pvts[i];
14307  if (!pvt) {
14308  continue;
14309  }
14310  if (pvt->owner) {
14311  continue;
14312  }
14313  if (mfcr2->nodev) {
14314  continue;
14315  }
14316  if (!pvt->r2chan) {
14317  ast_debug(1, "Wow, no r2chan on channel %d\n", pvt->channel);
14318  quit_loop = 1;
14319  break;
14320  }
14321  openr2_chan_enable_read(pvt->r2chan);
14322  pollers[i].events = POLLIN | POLLPRI;
14323  pollers[i].fd = pvt->subs[SUB_REAL].dfd;
14324  pollsize++;
14325  }
14326  if (quit_loop) {
14327  break;
14328  }
14329  if (pollsize == 0) {
14330  if (!was_idle) {
14331  ast_debug(1, "Monitor thread going idle since everybody has an owner\n");
14332  was_idle = 1;
14333  }
14334  poll(NULL, 0, maxsleep);
14335  continue;
14336  }
14337  was_idle = 0;
14338  /* probably poll() is a valid cancel point, lets just be on the safe side
14339  by calling pthread_testcancel */
14340  pthread_testcancel();
14341  res = poll(pollers, mfcr2->numchans, maxsleep);
14342  pthread_testcancel();
14343  if ((res < 0) && (errno != EINTR)) {
14344  ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14345  break;
14346  }
14347  /* do we want to allow to cancel while processing events? */
14348  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14349  for (i = 0; i < mfcr2->numchans; i++) {
14350  pvt = mfcr2->pvts[i];
14351  if (!pvt) {
14352  continue;
14353  }
14354  if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14355  openr2_chan_process_event(pvt->r2chan);
14356  }
14357  }
14358  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14359  }
14360  ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14361  return 0;
14362 }
14363 #endif /* HAVE_OPENR2 */
14364 
14365 #if defined(HAVE_PRI)
14366 static void dahdi_pri_message(struct pri *pri, char *s)
14367 {
14368  int x;
14369  int y;
14370  int dchan = -1;
14371  int span = -1;
14372  int dchancount = 0;
14373 
14374  if (pri) {
14375  for (x = 0; x < NUM_SPANS; x++) {
14376  for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14377  if (pris[x].pri.dchans[y]) {
14378  dchancount++;
14379  }
14380 
14381  if (pris[x].pri.dchans[y] == pri) {
14382  dchan = y;
14383  }
14384  }
14385  if (dchan >= 0) {
14386  span = x;
14387  break;
14388  }
14389  dchancount = 0;
14390  }
14391  if (-1 < span) {
14392  if (1 < dchancount) {
14393  ast_verbose_callid(0, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14394  } else {
14395  ast_verbose_callid(0, "PRI Span: %d %s", span + 1, s);
14396  }
14397  } else {
14398  ast_verbose_callid(0, "PRI Span: ? %s", s);
14399  }
14400  } else {
14401  ast_verbose_callid(0, "PRI Span: ? %s", s);
14402  }
14403 
14404  ast_mutex_lock(&pridebugfdlock);
14405 
14406  if (pridebugfd >= 0) {
14407  if (write(pridebugfd, s, strlen(s)) < 0) {
14408  ast_log_callid(LOG_WARNING, 0, "write() failed: %s\n", strerror(errno));
14409  }
14410  }
14411 
14412  ast_mutex_unlock(&pridebugfdlock);
14413 }
14414 #endif /* defined(HAVE_PRI) */
14415 
14416 #if defined(HAVE_PRI)
14417 static void dahdi_pri_error(struct pri *pri, char *s)
14418 {
14419  int x;
14420  int y;
14421  int dchan = -1;
14422  int span = -1;
14423  int dchancount = 0;
14424 
14425  if (pri) {
14426  for (x = 0; x < NUM_SPANS; x++) {
14427  for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14428  if (pris[x].pri.dchans[y]) {
14429  dchancount++;
14430  }
14431 
14432  if (pris[x].pri.dchans[y] == pri) {
14433  dchan = y;
14434  }
14435  }
14436  if (dchan >= 0) {
14437  span = x;
14438  break;
14439  }
14440  dchancount = 0;
14441  }
14442  if (-1 < span) {
14443  if (1 < dchancount) {
14444  ast_log_callid(LOG_ERROR, 0, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14445  } else {
14446  ast_log_callid(LOG_ERROR, 0, "PRI Span: %d %s", span + 1, s);
14447  }
14448  } else {
14449  ast_log_callid(LOG_ERROR, 0, "PRI Span: ? %s", s);
14450  }
14451  } else {
14452  ast_log_callid(LOG_ERROR, 0, "PRI Span: ? %s", s);
14453  }
14454 
14455  ast_mutex_lock(&pridebugfdlock);
14456 
14457  if (pridebugfd >= 0) {
14458  if (write(pridebugfd, s, strlen(s)) < 0) {
14459  ast_log_callid(LOG_WARNING, 0, "write() failed: %s\n", strerror(errno));
14460  }
14461  }
14462 
14463  ast_mutex_unlock(&pridebugfdlock);
14464 }
14465 #endif /* defined(HAVE_PRI) */
14466 
14467 #if defined(HAVE_PRI)
14468 static int prepare_pri(struct dahdi_pri *pri)
14469 {
14470  int i, res, x;
14471  struct dahdi_params p;
14472  struct dahdi_bufferinfo bi;
14473  struct dahdi_spaninfo si;
14474 
14475  for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14476  if (!pri->dchannels[i])
14477  break;
14478  if (pri->pri.fds[i] >= 0) {
14479  /* A partial range addition. Not a complete setup. */
14480  break;
14481  }
14482  pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14483  if ((pri->pri.fds[i] < 0)) {
14484  ast_log(LOG_ERROR, "Unable to open D-channel (fd=%d) (%s)\n",
14485  pri->pri.fds[i], strerror(errno));
14486  return -1;
14487  }
14488  x = pri->dchannels[i];
14489  res = ioctl(pri->pri.fds[i], DAHDI_SPECIFY, &x);
14490  if (res) {
14491  dahdi_close_pri_fd(pri, i);
14492  ast_log(LOG_ERROR, "Unable to SPECIFY channel %d (%s)\n", x, strerror(errno));
14493  return -1;
14494  }
14495  memset(&p, 0, sizeof(p));
14496  res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14497  if (res) {
14498  dahdi_close_pri_fd(pri, i);
14499  ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14500  return -1;
14501  }
14502  if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14503  dahdi_close_pri_fd(pri, i);
14504  ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14505  return -1;
14506  }
14507  memset(&si, 0, sizeof(si));
14508  res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14509  if (res) {
14510  dahdi_close_pri_fd(pri, i);
14511  ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14512  }
14513  if (!si.alarms) {
14514  pri_event_noalarm(&pri->pri, i, 1);
14515  } else {
14516  pri_event_alarm(&pri->pri, i, 1);
14517  }
14518  memset(&bi, 0, sizeof(bi));
14519  bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14520  bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14521  bi.numbufs = 32;
14522  bi.bufsize = 1024;
14523  if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14524  ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14525  dahdi_close_pri_fd(pri, i);
14526  return -1;
14527  }
14528  pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14529  }
14530  return 0;
14531 }
14532 #endif /* defined(HAVE_PRI) */
14533 
14534 #if defined(HAVE_PRI)
14535 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14536 {
14537  int which, span;
14538  char *ret = NULL;
14539 
14540  if (pos != rpos)
14541  return ret;
14542 
14543  for (which = span = 0; span < NUM_SPANS; span++) {
14544  if (pris[span].pri.pri && ++which > state) {
14545  if (ast_asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
14546  ret = NULL;
14547  }
14548  break;
14549  }
14550  }
14551  return ret;
14552 }
14553 #endif /* defined(HAVE_PRI) */
14554 
14555 #if defined(HAVE_PRI)
14556 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14557 {
14558  return complete_span_helper(line,word,pos,state,3);
14559 }
14560 #endif /* defined(HAVE_PRI) */
14561 
14562 #if defined(HAVE_PRI)
14563 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14564 {
14565  int myfd;
14566  switch (cmd) {
14567  case CLI_INIT:
14568  e->command = "pri set debug file";
14569  e->usage = "Usage: pri set debug file [output-file]\n"
14570  " Sends PRI debug output to the specified output file\n";
14571  return NULL;
14572  case CLI_GENERATE:
14573  return NULL;
14574  }
14575  if (a->argc < 5)
14576  return CLI_SHOWUSAGE;
14577 
14578  if (ast_strlen_zero(a->argv[4]))
14579  return CLI_SHOWUSAGE;
14580 
14581  myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14582  if (myfd < 0) {
14583  ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14584  return CLI_SUCCESS;
14585  }
14586 
14587  ast_mutex_lock(&pridebugfdlock);
14588 
14589  if (pridebugfd >= 0)
14590  close(pridebugfd);
14591 
14592  pridebugfd = myfd;
14593  ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14594  ast_mutex_unlock(&pridebugfdlock);
14595  ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14596  return CLI_SUCCESS;
14597 }
14598 #endif /* defined(HAVE_PRI) */
14599 
14600 #if defined(HAVE_PRI)
14601 static int action_pri_debug_file_set(struct mansession *s, const struct message *m)
14602 {
14603  const char *output_file = astman_get_header(m, "File");
14604  int myfd;
14605 
14606  if (ast_strlen_zero(output_file)) {
14607  astman_send_error(s, m, "Action must define a 'File'");
14608  }
14609 
14610  myfd = open(output_file, O_CREAT|O_WRONLY, AST_FILE_MODE);
14611  if (myfd < 0) {
14612  astman_send_error(s, m, "Unable to open requested file for writing");
14613  return 0;
14614  }
14615 
14616  ast_mutex_lock(&pridebugfdlock);
14617 
14618  if (pridebugfd >= 0) {
14619  close(pridebugfd);
14620  }
14621 
14622  pridebugfd = myfd;
14623  ast_copy_string(pridebugfilename, output_file, sizeof(pridebugfilename));
14624  ast_mutex_unlock(&pridebugfdlock);
14625  astman_send_ack(s, m, "PRI debug output will now be sent to requested file.");
14626 
14627  return 0;
14628 }
14629 #endif /* defined(HAVE_PRI) */
14630 
14631 #if defined(HAVE_PRI)
14632 static int action_pri_debug_file_unset(struct mansession *s, const struct message *m)
14633 {
14634  ast_mutex_lock(&pridebugfdlock);
14635 
14636  if (pridebugfd >= 0) {
14637  close(pridebugfd);
14638  }
14639 
14640  pridebugfd = -1;
14641 
14642  ast_mutex_unlock(&pridebugfdlock);
14643 
14644  astman_send_ack(s, m, "PRI Debug output to file disabled");
14645  return 0;
14646 }
14647 #endif /* defined(HAVE_PRI) */
14648 
14649 #if defined(HAVE_PRI)
14650 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14651 {
14652  int span;
14653  int x;
14654  int debugmask = 0;
14655  int level = 0;
14656  switch (cmd) {
14657  case CLI_INIT:
14658  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";
14659  e->usage =
14660  "Usage: pri set debug {<level>|on|off|hex|intense} span <span>\n"
14661  " Enables debugging on a given PRI span\n"
14662  " Level is a bitmap of the following values:\n"
14663  " 1 General debugging incl. state changes\n"
14664  " 2 Decoded Q.931 messages\n"
14665  " 4 Decoded Q.921 messages\n"
14666  " 8 Raw hex dumps of Q.921 frames\n"
14667  " on - equivalent to 3\n"
14668  " hex - equivalent to 8\n"
14669  " intense - equivalent to 15\n";
14670  return NULL;
14671  case CLI_GENERATE:
14672  return complete_span_4(a->line, a->word, a->pos, a->n);
14673  }
14674  if (a->argc < 6) {
14675  return CLI_SHOWUSAGE;
14676  }
14677 
14678  if (!strcasecmp(a->argv[3], "on")) {
14679  level = 3;
14680  } else if (!strcasecmp(a->argv[3], "off")) {
14681  level = 0;
14682  } else if (!strcasecmp(a->argv[3], "intense")) {
14683  level = 15;
14684  } else if (!strcasecmp(a->argv[3], "hex")) {
14685  level = 8;
14686  } else {
14687  level = atoi(a->argv[3]);
14688  }
14689  span = atoi(a->argv[5]);
14690  if ((span < 1) || (span > NUM_SPANS)) {
14691  ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14692  return CLI_SUCCESS;
14693  }
14694  if (!pris[span-1].pri.pri) {
14695  ast_cli(a->fd, "No PRI running on span %d\n", span);
14696  return CLI_SUCCESS;
14697  }
14698 
14699  if (level & 1) debugmask |= SIG_PRI_DEBUG_NORMAL;
14700  if (level & 2) debugmask |= PRI_DEBUG_Q931_DUMP;
14701  if (level & 4) debugmask |= PRI_DEBUG_Q921_DUMP;
14702  if (level & 8) debugmask |= PRI_DEBUG_Q921_RAW;
14703 
14704  /* Set debug level in libpri */
14705  for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14706  if (pris[span - 1].pri.dchans[x]) {
14707  pri_set_debug(pris[span - 1].pri.dchans[x], debugmask);
14708  }
14709  }
14710  if (level == 0) {
14711  /* Close the debugging file if it's set */
14712  ast_mutex_lock(&pridebugfdlock);
14713  if (0 <= pridebugfd) {
14714  close(pridebugfd);
14715  pridebugfd = -1;
14716  ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14717  pridebugfilename);
14718  }
14719  ast_mutex_unlock(&pridebugfdlock);
14720  }
14721  pris[span - 1].pri.debug = (level) ? 1 : 0;
14722  ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14723  return CLI_SUCCESS;
14724 }
14725 #endif /* defined(HAVE_PRI) */
14726 
14727 #if defined(HAVE_PRI)
14728 static int action_pri_debug_set(struct mansession *s, const struct message *m)
14729 {
14730  const char *level = astman_get_header(m, "Level");
14731  const char *span = astman_get_header(m, "Span");
14732  int level_val;
14733  int span_val;
14734  int x;
14735  int debugmask = 0;
14736 
14737  if (ast_strlen_zero(level)) {
14738  astman_send_error(s, m, "'Level' was not specified");
14739  return 0;
14740  }
14741 
14742  if (ast_strlen_zero(span)) {
14743  astman_send_error(s, m, "'Span' was not specified");
14744  return 0;
14745  }
14746 
14747  if (!strcasecmp(level, "on")) {
14748  level_val = 3;
14749  } else if (!strcasecmp(level, "off")) {
14750  level_val = 0;
14751  } else if (!strcasecmp(level, "intense")) {
14752  level_val = 15;
14753  } else if (!strcasecmp(level, "hex")) {
14754  level_val = 8;
14755  } else {
14756  if (sscanf(level, "%30d", &level_val) != 1) {
14757  astman_send_error(s, m, "Invalid value for 'Level'");
14758  return 0;
14759  }
14760  }
14761 
14762  if (sscanf(span, "%30d", &span_val) != 1) {
14763  astman_send_error(s, m, "Invalid value for 'Span'");
14764  }
14765 
14766  if ((span_val < 1) || (span_val > NUM_SPANS)) {
14767  const char *id = astman_get_header(m, "ActionID");
14768  char id_text[256] = "";
14769 
14770  if (!ast_strlen_zero(id)) {
14771  snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
14772  }
14773 
14774  astman_append(s, "Response: Error\r\n"
14775  "%s" /* id_text */
14776  "Message: Invalid span '%s' - Should be a number from 1 to %d\r\n"
14777  "\r\n",
14778  id_text,
14779  span, NUM_SPANS);
14780 
14781  return 0;
14782  }
14783 
14784  if (!pris[span_val-1].pri.pri) {
14785  astman_send_error(s, m, "No PRI running on requested span");
14786  return 0;
14787  }
14788 
14789  if (level_val & 1) {
14790  debugmask |= SIG_PRI_DEBUG_NORMAL;
14791  }
14792  if (level_val & 2) {
14793  debugmask |= PRI_DEBUG_Q931_DUMP;
14794  }
14795  if (level_val & 4) {
14796  debugmask |= PRI_DEBUG_Q921_DUMP;
14797  }
14798  if (level_val & 8) {
14799  debugmask |= PRI_DEBUG_Q921_RAW;
14800  }
14801 
14802  /* Set debug level in libpri */
14803  for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14804  if (pris[span_val - 1].pri.dchans[x]) {
14805  pri_set_debug(pris[span_val - 1].pri.dchans[x], debugmask);
14806  }
14807  }
14808 
14809  pris[span_val - 1].pri.debug = (level_val) ? 1 : 0;
14810  astman_send_ack(s, m, "Debug level set for requested span");
14811 
14812  return 0;
14813 }
14814 #endif /* defined(HAVE_PRI) */
14815 
14816 #if defined(HAVE_PRI)
14817 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14818 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14819 {
14820  unsigned *why;
14821  int channel;
14822  int trunkgroup;
14823  int x, y, fd = a->fd;
14824  int interfaceid = 0;
14825  char db_chan_name[20], db_answer[15];
14826  struct dahdi_pvt *tmp;
14827  struct dahdi_pri *pri;
14828 
14829  if (a->argc < 5 || a->argc > 6)
14830  return CLI_SHOWUSAGE;
14831  if (strchr(a->argv[4], ':')) {
14832  if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14833  return CLI_SHOWUSAGE;
14834  if ((trunkgroup < 1) || (channel < 1))
14835  return CLI_SHOWUSAGE;
14836  pri = NULL;
14837  for (x=0;x<NUM_SPANS;x++) {
14838  if (pris[x].pri.trunkgroup == trunkgroup) {
14839  pri = pris + x;
14840  break;
14841  }
14842  }
14843  if (!pri) {
14844  ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14845  return CLI_FAILURE;
14846  }
14847  } else
14848  channel = atoi(a->argv[4]);
14849 
14850  if (a->argc == 6)
14851  interfaceid = atoi(a->argv[5]);
14852 
14853  /* either servicing a D-Channel */
14854  for (x = 0; x < NUM_SPANS; x++) {
14855  for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14856  if (pris[x].dchannels[y] == channel) {
14857  pri = pris + x;
14858  if (pri->pri.enable_service_message_support) {
14859  ast_mutex_lock(&pri->pri.lock);
14860  pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14861  ast_mutex_unlock(&pri->pri.lock);
14862  } else {
14863  ast_cli(fd,
14864  "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14865  "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14866  }
14867  return CLI_SUCCESS;
14868  }
14869  }
14870  }
14871 
14872  /* or servicing a B-Channel */
14873  ast_mutex_lock(&iflock);
14874  for (tmp = iflist; tmp; tmp = tmp->next) {
14875  if (tmp->pri && tmp->channel == channel) {
14876  ast_mutex_unlock(&iflock);
14877  ast_mutex_lock(&tmp->pri->lock);
14878  if (!tmp->pri->enable_service_message_support) {
14879  ast_mutex_unlock(&tmp->pri->lock);
14880  ast_cli(fd,
14881  "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14882  "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14883  return CLI_SUCCESS;
14884  }
14885  snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14886  why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14887  switch(changestatus) {
14888  case 0: /* enable */
14889  /* Near end wants to be in service now. */
14890  ast_db_del(db_chan_name, SRVST_DBKEY);
14891  *why &= ~SRVST_NEAREND;
14892  if (*why) {
14893  snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14894  ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14895  } else {
14896  dahdi_pri_update_span_devstate(tmp->pri);
14897  }
14898  break;
14899  /* case 1: -- loop */
14900  case 2: /* disable */
14901  /* Near end wants to be out-of-service now. */
14902  ast_db_del(db_chan_name, SRVST_DBKEY);
14903  *why |= SRVST_NEAREND;
14904  snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14905  ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14906  dahdi_pri_update_span_devstate(tmp->pri);
14907  break;
14908  /* case 3: -- continuity */
14909  /* case 4: -- shutdown */
14910  default:
14911  ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14912  break;
14913  }
14914  pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14915  ast_mutex_unlock(&tmp->pri->lock);
14916  return CLI_SUCCESS;
14917  }
14918  }
14919  ast_mutex_unlock(&iflock);
14920 
14921  ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14922  return CLI_FAILURE;
14923 }
14924 
14925 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14926 {
14927  switch (cmd) {
14928  case CLI_INIT:
14929  e->command = "pri service enable channel";
14930  e->usage =
14931  "Usage: pri service enable channel <channel> [<interface id>]\n"
14932  " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14933  " to restore a channel to service, with optional interface id\n"
14934  " as agreed upon with remote switch operator\n";
14935  return NULL;
14936  case CLI_GENERATE:
14937  return NULL;
14938  }
14939  return handle_pri_service_generic(e, cmd, a, 0);
14940 }
14941 
14942 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14943 {
14944  switch (cmd) {
14945  case CLI_INIT:
14946  e->command = "pri service disable channel";
14947  e->usage =
14948  "Usage: pri service disable channel <chan num> [<interface id>]\n"
14949  " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14950  " to remove a channel from service, with optional interface id\n"
14951  " as agreed upon with remote switch operator\n";
14952  return NULL;
14953  case CLI_GENERATE:
14954  return NULL;
14955  }
14956  return handle_pri_service_generic(e, cmd, a, 2);
14957 }
14958 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14959 #endif /* defined(HAVE_PRI) */
14960 
14961 #if defined(HAVE_PRI)
14962 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14963 {
14964  int span;
14965 
14966  switch (cmd) {
14967  case CLI_INIT:
14968  e->command = "pri show channels";
14969  e->usage =
14970  "Usage: pri show channels\n"
14971  " Displays PRI channel information such as the current mapping\n"
14972  " of DAHDI B channels to Asterisk channel names and which calls\n"
14973  " are on hold or call-waiting. Calls on hold or call-waiting\n"
14974  " are not associated with any B channel.\n";
14975  return NULL;
14976  case CLI_GENERATE:
14977  return NULL;
14978  }
14979 
14980  if (a->argc != 3)
14981  return CLI_SHOWUSAGE;
14982 
14983  sig_pri_cli_show_channels_header(a->fd);
14984  for (span = 0; span < NUM_SPANS; ++span) {
14985  if (pris[span].pri.pri) {
14986  sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14987  }
14988  }
14989  return CLI_SUCCESS;
14990 }
14991 #endif /* defined(HAVE_PRI) */
14992 
14993 #if defined(HAVE_PRI)
14994 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14995 {
14996  int span;
14997 
14998  switch (cmd) {
14999  case CLI_INIT:
15000  e->command = "pri show spans";
15001  e->usage =
15002  "Usage: pri show spans\n"
15003  " Displays PRI span information\n";
15004  return NULL;
15005  case CLI_GENERATE:
15006  return NULL;
15007  }
15008 
15009  if (a->argc != 3)
15010  return CLI_SHOWUSAGE;
15011 
15012  for (span = 0; span < NUM_SPANS; span++) {
15013  if (pris[span].pri.pri) {
15014  sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
15015  }
15016  }
15017  return CLI_SUCCESS;
15018 }
15019 #endif /* defined(HAVE_PRI) */
15020 
15021 #if defined(HAVE_PRI)
15022 #define container_of(ptr, type, member) \
15023  ((type *)((char *)(ptr) - offsetof(type, member)))
15024 /*!
15025  * \internal
15026  * \brief Destroy a D-Channel of a PRI span
15027  * \since 12
15028  *
15029  * \param pri the pri span
15030  *
15031  * Shuts down a span and destroys its D-Channel. Further destruction
15032  * of the B-channels using dahdi_destroy_channel() would probably be required
15033  * for the B-Channels.
15034  */
15035 static void pri_destroy_span(struct sig_pri_span *pri)
15036 {
15037  int i;
15038  int res;
15039  int cancel_code;
15040  struct dahdi_pri* dahdi_pri;
15041  pthread_t master = pri->master;
15042 
15043  if (!master || (master == AST_PTHREADT_NULL)) {
15044  return;
15045  }
15046  ast_debug(2, "About to destroy DAHDI channels of span %d.\n", pri->span);
15047  for (i = 0; i < pri->numchans; i++) {
15048  int channel;
15049  struct sig_pri_chan *pvt = pri->pvts[i];
15050 
15051  if (!pvt) {
15052  continue;
15053  }
15054  channel = pvt->channel;
15055  ast_debug(2, "About to destroy B-channel %d.\n", channel);
15056  dahdi_destroy_channel_range(channel, channel);
15057  }
15058 
15059  cancel_code = pthread_cancel(master);
15060  pthread_kill(master, SIGURG);
15061  ast_debug(4,
15062  "Waiting to join thread of span %d "
15063  "with pid=%p cancel_code=%d\n",
15064  pri->span, (void *)master, cancel_code);
15065  res = pthread_join(master, NULL);
15066  if (res != 0) {
15067  ast_log(LOG_NOTICE, "pthread_join failed: %d\n", res);
15068  }
15069  pri->master = AST_PTHREADT_NULL;
15070 
15071  /* The 'struct dahdi_pri' that contains our 'struct sig_pri_span' */
15072  dahdi_pri = container_of(pri, struct dahdi_pri, pri);
15073  for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
15074  ast_debug(4, "closing pri_fd %d\n", i);
15075  dahdi_close_pri_fd(dahdi_pri, i);
15076  dahdi_pri->dchannels[i] = 0;
15077  }
15078  sig_pri_init_pri(pri);
15079  ast_debug(1, "PRI span %d destroyed\n", pri->span);
15080 }
15081 
15082 static char *handle_pri_destroy_span(struct ast_cli_entry *e, int cmd,
15083  struct ast_cli_args *a)
15084 {
15085  int span;
15086  int res;
15087  struct sig_pri_span *pri;
15088 
15089  switch (cmd) {
15090  case CLI_INIT:
15091  e->command = "pri destroy span";
15092  e->usage =
15093  "Usage: pri destroy span <span>\n"
15094  " Destorys D-channel of span and its B-channels.\n"
15095  " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
15096  return NULL;
15097  case CLI_GENERATE:
15098  return complete_span_4(a->line, a->word, a->pos, a->n);
15099  }
15100 
15101  if (a->argc < 4) {
15102  return CLI_SHOWUSAGE;
15103  }
15104  res = sscanf(a->argv[3], "%30d", &span);
15105  if ((res != 1) || span < 1 || span > NUM_SPANS) {
15106  ast_cli(a->fd,
15107  "Invalid span '%s'. Should be a number from %d to %d\n",
15108  a->argv[3], 1, NUM_SPANS);
15109  return CLI_SUCCESS;
15110  }
15111  pri = &pris[span - 1].pri;
15112  if (!pri->pri) {
15113  ast_cli(a->fd, "No PRI running on span %d\n", span);
15114  return CLI_SUCCESS;
15115  }
15116 
15117  pri_destroy_span(pri);
15118  return CLI_SUCCESS;
15119 }
15120 
15121 #endif /* defined(HAVE_PRI) */
15122 
15123 #if defined(HAVE_PRI)
15124 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15125 {
15126  int span;
15127 
15128  switch (cmd) {
15129  case CLI_INIT:
15130  e->command = "pri show span";
15131  e->usage =
15132  "Usage: pri show span <span>\n"
15133  " Displays PRI Information on a given PRI span\n";
15134  return NULL;
15135  case CLI_GENERATE:
15136  return complete_span_4(a->line, a->word, a->pos, a->n);
15137  }
15138 
15139  if (a->argc < 4)
15140  return CLI_SHOWUSAGE;
15141  span = atoi(a->argv[3]);
15142  if ((span < 1) || (span > NUM_SPANS)) {
15143  ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
15144  return CLI_SUCCESS;
15145  }
15146  if (!pris[span-1].pri.pri) {
15147  ast_cli(a->fd, "No PRI running on span %d\n", span);
15148  return CLI_SUCCESS;
15149  }
15150 
15151  sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
15152 
15153  return CLI_SUCCESS;
15154 }
15155 #endif /* defined(HAVE_PRI) */
15156 
15157 #if defined(HAVE_PRI)
15158 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15159 {
15160  int x;
15161  int span;
15162  int count=0;
15163  int debug;
15164 
15165  switch (cmd) {
15166  case CLI_INIT:
15167  e->command = "pri show debug";
15168  e->usage =
15169  "Usage: pri show debug\n"
15170  " Show the debug state of pri spans\n";
15171  return NULL;
15172  case CLI_GENERATE:
15173  return NULL;
15174  }
15175 
15176  for (span = 0; span < NUM_SPANS; span++) {
15177  if (pris[span].pri.pri) {
15178  for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
15179  if (pris[span].pri.dchans[x]) {
15180  debug = pri_get_debug(pris[span].pri.dchans[x]);
15181  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" );
15182  count++;
15183  }
15184  }
15185  }
15186 
15187  }
15188  ast_mutex_lock(&pridebugfdlock);
15189  if (pridebugfd >= 0)
15190  ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
15191  ast_mutex_unlock(&pridebugfdlock);
15192 
15193  if (!count)
15194  ast_cli(a->fd, "No PRI running\n");
15195  return CLI_SUCCESS;
15196 }
15197 #endif /* defined(HAVE_PRI) */
15198 
15199 #if defined(HAVE_PRI)
15200 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15201 {
15202  switch (cmd) {
15203  case CLI_INIT:
15204  e->command = "pri show version";
15205  e->usage =
15206  "Usage: pri show version\n"
15207  "Show libpri version information\n";
15208  return NULL;
15209  case CLI_GENERATE:
15210  return NULL;
15211  }
15212 
15213  ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
15214 
15215  return CLI_SUCCESS;
15216 }
15217 #endif /* defined(HAVE_PRI) */
15218 
15219 #if defined(HAVE_PRI)
15220 static struct ast_cli_entry dahdi_pri_cli[] = {
15221  AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
15222 #if defined(HAVE_PRI_SERVICE_MESSAGES)
15223  AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
15224  AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
15225 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
15226  AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
15227  AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
15228  AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
15229  AST_CLI_DEFINE(handle_pri_destroy_span, "Destroy a PRI span"),
15230  AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
15231  AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
15232  AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
15233 };
15234 #endif /* defined(HAVE_PRI) */
15235 
15236 #ifdef HAVE_OPENR2
15237 
15238 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15239 {
15240  switch (cmd) {
15241  case CLI_INIT:
15242  e->command = "mfcr2 show version";
15243  e->usage =
15244  "Usage: mfcr2 show version\n"
15245  " Shows the version of the OpenR2 library being used.\n";
15246  return NULL;
15247  case CLI_GENERATE:
15248  return NULL;
15249  }
15250  ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
15251  return CLI_SUCCESS;
15252 }
15253 
15254 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15255 {
15256 #define FORMAT "%4s %40s\n"
15257  int i = 0;
15258  int numvariants = 0;
15259  const openr2_variant_entry_t *variants;
15260  switch (cmd) {
15261  case CLI_INIT:
15262  e->command = "mfcr2 show variants";
15263  e->usage =
15264  "Usage: mfcr2 show variants\n"
15265  " Shows the list of MFC/R2 variants supported.\n";
15266  return NULL;
15267  case CLI_GENERATE:
15268  return NULL;
15269  }
15270  if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
15271  ast_cli(a->fd, "Failed to get list of variants.\n");
15272  return CLI_FAILURE;
15273  }
15274  ast_cli(a->fd, FORMAT, "Variant Code", "Country");
15275  for (i = 0; i < numvariants; i++) {
15276  ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
15277  }
15278  return CLI_SUCCESS;
15279 #undef FORMAT
15280 }
15281 
15282 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15283 {
15284 #define FORMAT "%4s %4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
15285  int filtertype = 0;
15286  int targetnum = 0;
15287  char channo[5];
15288  char linkno[5];
15289  char anino[5];
15290  char dnisno[5];
15291  struct dahdi_pvt *p;
15292  openr2_context_t *r2context;
15293  openr2_variant_t r2variant;
15294  switch (cmd) {
15295  case CLI_INIT:
15296  e->command = "mfcr2 show channels [group|context]";
15297  e->usage =
15298  "Usage: mfcr2 show channels [group <group> | context <context>]\n"
15299  " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
15300  return NULL;
15301  case CLI_GENERATE:
15302  return NULL;
15303  }
15304  if (!((a->argc == 3) || (a->argc == 5))) {
15305  return CLI_SHOWUSAGE;
15306  }
15307  if (a->argc == 5) {
15308  if (!strcasecmp(a->argv[3], "group")) {
15309  targetnum = atoi(a->argv[4]);
15310  if ((targetnum < 0) || (targetnum > 63))
15311  return CLI_SHOWUSAGE;
15312  targetnum = 1 << targetnum;
15313  filtertype = 1;
15314  } else if (!strcasecmp(a->argv[3], "context")) {
15315  filtertype = 2;
15316  } else {
15317  return CLI_SHOWUSAGE;
15318  }
15319  }
15320  ast_cli(a->fd, FORMAT, "Chan", "Link#", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
15321  ast_mutex_lock(&iflock);
15322  for (p = iflist; p; p = p->next) {
15323  if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15324  continue;
15325  }
15326  if (filtertype) {
15327  switch(filtertype) {
15328  case 1: /* mfcr2 show channels group <group> */
15329  if (p->group != targetnum) {
15330  continue;
15331  }
15332  break;
15333  case 2: /* mfcr2 show channels context <context> */
15334  if (strcasecmp(p->context, a->argv[4])) {
15335  continue;
15336  }
15337  break;
15338  default:
15339  ;
15340  }
15341  }
15342  r2context = openr2_chan_get_context(p->r2chan);
15343  r2variant = openr2_context_get_variant(r2context);
15344  snprintf(channo, sizeof(channo), "%d", p->channel);
15345  snprintf(linkno, sizeof(linkno), "%d", p->mfcr2->index);
15346  snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
15347  snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
15348  ast_cli(a->fd, FORMAT, channo, linkno, openr2_proto_get_variant_string(r2variant),
15349  anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
15350  openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
15351  openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
15352  }
15353  ast_mutex_unlock(&iflock);
15354  return CLI_SUCCESS;
15355 #undef FORMAT
15356 }
15357 
15358 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15359 {
15360  struct dahdi_pvt *p = NULL;
15361  int channo = 0;
15362  char *toklevel = NULL;
15363  char *saveptr = NULL;
15364  char *logval = NULL;
15365  openr2_log_level_t loglevel = OR2_LOG_NOTHING;
15366  openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
15367  switch (cmd) {
15368  case CLI_INIT:
15369  e->command = "mfcr2 set debug";
15370  e->usage =
15371  "Usage: mfcr2 set debug <loglevel> <channel>\n"
15372  " Set a new logging level for the specified channel.\n"
15373  " If no channel is specified the logging level will be applied to all channels.\n";
15374  return NULL;
15375  case CLI_GENERATE:
15376  return NULL;
15377  }
15378  if (a->argc < 4) {
15379  return CLI_SHOWUSAGE;
15380  }
15381  channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15382  logval = ast_strdupa(a->argv[3]);
15383  toklevel = strtok_r(logval, ",", &saveptr);
15384  if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15385  ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
15386  return CLI_FAILURE;
15387  } else if (OR2_LOG_NOTHING == tmplevel) {
15388  loglevel = tmplevel;
15389  } else {
15390  loglevel |= tmplevel;
15391  while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
15392  if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15393  ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
15394  continue;
15395  }
15396  loglevel |= tmplevel;
15397  }
15398  }
15399  ast_mutex_lock(&iflock);
15400  for (p = iflist; p; p = p->next) {
15401  if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15402  continue;
15403  }
15404  if ((channo != -1) && (p->channel != channo )) {
15405  continue;
15406  }
15407  openr2_chan_set_log_level(p->r2chan, loglevel);
15408  if (channo != -1) {
15409  ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
15410  break;
15411  }
15412  }
15413  if ((channo != -1) && !p) {
15414  ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15415  }
15416  if (channo == -1) {
15417  ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
15418  }
15419  ast_mutex_unlock(&iflock);
15420  return CLI_SUCCESS;
15421 }
15422 
15423 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15424 {
15425  struct dahdi_pvt *p = NULL;
15426  int channo = 0;
15427  switch (cmd) {
15428  case CLI_INIT:
15429  e->command = "mfcr2 call files [on|off]";
15430  e->usage =
15431  "Usage: mfcr2 call files [on|off] <channel>\n"
15432  " Enable call files creation on the specified channel.\n"
15433  " If no channel is specified call files creation policy will be applied to all channels.\n";
15434  return NULL;
15435  case CLI_GENERATE:
15436  return NULL;
15437  }
15438  if (a->argc < 4) {
15439  return CLI_SHOWUSAGE;
15440  }
15441  channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15442  ast_mutex_lock(&iflock);
15443  for (p = iflist; p; p = p->next) {
15444  if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15445  continue;
15446  }
15447  if ((channo != -1) && (p->channel != channo )) {
15448  continue;
15449  }
15450  if (ast_true(a->argv[3])) {
15451  openr2_chan_enable_call_files(p->r2chan);
15452  } else {
15453  openr2_chan_disable_call_files(p->r2chan);
15454  }
15455  if (channo != -1) {
15456  if (ast_true(a->argv[3])) {
15457  ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
15458  } else {
15459  ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
15460  }
15461  break;
15462  }
15463  }
15464  if ((channo != -1) && !p) {
15465  ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15466  }
15467  if (channo == -1) {
15468  if (ast_true(a->argv[3])) {
15469  ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
15470  } else {
15471  ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
15472  }
15473  }
15474  ast_mutex_unlock(&iflock);
15475  return CLI_SUCCESS;
15476 }
15477 
15478 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15479 {
15480  struct dahdi_pvt *p = NULL;
15481  int channo = 0;
15482  switch (cmd) {
15483  case CLI_INIT:
15484  e->command = "mfcr2 set idle";
15485  e->usage =
15486  "Usage: mfcr2 set idle <channel>\n"
15487  " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15488  " Force the given channel into IDLE state.\n"
15489  " If no channel is specified, all channels will be set to IDLE.\n";
15490  return NULL;
15491  case CLI_GENERATE:
15492  return NULL;
15493  }
15494  channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15495  ast_mutex_lock(&iflock);
15496  for (p = iflist; p; p = p->next) {
15497  if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15498  continue;
15499  }
15500  if ((channo != -1) && (p->channel != channo )) {
15501  continue;
15502  }
15503  openr2_chan_set_idle(p->r2chan);
15504  ast_mutex_lock(&p->lock);
15505  p->locallyblocked = 0;
15506  p->mfcr2call = 0;
15507  ast_mutex_unlock(&p->lock);
15508  if (channo != -1) {
15509  break;
15510  }
15511  }
15512  if ((channo != -1) && !p) {
15513  ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15514  }
15515  ast_mutex_unlock(&iflock);
15516  return CLI_SUCCESS;
15517 }
15518 
15519 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15520 {
15521  struct dahdi_pvt *p = NULL;
15522  int channo = 0;
15523  switch (cmd) {
15524  case CLI_INIT:
15525  e->command = "mfcr2 set blocked";
15526  e->usage =
15527  "Usage: mfcr2 set blocked <channel>\n"
15528  " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15529  " Force the given channel into BLOCKED state.\n"
15530  " If no channel is specified, all channels will be set to BLOCKED.\n";
15531  return NULL;
15532  case CLI_GENERATE:
15533  return NULL;
15534  }
15535  channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15536  ast_mutex_lock(&iflock);
15537  for (p = iflist; p; p = p->next) {
15538  if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15539  continue;
15540  }
15541  if ((channo != -1) && (p->channel != channo )) {
15542  continue;
15543  }
15544  openr2_chan_set_blocked(p->r2chan);
15545  ast_mutex_lock(&p->lock);
15546  p->locallyblocked = 1;
15547  ast_mutex_unlock(&p->lock);
15548  if (channo != -1) {
15549  break;
15550  }
15551  }
15552  if ((channo != -1) && !p) {
15553  ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15554  }
15555  ast_mutex_unlock(&iflock);
15556  return CLI_SUCCESS;
15557 }
15558 
15559 static void mfcr2_show_links_of(struct ast_cli_args *a, struct r2links *list_head, const char *title)
15560 {
15561 #define FORMAT "%-5s %-10s %-15s %-10s %s\n"
15562  AST_LIST_LOCK(list_head);
15563  if (! AST_LIST_EMPTY(list_head)) {
15564  int x = 0;
15565  char index[5];
15566  char live_chans_str[5];
15567  char channel_list[R2_LINK_CAPACITY * 4];
15568  struct r2link_entry *cur;
15569  ast_cli(a->fd, "%s\n", title);
15570  ast_cli(a->fd, FORMAT, "Index", "Thread", "Dahdi-Device", "Channels", "Channel-List");
15571  AST_LIST_TRAVERSE(list_head, cur, list) {
15572  struct dahdi_mfcr2 *mfcr2 = &cur->mfcr2;
15573  const char *thread_status = NULL;
15574  int i;
15575  int len;
15576  int inside_range;
15577  int channo;
15578  int prev_channo;
15579  x++;
15580  if (mfcr2->r2master == 0L) {
15581  thread_status = "zero";
15582  } else if (mfcr2->r2master == AST_PTHREADT_NULL) {
15583  thread_status = "none";
15584  } else {
15585  thread_status = "created";
15586  }
15587  snprintf(index, sizeof(index), "%d", mfcr2->index);
15588  snprintf(live_chans_str, sizeof(live_chans_str), "%d", mfcr2->live_chans);
15589  channo = 0;
15590  prev_channo = 0;
15591  inside_range = 0;
15592  len = 0;
15593  /* Prepare nice string in channel_list[] */
15594  for (i = 0; i < mfcr2->numchans && len < sizeof(channel_list) - 1; i++) {
15595  struct dahdi_pvt *p = mfcr2->pvts[i];
15596  if (!p) {
15597  continue;
15598  }
15599  channo = p->channel;
15600  /* Don't show a range until we know the last channel number */
15601  if (prev_channo && prev_channo == channo - 1) {
15602  prev_channo = channo;
15603  inside_range = 1;
15604  continue;
15605  }
15606  if (inside_range) {
15607  /* Close range */
15608  len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, "-%d,%d", prev_channo, channo);
15609  inside_range = 0;
15610  } else if (prev_channo) {
15611  /* Non-sequential channel numbers */
15612  len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, ",%d", channo);
15613  } else {
15614  /* First channel number */
15615  len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, "%d", channo);
15616  }
15617  prev_channo = channo;
15618  }
15619  /* Handle leftover channels */
15620  if (inside_range) {
15621  /* Close range */
15622  len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, "-%d", channo);
15623  inside_range = 0;
15624  } else if (prev_channo) {
15625  /* Non-sequential channel numbers */
15626  len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, ",%d", channo);
15627  }
15628  // channel_list[len] = '\0';
15629  ast_cli(a->fd, FORMAT,
15630  index,
15631  thread_status,
15632  (mfcr2->nodev) ? "MISSING" : "OK",
15633  live_chans_str,
15634  channel_list);
15635  }
15636  }
15637  AST_LIST_UNLOCK(list_head);
15638 #undef FORMAT
15639 }
15640 
15641 static char *handle_mfcr2_show_links(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15642 {
15643  switch (cmd) {
15644  case CLI_INIT:
15645  e->command = "mfcr2 show links";
15646  e->usage =
15647  "Usage: mfcr2 show links\n"
15648  " Shows the DAHDI MFC/R2 links.\n";
15649  return NULL;
15650  case CLI_GENERATE:
15651  return NULL;
15652  }
15653  if (a->argc != 3) {
15654  return CLI_SHOWUSAGE;
15655  }
15656  mfcr2_show_links_of(a, &r2links, "Live links\n");
15657  mfcr2_show_links_of(a, &nodev_r2links, "Links to be removed (device missing)\n");
15658  return CLI_SUCCESS;
15659 }
15660 
15661 static char *handle_mfcr2_destroy_link(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15662 {
15663  int res;
15664  int wanted_link_index;
15665  int found_link = 0;
15666  struct r2link_entry *cur = NULL;
15667 
15668  switch (cmd) {
15669  case CLI_INIT:
15670  e->command = "mfcr2 destroy link";
15671  e->usage =
15672  "Usage: mfcr2 destroy link <index-number>\n"
15673  " Destorys D-channel of link and its B-channels.\n"
15674  " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
15675  return NULL;
15676  case CLI_GENERATE:
15677  return NULL;
15678  }
15679  if (a->argc < 4) {
15680  return CLI_SHOWUSAGE;
15681  }
15682  res = sscanf(a->argv[3], "%30d", &wanted_link_index);
15683  if ((res != 1) || wanted_link_index < 1) {
15684  ast_cli(a->fd,
15685  "Invalid link index '%s'. Should be a positive number\n", a->argv[3]);
15686  return CLI_SUCCESS;
15687  }
15688  AST_LIST_LOCK(&r2links);
15689  AST_LIST_TRAVERSE_SAFE_BEGIN(&r2links, cur, list) {
15690  struct dahdi_mfcr2 *mfcr2 = &cur->mfcr2;
15691  if (wanted_link_index == mfcr2->index) {
15692  AST_LIST_MOVE_CURRENT(&nodev_r2links, list);
15693  r2links_count--;
15694  break;
15695  }
15696  }
15698  AST_LIST_UNLOCK(&r2links);
15699  if (! found_link) {
15700  ast_cli(a->fd, "No link found with index %d.\n", wanted_link_index);
15701  return CLI_FAILURE;
15702  }
15703  return CLI_SUCCESS;
15704 }
15705 
15706 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15707  AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15708  AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15709  AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15710  AST_CLI_DEFINE(handle_mfcr2_show_links, "Show MFC/R2 links"),
15711  AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15712  AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15713  AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15714  AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15715  AST_CLI_DEFINE(handle_mfcr2_destroy_link, "Destroy given MFC/R2 link"),
15716 };
15717 
15718 #endif /* HAVE_OPENR2 */
15719 
15720 static char *dahdi_destroy_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15721 {
15722  int start;
15723  int end;
15724  switch (cmd) {
15725  case CLI_INIT:
15726  e->command = "dahdi destroy channels";
15727  e->usage =
15728  "Usage: dahdi destroy channels <from_channel> [<to_channel>]\n"
15729  " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
15730  return NULL;
15731  case CLI_GENERATE:
15732  return NULL;
15733  }
15734  if ((a->argc < 4) || a->argc > 5) {
15735  return CLI_SHOWUSAGE;
15736  }
15737  start = atoi(a->argv[3]);
15738  if (start < 1) {
15739  ast_cli(a->fd, "Invalid starting channel number %s.\n",
15740  a->argv[4]);
15741  return CLI_FAILURE;
15742  }
15743  if (a->argc == 5) {
15744  end = atoi(a->argv[4]);
15745  if (end < 1) {
15746  ast_cli(a->fd, "Invalid ending channel number %s.\n",
15747  a->argv[4]);
15748  return CLI_FAILURE;
15749  }
15750  } else {
15751  end = start;
15752  }
15753 
15754  if (end < start) {
15755  ast_cli(a->fd,
15756  "range end (%d) is smaller than range start (%d)\n",
15757  end, start);
15758  return CLI_FAILURE;
15759  }
15760  dahdi_destroy_channel_range(start, end);
15761  return CLI_SUCCESS;
15762 }
15763 
15764 static char *dahdi_create_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15765 {
15766  int start;
15767  int end;
15768  int ret;
15769 
15770  switch (cmd) {
15771  case CLI_INIT:
15772  e->command = "dahdi create channels";
15773  e->usage = "Usage: dahdi create channels <from> [<to>] - a range of channels\n"
15774  " dahdi create channels new - add channels not yet created\n"
15775  "For ISDN and SS7 the range should include complete spans.\n";
15776  return NULL;
15777  case CLI_GENERATE:
15778  return NULL;
15779  }
15780  if ((a->argc < 4) || a->argc > 5) {
15781  return CLI_SHOWUSAGE;
15782  }
15783  if (a->argc == 4 && !strcmp(a->argv[3], "new")) {
15784  ret = dahdi_create_channel_range(0, 0);
15785  return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
15786  }
15787  start = atoi(a->argv[3]);
15788  if (start <= 0) {
15789  ast_cli(a->fd, "Invalid starting channel number '%s'.\n",
15790  a->argv[3]);
15791  return CLI_FAILURE;
15792  }
15793  if (a->argc == 5) {
15794  end = atoi(a->argv[4]);
15795  if (end <= 0) {
15796  ast_cli(a->fd, "Invalid ending channel number '%s'.\n",
15797  a->argv[4]);
15798  return CLI_FAILURE;
15799  }
15800  } else {
15801  end = start;
15802  }
15803  if (end < start) {
15804  ast_cli(a->fd,
15805  "range end (%d) is smaller than range start (%d)\n",
15806  end, start);
15807  return CLI_FAILURE;
15808  }
15809  ret = dahdi_create_channel_range(start, end);
15810  return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
15811 }
15812 
15813 static void dahdi_softhangup_all(void)
15814 {
15815  struct dahdi_pvt *p;
15816 retry:
15817  ast_mutex_lock(&iflock);
15818  for (p = iflist; p; p = p->next) {
15819  ast_mutex_lock(&p->lock);
15820  if (p->owner && !p->restartpending) {
15821  if (ast_channel_trylock(p->owner)) {
15822  if (DEBUG_ATLEAST(3))
15823  ast_verbose("Avoiding deadlock\n");
15824  /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15825  ast_mutex_unlock(&p->lock);
15826  ast_mutex_unlock(&iflock);
15827  goto retry;
15828  }
15829  if (DEBUG_ATLEAST(3))
15830  ast_verbose("Softhanging up on %s\n", ast_channel_name(p->owner));
15832  p->restartpending = 1;
15833  num_restart_pending++;
15834  ast_channel_unlock(p->owner);
15835  }
15836  ast_mutex_unlock(&p->lock);
15837  }
15838  ast_mutex_unlock(&iflock);
15839 }
15840 
15841 static int dahdi_restart(void)
15842 {
15843 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15844  int i, j;
15845 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15846  int cancel_code;
15847  struct dahdi_pvt *p;
15848 
15849  ast_mutex_lock(&restart_lock);
15850  ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15851  dahdi_softhangup_all();
15852  ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15853 #ifdef HAVE_OPENR2
15854  dahdi_r2_destroy_links();
15855 #endif
15856 
15857 #if defined(HAVE_PRI)
15858  for (i = 0; i < NUM_SPANS; i++) {
15859  if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15860  cancel_code = pthread_cancel(pris[i].pri.master);
15861  pthread_kill(pris[i].pri.master, SIGURG);
15862  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);
15863  pthread_join(pris[i].pri.master, NULL);
15864  ast_debug(4, "Joined thread of span %d\n", i);
15865  }
15866  }
15867 #endif
15868 
15869 #if defined(HAVE_SS7)
15870  for (i = 0; i < NUM_SPANS; i++) {
15871  if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15872  cancel_code = pthread_cancel(linksets[i].ss7.master);
15873  pthread_kill(linksets[i].ss7.master, SIGURG);
15874  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);
15875  pthread_join(linksets[i].ss7.master, NULL);
15876  ast_debug(4, "Joined thread of span %d\n", i);
15877  }
15878  }
15879 #endif /* defined(HAVE_SS7) */
15880 
15881  ast_mutex_lock(&monlock);
15882  if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15883  cancel_code = pthread_cancel(monitor_thread);
15884  pthread_kill(monitor_thread, SIGURG);
15885  ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15886  pthread_join(monitor_thread, NULL);
15887  ast_debug(4, "Joined monitor thread\n");
15888  }
15889  monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15890 
15891  ast_mutex_lock(&ss_thread_lock);
15892  while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15893  int x = DAHDI_FLASH;
15894  ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15895 
15896  ast_mutex_lock(&iflock);
15897  for (p = iflist; p; p = p->next) {
15898  if (p->owner) {
15899  /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15900  ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15901  }
15902  }
15903  ast_mutex_unlock(&iflock);
15904  ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15905  }
15906 
15907  /* ensure any created channels before monitor threads were stopped are hungup */
15908  dahdi_softhangup_all();
15909  ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15910  destroy_all_channels();
15911  memset(round_robin, 0, sizeof(round_robin));
15912  ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15913 
15914  ast_mutex_unlock(&monlock);
15915 
15916 #ifdef HAVE_PRI
15917  for (i = 0; i < NUM_SPANS; i++) {
15918  for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15919  dahdi_close_pri_fd(&(pris[i]), j);
15920  }
15921 
15922  memset(pris, 0, sizeof(pris));
15923  for (i = 0; i < NUM_SPANS; i++) {
15924  sig_pri_init_pri(&pris[i].pri);
15925  }
15926  pri_set_error(dahdi_pri_error);
15927  pri_set_message(dahdi_pri_message);
15928 #endif
15929 #if defined(HAVE_SS7)
15930  for (i = 0; i < NUM_SPANS; i++) {
15931  for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15932  dahdi_close_ss7_fd(&(linksets[i]), j);
15933  }
15934 
15935  memset(linksets, 0, sizeof(linksets));
15936  for (i = 0; i < NUM_SPANS; i++) {
15937  sig_ss7_init_linkset(&linksets[i].ss7);
15938  }
15939  ss7_set_error(dahdi_ss7_error);
15940  ss7_set_message(dahdi_ss7_message);
15941  ss7_set_hangup(sig_ss7_cb_hangup);
15942  ss7_set_notinservice(sig_ss7_cb_notinservice);
15943  ss7_set_call_null(sig_ss7_cb_call_null);
15944 #endif /* defined(HAVE_SS7) */
15945 
15946  if (setup_dahdi(2) != 0) {
15947  ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15948  ast_mutex_unlock(&ss_thread_lock);
15949  return 1;
15950  }
15951  ast_mutex_unlock(&ss_thread_lock);
15952  ast_mutex_unlock(&restart_lock);
15953  return 0;
15954 }
15955 
15956 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15957 {
15958  switch (cmd) {
15959  case CLI_INIT:
15960  e->command = "dahdi restart";
15961  e->usage =
15962  "Usage: dahdi restart\n"
15963  " Restarts the DAHDI channels: destroys them all and then\n"
15964  " re-reads them from chan_dahdi.conf.\n"
15965  " Note that this will STOP any running CALL on DAHDI channels.\n"
15966  "";
15967  return NULL;
15968  case CLI_GENERATE:
15969  return NULL;
15970  }
15971  if (a->argc != 2)
15972  return CLI_SHOWUSAGE;
15973 
15974  if (dahdi_restart() != 0)
15975  return CLI_FAILURE;
15976  return CLI_SUCCESS;
15977 }
15978 
15979 static int action_dahdirestart(struct mansession *s, const struct message *m)
15980 {
15981  if (dahdi_restart() != 0) {
15982  astman_send_error(s, m, "Failed rereading DAHDI configuration");
15983  return 1;
15984  }
15985  astman_send_ack(s, m, "DAHDIRestart: Success");
15986  return 0;
15987 }
15988 
15989 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15990 {
15991 #define FORMAT "%7s %4d %-20.20s %-10.10s %-15.15s %-8.8s %-20.20s %-10.10s %-10.10s %-12.12s %-32.32s\n"
15992 #define FORMAT2 "%7s %4s %-20.20s %-10.10s %-15.15s %-8.8s %-20.20s %-10.10s %-10.10s %-12.12s %-32.32s\n"
15993  ast_group_t targetnum = 0;
15994  int filtertype = 0;
15995  struct dahdi_pvt *tmp = NULL;
15996  char tmps[20];
15997  char blockstr[20];
15998 
15999  switch (cmd) {
16000  case CLI_INIT:
16001  e->command = "dahdi show channels [group|context]";
16002  e->usage =
16003  "Usage: dahdi show channels [ group <group> | context <context> ]\n"
16004  " Shows a list of available channels with optional filtering\n"
16005  " <group> must be a number between 0 and 63\n";
16006  return NULL;
16007  case CLI_GENERATE:
16008  return NULL;
16009  }
16010 
16011  /* syntax: dahdi show channels [ group <group> | context <context> ] */
16012 
16013  if (!((a->argc == 3) || (a->argc == 5))) {
16014  return CLI_SHOWUSAGE;
16015  }
16016 
16017  if (a->argc == 5) {
16018  if (!strcasecmp(a->argv[3], "group")) {
16019  targetnum = atoi(a->argv[4]);
16020  if (63 < targetnum) {
16021  return CLI_SHOWUSAGE;
16022  }
16023  targetnum = ((ast_group_t) 1) << targetnum;
16024  filtertype = 1;
16025  } else if (!strcasecmp(a->argv[3], "context")) {
16026  filtertype = 2;
16027  }
16028  }
16029 
16030  ast_cli(a->fd, FORMAT2, "Chan", "Span", "Signalling", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "In Service", "Alarms", "Description");
16031  ast_mutex_lock(&iflock);
16032  for (tmp = iflist; tmp; tmp = tmp->next) {
16033  int alm = 0;
16034  if (filtertype) {
16035  switch(filtertype) {
16036  case 1: /* dahdi show channels group <group> */
16037  if (!(tmp->group & targetnum)) {
16038  continue;
16039  }
16040  break;
16041  case 2: /* dahdi show channels context <context> */
16042  if (strcasecmp(tmp->context, a->argv[4])) {
16043  continue;
16044  }
16045  break;
16046  default:
16047  break;
16048  }
16049  }
16050  if (tmp->channel > 0) {
16051  snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
16052  alm = get_alarms(tmp);
16053  } else {
16054  ast_copy_string(tmps, "pseudo", sizeof(tmps));
16055  }
16056 
16057  blockstr[0] = tmp->locallyblocked ? 'L' : ' ';
16058  blockstr[1] = tmp->remotelyblocked ? 'R' : ' ';
16059  blockstr[2] = '\0';
16060 
16061  ast_cli(a->fd, FORMAT, tmps, tmp->span, sig2str(tmp->sig), tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, tmp->inservice ? "Yes" : "No",
16062  alarm2str(alm), tmp->description);
16063  }
16064  ast_mutex_unlock(&iflock);
16065  return CLI_SUCCESS;
16066 #undef FORMAT
16067 #undef FORMAT2
16068 }
16069 
16070 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16071 {
16072  int channel;
16073  struct dahdi_pvt *tmp = NULL;
16074  struct dahdi_confinfo ci;
16075  struct dahdi_params ps;
16076  int x;
16077  char hwrxgain[15];
16078  char hwtxgain[15];
16079 
16080  switch (cmd) {
16081  case CLI_INIT:
16082  e->command = "dahdi show channel";
16083  e->usage =
16084  "Usage: dahdi show channel <chan num>\n"
16085  " Detailed information about a given channel\n";
16086  return NULL;
16087  case CLI_GENERATE:
16088  return NULL;
16089  }
16090 
16091  if (a->argc != 4)
16092  return CLI_SHOWUSAGE;
16093 
16094  channel = atoi(a->argv[3]);
16095 
16096  ast_mutex_lock(&iflock);
16097  for (tmp = iflist; tmp; tmp = tmp->next) {
16098  if (tmp->channel == channel) {
16099  ast_cli(a->fd, "Channel: %d\n", tmp->channel);
16100  ast_cli(a->fd, "Description: %s\n", tmp->description);
16101  ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
16102  ast_cli(a->fd, "Span: %d\n", tmp->span);
16103  ast_cli(a->fd, "Extension: %s\n", tmp->exten);
16104  ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
16105  ast_cli(a->fd, "Context: %s\n", tmp->context);
16106  ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
16107  ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
16108 #if defined(HAVE_PRI)
16109 #if defined(HAVE_PRI_SUBADDR)
16110  ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
16111 #endif /* defined(HAVE_PRI_SUBADDR) */
16112 #endif /* defined(HAVE_PRI) */
16113  ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
16114  ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
16115  if (tmp->vars) {
16116  struct ast_variable *v;
16117  ast_cli(a->fd, "Variables:\n");
16118  for (v = tmp->vars ; v ; v = v->next)
16119  ast_cli(a->fd, " %s = %s\n", v->name, v->value);
16120  }
16121  ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
16122  ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
16123  ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
16124  ast_cli(a->fd, "Radio: %d\n", tmp->radio);
16125  ast_cli(a->fd, "Owner: %s\n", tmp->owner ? ast_channel_name(tmp->owner) : "<None>");
16126  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)" : "");
16127  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)" : "");
16128  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)" : "");
16129  ast_cli(a->fd, "Confno: %d\n", tmp->confno);
16130  ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
16131  ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
16132  ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
16133  ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
16134  if (tmp->busydetect) {
16135 #if defined(BUSYDETECT_TONEONLY)
16136  ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
16137 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
16138  ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
16139 #endif
16140 #ifdef BUSYDETECT_DEBUG
16141  ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
16142 #endif
16143  ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
16144  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);
16145  }
16146  ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
16147  ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
16148  ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
16149  ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
16150  ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
16151  ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
16152  if (tmp->hwrxgain_enabled) {
16153  snprintf(hwrxgain, sizeof(hwrxgain), "%.1f", tmp->hwrxgain);
16154  } else {
16155  ast_copy_string(hwrxgain, "Disabled", sizeof(hwrxgain));
16156  }
16157  if (tmp->hwtxgain_enabled) {
16158  snprintf(hwtxgain, sizeof(hwtxgain), "%.1f", tmp->hwtxgain);
16159  } else {
16160  ast_copy_string(hwtxgain, "Disabled", sizeof(hwtxgain));
16161  }
16162  ast_cli(a->fd, "HW Gains (RX/TX): %s/%s\n", hwrxgain, hwtxgain);
16163  ast_cli(a->fd, "SW Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
16164  ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
16165  ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
16166  ast_cli(a->fd, "Echo Cancellation:\n");
16167 
16168  if (tmp->echocancel.head.tap_length) {
16169  ast_cli(a->fd, "\t%u taps\n", tmp->echocancel.head.tap_length);
16170  for (x = 0; x < tmp->echocancel.head.param_count; x++) {
16171  ast_cli(a->fd, "\t\t%s: %dd\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
16172  }
16173  ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
16174  } else {
16175  ast_cli(a->fd, "\tnone\n");
16176  }
16177  ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
16178  if (tmp->master)
16179  ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
16180  for (x = 0; x < MAX_SLAVES; x++) {
16181  if (tmp->slaves[x])
16182  ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
16183  }
16184 #ifdef HAVE_OPENR2
16185  if (tmp->mfcr2) {
16186  char calldir[OR2_MAX_PATH];
16187  openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
16188  openr2_variant_t r2variant = openr2_context_get_variant(r2context);
16189  ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
16190  ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
16191  ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
16192  ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
16193  ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
16194  ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
16195  ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
16196  ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
16197 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
16198  ast_cli(a->fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
16199  ast_cli(a->fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
16200 #endif
16201  ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
16202 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
16203  ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
16204 #endif
16205  ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
16206  ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
16207  ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
16208  ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
16209  ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
16210  ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
16211  ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
16212  ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
16213  ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
16214  ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
16215  ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
16216  ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
16217  }
16218 #endif
16219 #if defined(HAVE_SS7)
16220  if (tmp->ss7) {
16221  struct sig_ss7_chan *chan = tmp->sig_pvt;
16222 
16223  ast_cli(a->fd, "CIC: %d\n", chan->cic);
16224  }
16225 #endif /* defined(HAVE_SS7) */
16226 #ifdef HAVE_PRI
16227  if (tmp->pri) {
16228  struct sig_pri_chan *chan = tmp->sig_pvt;
16229 
16230  ast_cli(a->fd, "PRI Flags: ");
16231  if (chan->resetting != SIG_PRI_RESET_IDLE) {
16232  ast_cli(a->fd, "Resetting=%u ", chan->resetting);
16233  }
16234  if (chan->call)
16235  ast_cli(a->fd, "Call ");
16236  if (chan->allocated) {
16237  ast_cli(a->fd, "Allocated ");
16238  }
16239  ast_cli(a->fd, "\n");
16240  if (tmp->logicalspan)
16241  ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
16242  else
16243  ast_cli(a->fd, "PRI Logical Span: Implicit\n");
16244  }
16245 #endif
16246  memset(&ci, 0, sizeof(ci));
16247  ps.channo = tmp->channel;
16248  if (tmp->subs[SUB_REAL].dfd > -1) {
16249  memset(&ci, 0, sizeof(ci));
16250  if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
16251  ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, (unsigned)ci.confmode);
16252  }
16253  if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
16254  ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
16255  }
16256  memset(&ps, 0, sizeof(ps));
16257  if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
16258  ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
16259  } else {
16260  ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
16261  }
16262  }
16263  ast_mutex_unlock(&iflock);
16264  return CLI_SUCCESS;
16265  }
16266  }
16267  ast_mutex_unlock(&iflock);
16268 
16269  ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16270  return CLI_FAILURE;
16271 }
16272 
16273 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16274 {
16275  int i, j;
16276  switch (cmd) {
16277  case CLI_INIT:
16278  e->command = "dahdi show cadences";
16279  e->usage =
16280  "Usage: dahdi show cadences\n"
16281  " Shows all cadences currently defined\n";
16282  return NULL;
16283  case CLI_GENERATE:
16284  return NULL;
16285  }
16286  for (i = 0; i < num_cadence; i++) {
16287  char output[1024];
16288  char tmp[16], tmp2[64];
16289  snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
16290  term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
16291 
16292  for (j = 0; j < 16; j++) {
16293  if (cadences[i].ringcadence[j] == 0)
16294  break;
16295  snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
16296  if (cidrings[i] * 2 - 1 == j)
16297  term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
16298  else
16299  term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
16300  if (j != 0)
16301  strncat(output, ",", sizeof(output) - strlen(output) - 1);
16302  strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
16303  }
16304  ast_cli(a->fd,"%s\n",output);
16305  }
16306  return CLI_SUCCESS;
16307 }
16308 
16309 static void build_alarm_info(char *restrict alarmstr, struct dahdi_spaninfo *spaninfo)
16310 {
16311  alarmstr[0] = '\0';
16312  if (spaninfo->alarms > 0) {
16313  if (spaninfo->alarms & DAHDI_ALARM_BLUE) {
16314  strcat(alarmstr, "BLU/");
16315  }
16316  if (spaninfo->alarms & DAHDI_ALARM_YELLOW) {
16317  strcat(alarmstr, "YEL/");
16318  }
16319  if (spaninfo->alarms & DAHDI_ALARM_RED) {
16320  strcat(alarmstr, "RED/");
16321  }
16322  if (spaninfo->alarms & DAHDI_ALARM_LOOPBACK) {
16323  strcat(alarmstr, "LB/");
16324  }
16325  if (spaninfo->alarms & DAHDI_ALARM_RECOVER) {
16326  strcat(alarmstr, "REC/");
16327  }
16328  if (spaninfo->alarms & DAHDI_ALARM_NOTOPEN) {
16329  strcat(alarmstr, "NOP/");
16330  }
16331  if (!strlen(alarmstr)) {
16332  strcat(alarmstr, "UUU/");
16333  }
16334  if (strlen(alarmstr)) {
16335  /* Strip trailing / */
16336  alarmstr[strlen(alarmstr) - 1] = '\0';
16337  }
16338  } else {
16339  if (spaninfo->numchans) {
16340  strcpy(alarmstr, "OK");
16341  } else {
16342  strcpy(alarmstr, "UNCONFIGURED");
16343  }
16344  }
16345 }
16346 
16347 /* Based on irqmiss.c */
16348 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16349 {
16350  #define FORMAT "%4d %-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
16351  #define FORMAT2 "%4s %-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
16352  int span;
16353  int res;
16354  char alarmstr[50];
16355 
16356  int ctl;
16357  struct dahdi_spaninfo s;
16358 
16359  switch (cmd) {
16360  case CLI_INIT:
16361  e->command = "dahdi show status";
16362  e->usage =
16363  "Usage: dahdi show status\n"
16364  " Shows a list of DAHDI cards with status\n";
16365  return NULL;
16366  case CLI_GENERATE:
16367  return NULL;
16368  }
16369  ctl = open("/dev/dahdi/ctl", O_RDWR);
16370  if (ctl < 0) {
16371  ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
16372  return CLI_FAILURE;
16373  }
16374  ast_cli(a->fd, FORMAT2, "Span", "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
16375 
16376  for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
16377  s.spanno = span;
16378  res = ioctl(ctl, DAHDI_SPANSTAT, &s);
16379  if (res) {
16380  continue;
16381  }
16382  build_alarm_info(alarmstr, &s);
16383  ast_cli(a->fd, FORMAT, span, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
16384  s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
16385  s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
16386  s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
16387  "CAS",
16388  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
16389  s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
16390  s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
16391  "Unknown",
16392  s.lineconfig & DAHDI_CONFIG_CRC4 ?
16393  s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
16394  s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
16395  lbostr[s.lbo]
16396  );
16397  }
16398  close(ctl);
16399 
16400  return CLI_SUCCESS;
16401 #undef FORMAT
16402 #undef FORMAT2
16403 }
16404 
16405 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16406 {
16407  int pseudo_fd = -1;
16408  struct dahdi_versioninfo vi;
16409 
16410  switch (cmd) {
16411  case CLI_INIT:
16412  e->command = "dahdi show version";
16413  e->usage =
16414  "Usage: dahdi show version\n"
16415  " Shows the DAHDI version in use\n";
16416  return NULL;
16417  case CLI_GENERATE:
16418  return NULL;
16419  }
16420  if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
16421  ast_cli(a->fd, "Failed to open control file to get version.\n");
16422  return CLI_SUCCESS;
16423  }
16424 
16425  strcpy(vi.version, "Unknown");
16426  strcpy(vi.echo_canceller, "Unknown");
16427 
16428  if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
16429  ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
16430  else
16431  ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
16432 
16433  close(pseudo_fd);
16434 
16435  return CLI_SUCCESS;
16436 }
16437 
16438 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16439 {
16440  int channel;
16441  float gain;
16442  int tx;
16443  struct dahdi_pvt *tmp = NULL;
16444 
16445  switch (cmd) {
16446  case CLI_INIT:
16447  e->command = "dahdi set hwgain {rx|tx}";
16448  e->usage =
16449  "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
16450  " Sets the hardware gain on a given channel and overrides the\n"
16451  " value provided at module loadtime. Changes take effect\n"
16452  " immediately whether the channel is in use or not.\n"
16453  "\n"
16454  " <rx|tx> which direction do you want to change (relative to our module)\n"
16455  " <chan num> is the channel number relative to the device\n"
16456  " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
16457  "\n"
16458  " Please note:\n"
16459  " * hwgain is only supportable by hardware with analog ports because\n"
16460  " hwgain works on the analog side of an analog-digital conversion.\n";
16461  return NULL;
16462  case CLI_GENERATE:
16463  return NULL;
16464  }
16465 
16466  if (a->argc != 6)
16467  return CLI_SHOWUSAGE;
16468 
16469  if (!strcasecmp("rx", a->argv[3]))
16470  tx = 0; /* rx */
16471  else if (!strcasecmp("tx", a->argv[3]))
16472  tx = 1; /* tx */
16473  else
16474  return CLI_SHOWUSAGE;
16475 
16476  channel = atoi(a->argv[4]);
16477  gain = atof(a->argv[5]);
16478 
16479  ast_mutex_lock(&iflock);
16480 
16481  for (tmp = iflist; tmp; tmp = tmp->next) {
16482 
16483  if (tmp->channel != channel)
16484  continue;
16485 
16486  if (tmp->subs[SUB_REAL].dfd == -1)
16487  break;
16488 
16489  if (set_hwgain(tmp->subs[SUB_REAL].dfd, gain, tx)) {
16490  ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
16491  ast_mutex_unlock(&iflock);
16492  return CLI_FAILURE;
16493  }
16494  ast_cli(a->fd, "Hardware %s gain set to %.1f dB on channel %d.\n",
16495  tx ? "tx" : "rx", gain, channel);
16496 
16497  if (tx) {
16498  tmp->hwtxgain_enabled = 1;
16499  tmp->hwtxgain = gain;
16500  } else {
16501  tmp->hwrxgain_enabled = 1;
16502  tmp->hwrxgain = gain;
16503  }
16504  break;
16505  }
16506 
16507  ast_mutex_unlock(&iflock);
16508 
16509  if (tmp)
16510  return CLI_SUCCESS;
16511 
16512  ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16513  return CLI_FAILURE;
16514 
16515 }
16516 
16517 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16518 {
16519  int channel;
16520  float gain;
16521  int tx;
16522  int res;
16523  struct dahdi_pvt *tmp = NULL;
16524 
16525  switch (cmd) {
16526  case CLI_INIT:
16527  e->command = "dahdi set swgain {rx|tx}";
16528  e->usage =
16529  "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
16530  " Sets the software gain on a given channel and overrides the\n"
16531  " value provided at module loadtime. Changes take effect\n"
16532  " immediately whether the channel is in use or not.\n"
16533  "\n"
16534  " <rx|tx> which direction do you want to change (relative to our module)\n"
16535  " <chan num> is the channel number relative to the device\n"
16536  " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
16537  return NULL;
16538  case CLI_GENERATE:
16539  return NULL;
16540  }
16541 
16542  if (a->argc != 6)
16543  return CLI_SHOWUSAGE;
16544 
16545  if (!strcasecmp("rx", a->argv[3]))
16546  tx = 0; /* rx */
16547  else if (!strcasecmp("tx", a->argv[3]))
16548  tx = 1; /* tx */
16549  else
16550  return CLI_SHOWUSAGE;
16551 
16552  channel = atoi(a->argv[4]);
16553  gain = atof(a->argv[5]);
16554 
16555  ast_mutex_lock(&iflock);
16556  for (tmp = iflist; tmp; tmp = tmp->next) {
16557 
16558  if (tmp->channel != channel)
16559  continue;
16560 
16561  if (tmp->subs[SUB_REAL].dfd == -1)
16562  break;
16563 
16564  if (tx)
16565  res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
16566  else
16567  res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
16568 
16569  if (res) {
16570  ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
16571  ast_mutex_unlock(&iflock);
16572  return CLI_FAILURE;
16573  }
16574 
16575  ast_cli(a->fd, "Software %s gain set to %.2f dB on channel %d.\n",
16576  tx ? "tx" : "rx", gain, channel);
16577 
16578  if (tx) {
16579  tmp->txgain = gain;
16580  } else {
16581  tmp->rxgain = gain;
16582  }
16583  break;
16584  }
16585  ast_mutex_unlock(&iflock);
16586 
16587  if (tmp)
16588  return CLI_SUCCESS;
16589 
16590  ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16591  return CLI_FAILURE;
16592 
16593 }
16594 
16595 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16596 {
16597  int channel;
16598  int on;
16599  struct dahdi_pvt *dahdi_chan = NULL;
16600 
16601  switch (cmd) {
16602  case CLI_INIT:
16603  e->command = "dahdi set dnd";
16604  e->usage =
16605  "Usage: dahdi set dnd <chan#> <on|off>\n"
16606  " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
16607  " Changes take effect immediately.\n"
16608  " <chan num> is the channel number\n"
16609  " <on|off> Enable or disable DND mode?\n"
16610  ;
16611  return NULL;
16612  case CLI_GENERATE:
16613  return NULL;
16614  }
16615 
16616  if (a->argc != 5)
16617  return CLI_SHOWUSAGE;
16618 
16619  if ((channel = atoi(a->argv[3])) <= 0) {
16620  ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16621  return CLI_SHOWUSAGE;
16622  }
16623 
16624  if (ast_true(a->argv[4]))
16625  on = 1;
16626  else if (ast_false(a->argv[4]))
16627  on = 0;
16628  else {
16629  ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
16630  return CLI_SHOWUSAGE;
16631  }
16632 
16633  ast_mutex_lock(&iflock);
16634  for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16635  if (dahdi_chan->channel != channel)
16636  continue;
16637 
16638  /* Found the channel. Actually set it */
16639  dahdi_dnd(dahdi_chan, on);
16640  break;
16641  }
16642  ast_mutex_unlock(&iflock);
16643 
16644  if (!dahdi_chan) {
16645  ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16646  return CLI_FAILURE;
16647  }
16648 
16649  return CLI_SUCCESS;
16650 }
16651 
16652 static char *dahdi_set_mwi(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16653 {
16654  int channel;
16655  int on;
16656  int override = 1;
16657  struct dahdi_pvt *dahdi_chan = NULL;
16658 
16659  switch (cmd) {
16660  case CLI_INIT:
16661  e->command = "dahdi set mwi";
16662  e->usage =
16663  "Usage: dahdi set mwi <chan#> <on|off|reset>\n"
16664  " Sets/unsets MWI (Message Waiting Indicator) manually on a channel.\n"
16665  " This may be used regardless of whether the channel is assigned any mailboxes.\n"
16666  " When active, this setting will override the voicemail status to set MWI.\n"
16667  " Once cleared, the voicemail status will resume control of MWI.\n"
16668  " Changes are queued for when the channel is idle and persist until cleared.\n"
16669  " <chan num> is the channel number\n"
16670  " <on|off|reset> Enable, disable, or reset Message Waiting Indicator override?\n"
16671  ;
16672  return NULL;
16673  case CLI_GENERATE:
16674  return NULL;
16675  }
16676 
16677  if (a->argc != 5)
16678  return CLI_SHOWUSAGE;
16679 
16680  if ((channel = atoi(a->argv[3])) <= 0) {
16681  ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16682  return CLI_SHOWUSAGE;
16683  }
16684 
16685  if (ast_true(a->argv[4])) {
16686  on = 1;
16687  } else if (ast_false(a->argv[4])) {
16688  on = 0;
16689  } else if (!strcmp(a->argv[4], "reset")) {
16690  override = 0;
16691  } else {
16692  ast_cli(a->fd, "Expected 'on' or 'off' or 'reset', got '%s'\n", a->argv[4]);
16693  return CLI_SHOWUSAGE;
16694  }
16695 
16696  ast_mutex_lock(&iflock);
16697  for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16698  if (dahdi_chan->channel != channel)
16699  continue;
16700 
16701  /* Found the channel. Actually set it */
16702  if (override) {
16703  dahdi_chan->mwioverride_disposition = on;
16704  ast_cli(a->fd, "MWI '%s' queued for channel %d\n", on ? "enable" : "disable", channel);
16705  }
16706  dahdi_chan->mwioverride_active = override;
16707  /* The do_monitor thread will take care of actually sending the MWI
16708  * at an appropriate time for the channel. */
16709  break;
16710  }
16711  ast_mutex_unlock(&iflock);
16712 
16713  if (!dahdi_chan) {
16714  ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16715  return CLI_FAILURE;
16716  }
16717 
16718  return CLI_SUCCESS;
16719 }
16720 
16721 static struct ast_cli_entry dahdi_cli[] = {
16722  AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
16723  AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
16724  AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
16725  AST_CLI_DEFINE(dahdi_destroy_channels, "Destroy channels"),
16726  AST_CLI_DEFINE(dahdi_create_channels, "Create channels"),
16727  AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
16728  AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
16729  AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
16730  AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
16731  AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
16732  AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
16733  AST_CLI_DEFINE(dahdi_set_mwi, "Sets/unsets MWI (Message Waiting Indicator) manually on a channel"),
16734 };
16735 
16736 #define TRANSFER 0
16737 #define HANGUP 1
16738 
16739 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
16740 {
16741  if (p) {
16742  switch (mode) {
16743  case TRANSFER:
16744  p->fake_event = DAHDI_EVENT_WINKFLASH;
16745  break;
16746  case HANGUP:
16747  p->fake_event = DAHDI_EVENT_ONHOOK;
16748  break;
16749  default:
16750  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));
16751  }
16752  }
16753  return 0;
16754 }
16755 static struct dahdi_pvt *find_channel(int channel)
16756 {
16757  struct dahdi_pvt *p;
16758 
16759  ast_mutex_lock(&iflock);
16760  for (p = iflist; p; p = p->next) {
16761  if (p->channel == channel) {
16762  break;
16763  }
16764  }
16765  ast_mutex_unlock(&iflock);
16766  return p;
16767 }
16768 
16769 /*!
16770  * \internal
16771  * \brief Get private struct using given numeric channel string.
16772  *
16773  * \param channel Numeric channel number string get private struct.
16774  *
16775  * \retval pvt on success.
16776  * \retval NULL on error.
16777  */
16778 static struct dahdi_pvt *find_channel_from_str(const char *channel)
16779 {
16780  int chan_num;
16781 
16782  if (sscanf(channel, "%30d", &chan_num) != 1) {
16783  /* Not numeric string. */
16784  return NULL;
16785  }
16786 
16787  return find_channel(chan_num);
16788 }
16789 
16790 static int action_dahdidndon(struct mansession *s, const struct message *m)
16791 {
16792  struct dahdi_pvt *p;
16793  const char *channel = astman_get_header(m, "DAHDIChannel");
16794 
16795  if (ast_strlen_zero(channel)) {
16796  astman_send_error(s, m, "No channel specified");
16797  return 0;
16798  }
16799  p = find_channel_from_str(channel);
16800  if (!p) {
16801  astman_send_error(s, m, "No such channel");
16802  return 0;
16803  }
16804  dahdi_dnd(p, 1);
16805  astman_send_ack(s, m, "DND Enabled");
16806  return 0;
16807 }
16808 
16809 static int action_dahdidndoff(struct mansession *s, const struct message *m)
16810 {
16811  struct dahdi_pvt *p;
16812  const char *channel = astman_get_header(m, "DAHDIChannel");
16813 
16814  if (ast_strlen_zero(channel)) {
16815  astman_send_error(s, m, "No channel specified");
16816  return 0;
16817  }
16818  p = find_channel_from_str(channel);
16819  if (!p) {
16820  astman_send_error(s, m, "No such channel");
16821  return 0;
16822  }
16823  dahdi_dnd(p, 0);
16824  astman_send_ack(s, m, "DND Disabled");
16825  return 0;
16826 }
16827 
16828 static int action_transfer(struct mansession *s, const struct message *m)
16829 {
16830  struct dahdi_pvt *p;
16831  const char *channel = astman_get_header(m, "DAHDIChannel");
16832 
16833  if (ast_strlen_zero(channel)) {
16834  astman_send_error(s, m, "No channel specified");
16835  return 0;
16836  }
16837  p = find_channel_from_str(channel);
16838  if (!p) {
16839  astman_send_error(s, m, "No such channel");
16840  return 0;
16841  }
16842  if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16843  astman_send_error(s, m, "Channel signaling is not analog");
16844  return 0;
16845  }
16846  dahdi_fake_event(p,TRANSFER);
16847  astman_send_ack(s, m, "DAHDITransfer");
16848  return 0;
16849 }
16850 
16851 static int action_transferhangup(struct mansession *s, const struct message *m)
16852 {
16853  struct dahdi_pvt *p;
16854  const char *channel = astman_get_header(m, "DAHDIChannel");
16855 
16856  if (ast_strlen_zero(channel)) {
16857  astman_send_error(s, m, "No channel specified");
16858  return 0;
16859  }
16860  p = find_channel_from_str(channel);
16861  if (!p) {
16862  astman_send_error(s, m, "No such channel");
16863  return 0;
16864  }
16865  if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16866  astman_send_error(s, m, "Channel signaling is not analog");
16867  return 0;
16868  }
16869  dahdi_fake_event(p,HANGUP);
16870  astman_send_ack(s, m, "DAHDIHangup");
16871  return 0;
16872 }
16873 
16874 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16875 {
16876  struct dahdi_pvt *p;
16877  const char *channel = astman_get_header(m, "DAHDIChannel");
16878  const char *number = astman_get_header(m, "Number");
16879  int i;
16880 
16881  if (ast_strlen_zero(channel)) {
16882  astman_send_error(s, m, "No channel specified");
16883  return 0;
16884  }
16885  if (ast_strlen_zero(number)) {
16886  astman_send_error(s, m, "No number specified");
16887  return 0;
16888  }
16889  p = find_channel_from_str(channel);
16890  if (!p) {
16891  astman_send_error(s, m, "No such channel");
16892  return 0;
16893  }
16894  if (!p->owner) {
16895  astman_send_error(s, m, "Channel does not have it's owner");
16896  return 0;
16897  }
16898  for (i = 0; i < strlen(number); i++) {
16899  struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16900  dahdi_queue_frame(p, &f);
16901  }
16902  astman_send_ack(s, m, "DAHDIDialOffhook");
16903  return 0;
16904 }
16905 
16906 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16907 {
16908  struct dahdi_pvt *tmp = NULL;
16909  const char *id = astman_get_header(m, "ActionID");
16910  const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16911  char idText[256];
16912  int channels = 0;
16913  int dahdichanquery;
16914 
16915  if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16916  /* Not numeric string. */
16917  dahdichanquery = -1;
16918  }
16919 
16920  idText[0] = '\0';
16921  if (!ast_strlen_zero(id)) {
16922  snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16923  }
16924 
16925  astman_send_listack(s, m, "DAHDI channel status will follow", "start");
16926 
16927  ast_mutex_lock(&iflock);
16928 
16929  for (tmp = iflist; tmp; tmp = tmp->next) {
16930  if (tmp->channel > 0) {
16931  int alm;
16932 
16933  /* If a specific channel is queried for, only deliver status for that channel */
16934  if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16935  continue;
16936 
16937  alm = get_alarms(tmp);
16938  channels++;
16939  if (tmp->owner) {
16940  /* Add data if we have a current call */
16941  astman_append(s,
16942  "Event: DAHDIShowChannels\r\n"
16943  "DAHDIChannel: %d\r\n"
16944  "Channel: %s\r\n"
16945  "Uniqueid: %s\r\n"
16946  "AccountCode: %s\r\n"
16947  "Signalling: %s\r\n"
16948  "SignallingCode: %d\r\n"
16949  "Context: %s\r\n"
16950  "DND: %s\r\n"
16951  "Alarm: %s\r\n"
16952  "Description: %s\r\n"
16953  "%s"
16954  "\r\n",
16955  tmp->channel,
16956  ast_channel_name(tmp->owner),
16957  ast_channel_uniqueid(tmp->owner),
16958  ast_channel_accountcode(tmp->owner),
16959  sig2str(tmp->sig),
16960  tmp->sig,
16961  tmp->context,
16962  dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16963  alarm2str(alm),
16964  tmp->description, idText);
16965  } else {
16966  astman_append(s,
16967  "Event: DAHDIShowChannels\r\n"
16968  "DAHDIChannel: %d\r\n"
16969  "Signalling: %s\r\n"
16970  "SignallingCode: %d\r\n"
16971  "Context: %s\r\n"
16972  "DND: %s\r\n"
16973  "Alarm: %s\r\n"
16974  "Description: %s\r\n"
16975  "%s"
16976  "\r\n",
16977  tmp->channel, sig2str(tmp->sig), tmp->sig,
16978  tmp->context,
16979  dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16980  alarm2str(alm),
16981  tmp->description, idText);
16982  }
16983  }
16984  }
16985 
16986  ast_mutex_unlock(&iflock);
16987 
16988  astman_send_list_complete_start(s, m, "DAHDIShowChannelsComplete", channels);
16989  astman_append(s, "Items: %d\r\n", channels);
16991  return 0;
16992 }
16993 
16994 static int action_dahdishowstatus(struct mansession *s, const struct message *m)
16995 {
16996  const char *id = astman_get_header(m, "ActionID");
16997  int span;
16998  int res;
16999  char alarmstr[50];
17000  int ctl;
17001  char idText[256];
17002  int numspans = 0;
17003  struct dahdi_spaninfo spaninfo;
17004 
17005  ctl = open("/dev/dahdi/ctl", O_RDWR);
17006  if (ctl < 0) {
17007  astman_send_error(s, m, "No DAHDI detected");
17008  return 0;
17009  }
17010 
17011  idText[0] = '\0';
17012  if (!ast_strlen_zero(id)) {
17013  snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
17014  }
17015  astman_send_listack(s, m, "DAHDI span statuses will follow", "start");
17016 
17017  for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
17018  spaninfo.spanno = span;
17019  res = ioctl(ctl, DAHDI_SPANSTAT, &spaninfo);
17020  if (res) {
17021  continue;
17022  }
17023  numspans++;
17024  build_alarm_info(alarmstr, &spaninfo);
17025  astman_append(s,
17026  "Event: DAHDIShowStatus\r\n"
17027  "Span: %d\r\n"
17028  "Description: %s\r\n"
17029  "Alarms: %s\r\n"
17030  "IRQ: %d\r\n"
17031  "bpviol: %d\r\n"
17032  "CRC: %d\r\n"
17033  "Framing: %s\r\n"
17034  "Coding: %s\r\n"
17035  "Options: %s\r\n"
17036  "LBO: %s\r\n"
17037  "%s"
17038  "\r\n",
17039  span, spaninfo.desc, alarmstr, spaninfo.irqmisses, spaninfo.bpvcount, spaninfo.crc4count,
17040  spaninfo.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
17041  spaninfo.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
17042  spaninfo.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
17043  "CAS",
17044  spaninfo.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
17045  spaninfo.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
17046  spaninfo.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
17047  "Unk",
17048  spaninfo.lineconfig & DAHDI_CONFIG_CRC4 ?
17049  spaninfo.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
17050  spaninfo.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
17051  lbostr[spaninfo.lbo],
17052  idText);
17053  }
17054  close(ctl);
17055 
17056  astman_send_list_complete_start(s, m, "DAHDIShowStatusComplete", numspans);
17057  astman_append(s, "Items: %d\r\n", numspans);
17059  return 0;
17060 }
17061 
17062 #if defined(HAVE_PRI)
17063 static int action_prishowspans(struct mansession *s, const struct message *m)
17064 {
17065  int count;
17066  int idx;
17067  int span_query;
17068  struct dahdi_pri *dspan;
17069  const char *id = astman_get_header(m, "ActionID");
17070  const char *span_str = astman_get_header(m, "Span");
17071  char action_id[256];
17072  const char *show_cmd = "PRIShowSpans";
17073 
17074  /* NOTE: Asking for span 0 gets all spans. */
17075  if (!ast_strlen_zero(span_str)) {
17076  span_query = atoi(span_str);
17077  } else {
17078  span_query = 0;
17079  }
17080 
17081  if (!ast_strlen_zero(id)) {
17082  snprintf(action_id, sizeof(action_id), "ActionID: %s\r\n", id);
17083  } else {
17084  action_id[0] = '\0';
17085  }
17086 
17087  astman_send_listack(s, m, "Span status will follow", "start");
17088 
17089  count = 0;
17090  for (idx = 0; idx < ARRAY_LEN(pris); ++idx) {
17091  dspan = &pris[idx];
17092 
17093  /* If a specific span is asked for, only deliver status for that span. */
17094  if (0 < span_query && dspan->pri.span != span_query) {
17095  continue;
17096  }
17097 
17098  if (dspan->pri.pri) {
17099  count += sig_pri_ami_show_spans(s, show_cmd, &dspan->pri, dspan->dchannels,
17100  action_id);
17101  }
17102  }
17103 
17104  astman_send_list_complete_start(s, m, "PRIShowSpansComplete", count);
17105  astman_append(s, "Items: %d\r\n", count);
17107  return 0;
17108 }
17109 #endif /* defined(HAVE_PRI) */
17110 
17111 #if defined(HAVE_SS7)
17112 static int linkset_addsigchan(int sigchan)
17113 {
17114  struct dahdi_ss7 *link;
17115  int res;
17116  int curfd;
17117  struct dahdi_params params;
17118  struct dahdi_bufferinfo bi;
17119  struct dahdi_spaninfo si;
17120 
17121  if (sigchan < 0) {
17122  ast_log(LOG_ERROR, "Invalid sigchan!\n");
17123  return -1;
17124  }
17125  if (cur_ss7type < 0) {
17126  ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
17127  return -1;
17128  }
17129  if (cur_pointcode < 0) {
17130  ast_log(LOG_ERROR, "Unspecified pointcode!\n");
17131  return -1;
17132  }
17133  if (cur_adjpointcode < 0) {
17134  ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
17135  return -1;
17136  }
17137  if (cur_defaultdpc < 0) {
17138  ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
17139  return -1;
17140  }
17141  if (cur_networkindicator < 0) {
17142  ast_log(LOG_ERROR, "Invalid networkindicator!\n");
17143  return -1;
17144  }
17145  link = ss7_resolve_linkset(cur_linkset);
17146  if (!link) {
17147  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
17148  return -1;
17149  }
17150  if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
17151  ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
17152  return -1;
17153  }
17154 
17155  curfd = link->ss7.numsigchans;
17156 
17157  /* Open signaling channel */
17158  link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
17159  if (link->ss7.fds[curfd] < 0) {
17160  ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
17161  strerror(errno));
17162  return -1;
17163  }
17164  if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
17165  dahdi_close_ss7_fd(link, curfd);
17166  ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
17167  strerror(errno));
17168  return -1;
17169  }
17170 
17171  /* Get signaling channel parameters */
17172  memset(&params, 0, sizeof(params));
17173  res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
17174  if (res) {
17175  dahdi_close_ss7_fd(link, curfd);
17176  ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
17177  strerror(errno));
17178  return -1;
17179  }
17180  if (params.sigtype != DAHDI_SIG_HDLCFCS
17181  && params.sigtype != DAHDI_SIG_HARDHDLC
17182  && params.sigtype != DAHDI_SIG_MTP2) {
17183  dahdi_close_ss7_fd(link, curfd);
17184  ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
17185  return -1;
17186  }
17187 
17188  /* Set signaling channel buffer policy. */
17189  memset(&bi, 0, sizeof(bi));
17190  bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
17191  bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
17192  bi.numbufs = 32;
17193  bi.bufsize = 512;
17194  if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
17195  ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
17196  sigchan, strerror(errno));
17197  dahdi_close_ss7_fd(link, curfd);
17198  return -1;
17199  }
17200 
17201  /* Get current signaling channel alarm status. */
17202  memset(&si, 0, sizeof(si));
17203  res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
17204  if (res) {
17205  dahdi_close_ss7_fd(link, curfd);
17206  ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
17207  strerror(errno));
17208  }
17209 
17210  res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
17211  (params.sigtype == DAHDI_SIG_MTP2)
17212  ? SS7_TRANSPORT_DAHDIMTP2
17213  : SS7_TRANSPORT_DAHDIDCHAN,
17214  si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode, cur_slc);
17215  if (res) {
17216  dahdi_close_ss7_fd(link, curfd);
17217  return -1;
17218  }
17219 
17220  ++link->ss7.numsigchans;
17221 
17222  return 0;
17223 }
17224 #endif /* defined(HAVE_SS7) */
17225 
17226 #if defined(HAVE_SS7)
17227 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17228 {
17229  int span;
17230  switch (cmd) {
17231  case CLI_INIT:
17232  e->command = "ss7 set debug {on|off} linkset";
17233  e->usage =
17234  "Usage: ss7 set debug {on|off} linkset <linkset>\n"
17235  " Enables debugging on a given SS7 linkset\n";
17236  return NULL;
17237  case CLI_GENERATE:
17238  return NULL;
17239  }
17240 
17241  if (a->argc < 6) {
17242  return CLI_SHOWUSAGE;
17243  }
17244 
17245  span = atoi(a->argv[5]);
17246  if ((span < 1) || (span > NUM_SPANS)) {
17247  ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
17248  return CLI_SUCCESS;
17249  }
17250  if (!linksets[span-1].ss7.ss7) {
17251  ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
17252  } else {
17253  if (!strcasecmp(a->argv[3], "on")) {
17254  linksets[span - 1].ss7.debug = 1;
17255  ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
17256  ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
17257  } else {
17258  linksets[span - 1].ss7.debug = 0;
17259  ss7_set_debug(linksets[span-1].ss7.ss7, 0);
17260  ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
17261  }
17262  }
17263 
17264  return CLI_SUCCESS;
17265 }
17266 #endif /* defined(HAVE_SS7) */
17267 
17268 #if defined(HAVE_SS7)
17269 static char *handle_ss7_cic_blocking(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17270 {
17271  int linkset, cic;
17272  int blocked, i;
17273  int do_block = 0;
17274  unsigned int dpc;
17275 
17276  switch (cmd) {
17277  case CLI_INIT:
17278  e->command = "ss7 {block|unblock} cic";
17279  e->usage =
17280  "Usage: ss7 {block|unblock} cic <linkset> <dpc> <CIC>\n"
17281  " Sends a remote {blocking|unblocking} request for the given CIC on the specified linkset\n";
17282  return NULL;
17283  case CLI_GENERATE:
17284  return NULL;
17285  }
17286 
17287  if (a->argc == 6) {
17288  linkset = atoi(a->argv[3]);
17289  } else {
17290  return CLI_SHOWUSAGE;
17291  }
17292 
17293  if (!strcasecmp(a->argv[1], "block")) {
17294  do_block = 1;
17295  } else if (strcasecmp(a->argv[1], "unblock")) {
17296  return CLI_SHOWUSAGE;
17297  }
17298 
17299  if ((linkset < 1) || (linkset > NUM_SPANS)) {
17300  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17301  return CLI_SUCCESS;
17302  }
17303 
17304  if (!linksets[linkset-1].ss7.ss7) {
17305  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17306  return CLI_SUCCESS;
17307  }
17308 
17309  cic = atoi(a->argv[5]);
17310  if (cic < 1) {
17311  ast_cli(a->fd, "Invalid CIC specified!\n");
17312  return CLI_SUCCESS;
17313  }
17314 
17315  dpc = atoi(a->argv[4]);
17316  if (dpc < 1) {
17317  ast_cli(a->fd, "Invalid DPC specified!\n");
17318  return CLI_SUCCESS;
17319  }
17320 
17321  for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
17322  if (linksets[linkset-1].ss7.pvts[i] && linksets[linkset-1].ss7.pvts[i]->cic == cic && linksets[linkset-1].ss7.pvts[i]->dpc == dpc) {
17323  blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
17324  if (!do_block ^ !(blocked & SS7_BLOCKED_MAINTENANCE)) {
17325  if (sig_ss7_cic_blocking(&linksets[linkset-1].ss7, do_block, i) < 0) {
17326  ast_cli(a->fd, "Unable to allocate new ss7call\n");
17327  } else {
17328  ast_cli(a->fd, "Sent %sblocking request for linkset %d on CIC %d DPC %d\n", (do_block) ? "" : "un", linkset, cic, dpc);
17329  }
17330  } else if (!do_block && blocked) {
17331  ast_cli(a->fd, "CIC %d is hardware locally blocked!\n", cic);
17332  } else {
17333  ast_cli(a->fd, "CIC %d %s locally blocked\n", cic, do_block ? "already" : "is not");
17334  }
17335  return CLI_SUCCESS;
17336  }
17337  }
17338 
17339  ast_cli(a->fd, "Invalid CIC specified!\n");
17340  return CLI_SUCCESS;
17341 }
17342 #endif /* defined(HAVE_SS7) */
17343 
17344 #if defined(HAVE_SS7)
17345 static char *handle_ss7_linkset_mng(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17346 {
17347  int linkset, i;
17348  enum {
17349  DO_BLOCK,
17350  DO_UNBLOCK,
17351  DO_RESET,
17352  } do_what;
17353 
17354  switch (cmd) {
17355  case CLI_INIT:
17356  e->command = "ss7 {reset|block|unblock} linkset";
17357  e->usage =
17358  "Usage: ss7 {reset|block|unblock} linkset <linkset number>\n"
17359  " Sends a remote {reset|blocking|unblocking} request for all CICs on the given linkset\n";
17360  return NULL;
17361  case CLI_GENERATE:
17362  return NULL;
17363  }
17364 
17365  if (a->argc == 4) {
17366  linkset = atoi(a->argv[3]);
17367  } else {
17368  return CLI_SHOWUSAGE;
17369  }
17370 
17371  if (!strcasecmp(a->argv[1], "block")) {
17372  do_what = DO_BLOCK;
17373  } else if (!strcasecmp(a->argv[1], "unblock")) {
17374  do_what = DO_UNBLOCK;
17375  } else if (!strcasecmp(a->argv[1], "reset")) {
17376  do_what = DO_RESET;
17377  } else {
17378  return CLI_SHOWUSAGE;
17379  }
17380 
17381  if ((linkset < 1) || (linkset > NUM_SPANS)) {
17382  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17383  return CLI_SUCCESS;
17384  }
17385 
17386  if (!linksets[linkset - 1].ss7.ss7) {
17387  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17388  return CLI_SUCCESS;
17389  }
17390 
17391  for (i = 0; i < linksets[linkset - 1].ss7.numchans; i++) {
17392  /* XXX Should be done with GRS/CGB/CGU instead - see ss7_reset_linkset() */
17393  if (linksets[linkset - 1].ss7.pvts[i]) {
17394  switch (do_what) {
17395  case DO_BLOCK:
17396  case DO_UNBLOCK:
17397  if (sig_ss7_cic_blocking(&linksets[linkset - 1].ss7, do_what == DO_BLOCK, i)) {
17398  ast_cli(a->fd, "Sent remote %s request on CIC %d\n",
17399  (do_what == DO_BLOCK) ? "blocking" : "unblocking",
17400  linksets[linkset - 1].ss7.pvts[i]->cic);
17401  }
17402  break;
17403  case DO_RESET:
17404  if (sig_ss7_reset_cic(&linksets[linkset - 1].ss7,
17405  linksets[linkset - 1].ss7.pvts[i]->cic,
17406  linksets[linkset - 1].ss7.pvts[i]->dpc)) {
17407  ast_cli(a->fd, "Sent reset request on CIC %d\n",
17408  linksets[linkset - 1].ss7.pvts[i]->cic);
17409  }
17410  break;
17411  }
17412  }
17413  }
17414 
17415  return CLI_SUCCESS;
17416 }
17417 #endif /* defined(HAVE_SS7) */
17418 
17419 #if defined(HAVE_SS7)
17420 static char *handle_ss7_group_blocking(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17421 {
17422  int linkset, cic, range, chanpos;
17423  int i, dpc, orient = 0;
17424  int do_block = 0;
17425  unsigned char state[255];
17426 
17427  switch (cmd) {
17428  case CLI_INIT:
17429  e->command = "ss7 {block|unblock} group";
17430  e->usage =
17431  "Usage: ss7 {block|unblock} group <linkset> <dpc> <1st. CIC> <range> [H]\n"
17432  " Sends a remote {blocking|unblocking} request for CIC range on the specified linkset\n";
17433  return NULL;
17434  case CLI_GENERATE:
17435  return NULL;
17436  }
17437 
17438  if (a->argc == 7 || a->argc == 8) {
17439  linkset = atoi(a->argv[3]);
17440  } else {
17441  return CLI_SHOWUSAGE;
17442  }
17443 
17444  if (!strcasecmp(a->argv[1], "block")) {
17445  do_block = 1;
17446  } else if (strcasecmp(a->argv[1], "unblock")) {
17447  return CLI_SHOWUSAGE;
17448  }
17449 
17450  if (a->argc == 8) {
17451  if (!strcasecmp(a->argv[7], "H")) {
17452  orient = 1;
17453  } else {
17454  return CLI_SHOWUSAGE;
17455  }
17456  }
17457 
17458  if ((linkset < 1) || (linkset > NUM_SPANS)) {
17459  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
17460  return CLI_SUCCESS;
17461  }
17462 
17463  if (!linksets[linkset-1].ss7.ss7) {
17464  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17465  return CLI_SUCCESS;
17466  }
17467 
17468  cic = atoi(a->argv[5]);
17469  if (cic < 1) {
17470  ast_cli(a->fd, "Invalid CIC specified!\n");
17471  return CLI_SUCCESS;
17472  }
17473 
17474  range = atoi(a->argv[6]);
17475  /* ITU-T Q.763 3.43 - range 0 is reserved, which makes a range of 2 CICs a minimum group */
17476  if (range < 1 || range > (linksets[linkset - 1].ss7.type == SS7_ANSI ? 24 : 31)) {
17477  ast_cli(a->fd, "Invalid range specified!\n");
17478  return CLI_SUCCESS;
17479  }
17480 
17481  dpc = atoi(a->argv[4]);
17482  if (dpc < 1) {
17483  ast_cli(a->fd, "Invalid DPC specified!\n");
17484  return CLI_SUCCESS;
17485  }
17486 
17487  ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17488  if (!sig_ss7_find_cic_range(&linksets[linkset-1].ss7, cic, cic + range, dpc)) {
17489  ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17490  ast_cli(a->fd, "Invalid CIC/RANGE\n");
17491  return CLI_SHOWUSAGE;
17492  }
17493 
17494  memset(state, 0, sizeof(state));
17495  for (i = 0; i <= range; ++i) {
17496  state[i] = 1;
17497  }
17498 
17499  /* We are guaranteed to find chanpos because of sig_ss7_find_cic_range() includes it. */
17500  chanpos = sig_ss7_find_cic(&linksets[linkset-1].ss7, cic, dpc);
17501  if (sig_ss7_group_blocking(&linksets[linkset-1].ss7, do_block, chanpos, cic + range, state, orient)) {
17502  ast_cli(a->fd, "Unable allocate new ss7call\n");
17503  } else {
17504  ast_cli(a->fd, "Sending remote%s %sblocking request linkset %d on CIC %d range %d\n",
17505  orient ? " hardware" : "", do_block ? "" : "un", linkset, cic, range);
17506  }
17507 
17508  ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17509 
17510  /* Break poll on the linkset so it sends our messages */
17511  if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17512  pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17513  }
17514  return CLI_SUCCESS;
17515 }
17516 #endif /* defined(HAVE_SS7) */
17517 
17518 #if defined(HAVE_SS7)
17519 static char *handle_ss7_group_reset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17520 {
17521  int linkset, cic, range;
17522  unsigned int dpc;
17523 
17524  switch (cmd) {
17525  case CLI_INIT:
17526  e->command = "ss7 reset group";
17527  e->usage =
17528  "Usage: ss7 reset group <linkset> <dpc> <1st CIC> <range>\n"
17529  " Send a GRS for the given CIC range on the specified linkset\n";
17530  return NULL;
17531  case CLI_GENERATE:
17532  return NULL;
17533  }
17534 
17535  if (a->argc == 7) {
17536  linkset = atoi(a->argv[3]);
17537  } else {
17538  return CLI_SHOWUSAGE;
17539  }
17540 
17541  if ((linkset < 1) || (linkset > NUM_SPANS)) {
17542  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
17543  return CLI_SUCCESS;
17544  }
17545 
17546  if (!linksets[linkset-1].ss7.ss7) {
17547  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17548  return CLI_SUCCESS;
17549  }
17550 
17551  cic = atoi(a->argv[5]);
17552 
17553  if (cic < 1) {
17554  ast_cli(a->fd, "Invalid CIC specified!\n");
17555  return CLI_SUCCESS;
17556  }
17557 
17558  range = atoi(a->argv[6]);
17559  if (range < 1 || range > (linksets[linkset - 1].ss7.type == SS7_ANSI ? 24 : 31)) {
17560  ast_cli(a->fd, "Invalid range specified!\n");
17561  return CLI_SUCCESS;
17562  }
17563 
17564  dpc = atoi(a->argv[4]);
17565  if (dpc < 1) {
17566  ast_cli(a->fd, "Invalid DPC specified!\n");
17567  return CLI_SUCCESS;
17568  }
17569 
17570  ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17571  if (!sig_ss7_find_cic_range(&linksets[linkset-1].ss7, cic, cic + range, dpc)) {
17572  ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17573  ast_cli(a->fd, "Invalid CIC/RANGE\n");
17574  return CLI_SHOWUSAGE;
17575  }
17576 
17577  if (sig_ss7_reset_group(&linksets[linkset-1].ss7, cic, dpc, range)) {
17578  ast_cli(a->fd, "Unable to allocate new ss7call\n");
17579  } else {
17580  ast_cli(a->fd, "GRS sent ... \n");
17581  }
17582 
17583  ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17584 
17585  /* Break poll on the linkset so it sends our messages */
17586  if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17587  pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17588  }
17589  return CLI_SUCCESS;
17590 }
17591 #endif /* defined(HAVE_SS7) */
17592 
17593 #if defined(HAVE_SS7)
17594 static char *handle_ss7_show_calls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17595 {
17596  int linkset;
17597 
17598  switch (cmd) {
17599  case CLI_INIT:
17600  e->command = "ss7 show calls";
17601  e->usage =
17602  "Usage: ss7 show calls <linkset>\n"
17603  " Show SS7 calls on the specified linkset\n";
17604  return NULL;
17605  case CLI_GENERATE:
17606  return NULL;
17607  }
17608 
17609  if (a->argc == 4) {
17610  linkset = atoi(a->argv[3]);
17611  } else {
17612  return CLI_SHOWUSAGE;
17613  }
17614 
17615  if ((linkset < 1) || (linkset > NUM_SPANS)) {
17616  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17617  return CLI_SUCCESS;
17618  }
17619 
17620  if (!linksets[linkset-1].ss7.ss7) {
17621  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17622  return CLI_SUCCESS;
17623  }
17624 
17625  ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17626  isup_show_calls(linksets[linkset-1].ss7.ss7, &ast_cli, a->fd);
17627  ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17628 
17629  return CLI_SUCCESS;
17630 }
17631 #endif /* defined(HAVE_SS7) */
17632 
17633 #if defined(HAVE_SS7)
17634 static char *handle_ss7_reset_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17635 {
17636  int linkset, cic, res;
17637  unsigned int dpc;
17638 
17639  switch (cmd) {
17640  case CLI_INIT:
17641  e->command = "ss7 reset cic";
17642  e->usage =
17643  "Usage: ss7 reset cic <linkset> <dpc> <CIC>\n"
17644  " Send a RSC for the given CIC on the specified linkset\n";
17645  return NULL;
17646  case CLI_GENERATE:
17647  return NULL;
17648  }
17649 
17650  if (a->argc == 6) {
17651  linkset = atoi(a->argv[3]);
17652  } else {
17653  return CLI_SHOWUSAGE;
17654  }
17655 
17656  if ((linkset < 1) || (linkset > NUM_SPANS)) {
17657  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17658  return CLI_SUCCESS;
17659  }
17660 
17661  if (!linksets[linkset-1].ss7.ss7) {
17662  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17663  return CLI_SUCCESS;
17664  }
17665 
17666  cic = atoi(a->argv[5]);
17667 
17668  if (cic < 1) {
17669  ast_cli(a->fd, "Invalid CIC specified!\n");
17670  return CLI_SUCCESS;
17671  }
17672 
17673  dpc = atoi(a->argv[4]);
17674  if (dpc < 1) {
17675  ast_cli(a->fd, "Invalid DPC specified!\n");
17676  return CLI_SUCCESS;
17677  }
17678 
17679  res = sig_ss7_reset_cic(&linksets[linkset-1].ss7, cic, dpc);
17680 
17681  ast_cli(a->fd, "%s RSC for linkset %d on CIC %d DPC %d\n", res ? "Sent" : "Failed", linkset, cic, dpc);
17682 
17683  return CLI_SUCCESS;
17684 }
17685 #endif /* defined(HAVE_SS7) */
17686 
17687 #if defined(HAVE_SS7)
17688 static char *handle_ss7_net_mng(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17689 {
17690  int linkset;
17691  unsigned int slc;
17692  unsigned int arg = 0;
17693  const char *res;
17694 
17695  switch (cmd) {
17696  case CLI_INIT:
17697  e->command = "ss7 mtp3";
17698  e->usage =
17699  "Usage: ss7 mtp3 <linkset> <slc> coo|coa|cbd|cba|eco|eca|tfp|tfa|lin|lun|lia|lua|lid|lfu <arg>\n"
17700  " Send a NET MNG message\n"
17701  " WARNING!!! WARNING!!! We are not a STP, just for testing/development purposes\n";
17702  return NULL;
17703  case CLI_GENERATE:
17704  return NULL;
17705  }
17706 
17707  if (a->argc < 5) {
17708  return CLI_SHOWUSAGE;
17709  }
17710 
17711  linkset = atoi(a->argv[2]);
17712  if ((linkset < 1) || (linkset > NUM_SPANS)) {
17713  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[2], 1, NUM_SPANS);
17714  return CLI_SUCCESS;
17715  }
17716  if (!linksets[linkset-1].ss7.ss7) {
17717  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17718  return CLI_SUCCESS;
17719  }
17720 
17721  slc = atoi(a->argv[3]);
17722 
17723  if (a->argc == 6) {
17724  arg = atoi(a->argv[5]);
17725  }
17726 
17727  ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17728  res = mtp3_net_mng(linksets[linkset-1].ss7.ss7, slc, a->argv[4], arg);
17729  ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17730 
17731  /* Break poll on the linkset so it sends our messages */
17732  if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17733  pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17734  }
17735 
17736  ast_cli(a->fd, "%s", res);
17737 
17738  return CLI_SUCCESS;
17739 }
17740 #endif /* defined(HAVE_SS7) */
17741 
17742 #if defined(HAVE_SS7)
17743 static char *handle_ss7_mtp3_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17744 {
17745  int linkset;
17746  unsigned int slc = 0;
17747 
17748  switch (cmd) {
17749  case CLI_INIT:
17750  e->command = "ss7 restart mtp3";
17751  e->usage =
17752  "Usage: ss7 restart mtp3 <linkset> <slc>\n"
17753  " Restart link\n";
17754  return NULL;
17755  case CLI_GENERATE:
17756  return NULL;
17757  }
17758 
17759  if (a->argc < 5) {
17760  return CLI_SHOWUSAGE;
17761  }
17762 
17763  linkset = atoi(a->argv[3]);
17764  if ((linkset < 1) || (linkset > NUM_SPANS)) {
17765  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[2], 1, NUM_SPANS);
17766  return CLI_SUCCESS;
17767  }
17768  if (!linksets[linkset-1].ss7.ss7) {
17769  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17770  return CLI_SUCCESS;
17771  }
17772 
17773  slc = atoi(a->argv[4]);
17774 
17775  ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17776  mtp3_init_restart(linksets[linkset-1].ss7.ss7, slc);
17777  ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17778 
17779  /* Break poll on the linkset so it sends our messages */
17780  if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17781  pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17782  }
17783 
17784  return CLI_SUCCESS;
17785 }
17786 #endif /* defined(HAVE_SS7) */
17787 
17788 #if defined(HAVE_SS7)
17789 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17790 {
17791  int linkset;
17792  struct sig_ss7_linkset *ss7;
17793  switch (cmd) {
17794  case CLI_INIT:
17795  e->command = "ss7 show linkset";
17796  e->usage =
17797  "Usage: ss7 show linkset <span>\n"
17798  " Shows the status of an SS7 linkset.\n";
17799  return NULL;
17800  case CLI_GENERATE:
17801  return NULL;
17802  }
17803 
17804  if (a->argc < 4) {
17805  return CLI_SHOWUSAGE;
17806  }
17807 
17808  linkset = atoi(a->argv[3]);
17809  if ((linkset < 1) || (linkset > NUM_SPANS)) {
17810  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17811  return CLI_SUCCESS;
17812  }
17813  ss7 = &linksets[linkset - 1].ss7;
17814  if (!ss7->ss7) {
17815  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17816  return CLI_SUCCESS;
17817  }
17818 
17819  ast_cli(a->fd, "SS7 flags: 0x%x\n", ss7->flags);
17820  ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
17821  ast_cli(a->fd, "SS7 calling nai: %i\n", ss7->calling_nai);
17822  ast_cli(a->fd, "SS7 called nai: %i\n", ss7->called_nai);
17823  ast_cli(a->fd, "SS7 nationalprefix: %s\n", ss7->nationalprefix);
17824  ast_cli(a->fd, "SS7 internationalprefix: %s\n", ss7->internationalprefix);
17825  ast_cli(a->fd, "SS7 unknownprefix: %s\n", ss7->unknownprefix);
17826  ast_cli(a->fd, "SS7 networkroutedprefix: %s\n", ss7->networkroutedprefix);
17827  ast_cli(a->fd, "SS7 subscriberprefix: %s\n", ss7->subscriberprefix);
17828  ss7_show_linkset(ss7->ss7, &ast_cli, a->fd);
17829 
17830  return CLI_SUCCESS;
17831 }
17832 #endif /* defined(HAVE_SS7) */
17833 
17834 #if defined(HAVE_SS7)
17835 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17836 {
17837  int linkset;
17838 
17839  switch (cmd) {
17840  case CLI_INIT:
17841  e->command = "ss7 show channels";
17842  e->usage =
17843  "Usage: ss7 show channels\n"
17844  " Displays SS7 channel information at a glance.\n";
17845  return NULL;
17846  case CLI_GENERATE:
17847  return NULL;
17848  }
17849 
17850  if (a->argc != 3) {
17851  return CLI_SHOWUSAGE;
17852  }
17853 
17854  sig_ss7_cli_show_channels_header(a->fd);
17855  for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
17856  if (linksets[linkset].ss7.ss7) {
17857  sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
17858  }
17859  }
17860  return CLI_SUCCESS;
17861 }
17862 #endif /* defined(HAVE_SS7) */
17863 
17864 #if defined(HAVE_SS7)
17865 static char *handle_ss7_show_cics(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17866 {
17867 #define FORMAT "%5s %5s %6s %12s %-12s\n"
17868 #define FORMAT2 "%5i %5i %6i %12s %-12s\n"
17869  int i, linkset, dpc = 0;
17870  struct sig_ss7_linkset *ss7;
17871  char *state;
17872  char blocking[12];
17873 
17874  switch (cmd) {
17875  case CLI_INIT:
17876  e->command = "ss7 show cics";
17877  e->usage =
17878  "Usage: ss7 show cics <linkset> [dpc]\n"
17879  " Shows the cics of an SS7 linkset.\n";
17880  return NULL;
17881  case CLI_GENERATE:
17882  return NULL;
17883  }
17884 
17885  if (a->argc < 4 || a->argc > 5) {
17886  return CLI_SHOWUSAGE;
17887  }
17888 
17889  linkset = atoi(a->argv[3]);
17890 
17891  if ((linkset < 1) || (linkset > NUM_SPANS)) {
17892  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17893  return CLI_SUCCESS;
17894  }
17895 
17896  if (!linksets[linkset-1].ss7.ss7) {
17897  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17898  return CLI_SUCCESS;
17899  }
17900  ss7 = &linksets[linkset-1].ss7;
17901 
17902  if (a->argc == 5) {
17903  dpc = atoi(a->argv[4]);
17904  if (dpc < 1) {
17905  ast_cli(a->fd, "Invalid DPC specified!\n");
17906  return CLI_SUCCESS;
17907  }
17908  }
17909 
17910  ast_cli(a->fd, FORMAT, "CIC", "DPC", "DAHDI", "STATE", "BLOCKING");
17911 
17912  for (i = 0; i < ss7->numchans; i++) {
17913  if (!dpc || (ss7->pvts[i] && ss7->pvts[i]->dpc == dpc)) {
17914  struct dahdi_pvt *p = ss7->pvts[i]->chan_pvt;
17915 
17916  if (ss7->pvts[i]->owner) {
17917  state = "Used";
17918  } else if (ss7->pvts[i]->ss7call) {
17919  state = "Pending";
17920  } else if (!p->inservice) {
17921  state = "NotInServ";
17922  } else {
17923  state = "Idle";
17924  }
17925 
17926  if (p->locallyblocked) {
17927  strcpy(blocking, "L:");
17928  if (p->locallyblocked & SS7_BLOCKED_MAINTENANCE) {
17929  strcat(blocking, "M");
17930  } else {
17931  strcat(blocking, " ");
17932  }
17933 
17934  if (p->locallyblocked & SS7_BLOCKED_HARDWARE) {
17935  strcat(blocking, "H");
17936  } else {
17937  strcat(blocking, " ");
17938  }
17939  } else {
17940  strcpy(blocking, " ");
17941  }
17942 
17943  if (p->remotelyblocked) {
17944  strcat(blocking, " R:");
17945  if (p->remotelyblocked & SS7_BLOCKED_MAINTENANCE) {
17946  strcat(blocking, "M");
17947  } else {
17948  strcat(blocking, " ");
17949  }
17950 
17951  if (p->remotelyblocked & SS7_BLOCKED_HARDWARE) {
17952  strcat(blocking, "H");
17953  } else {
17954  strcat(blocking, " ");
17955  }
17956  }
17957 
17958  ast_cli(a->fd, FORMAT2, ss7->pvts[i]->cic, ss7->pvts[i]->dpc, ss7->pvts[i]->channel, state, blocking);
17959  }
17960  }
17961 
17962  return CLI_SUCCESS;
17963 #undef FORMAT
17964 #undef FORMAT2
17965 }
17966 #endif /* defined(HAVE_SS7) */
17967 
17968 #if defined(HAVE_SS7)
17969 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17970 {
17971  switch (cmd) {
17972  case CLI_INIT:
17973  e->command = "ss7 show version";
17974  e->usage =
17975  "Usage: ss7 show version\n"
17976  " Show the libss7 version\n";
17977  return NULL;
17978  case CLI_GENERATE:
17979  return NULL;
17980  }
17981 
17982  ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
17983 
17984  return CLI_SUCCESS;
17985 }
17986 #endif /* defined(HAVE_SS7) */
17987 
17988 #if defined(HAVE_SS7)
17989 static struct ast_cli_entry dahdi_ss7_cli[] = {
17990  AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
17991  AST_CLI_DEFINE(handle_ss7_cic_blocking, "Blocks/Unblocks the given CIC"),
17992  AST_CLI_DEFINE(handle_ss7_linkset_mng, "Resets/Blocks/Unblocks all CICs on a linkset"),
17993  AST_CLI_DEFINE(handle_ss7_group_blocking, "Blocks/Unblocks the given CIC range"),
17994  AST_CLI_DEFINE(handle_ss7_reset_cic, "Resets the given CIC"),
17995  AST_CLI_DEFINE(handle_ss7_group_reset, "Resets the given CIC range"),
17996  AST_CLI_DEFINE(handle_ss7_mtp3_restart, "Restart a link"),
17997  AST_CLI_DEFINE(handle_ss7_net_mng, "Send an NET MNG message"),
17998  AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
17999  AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
18000  AST_CLI_DEFINE(handle_ss7_show_calls, "Show ss7 calls"),
18001  AST_CLI_DEFINE(handle_ss7_show_cics, "Show cics on a linkset"),
18002  AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
18003 };
18004 #endif /* defined(HAVE_SS7) */
18005 
18006 #if defined(HAVE_PRI)
18007 #if defined(HAVE_PRI_CCSS)
18008 /*!
18009  * \internal
18010  * \brief CC agent initialization.
18011  * \since 1.8
18012  *
18013  * \param agent CC core agent control.
18014  * \param chan Original channel the agent will attempt to recall.
18015  *
18016  * \details
18017  * This callback is called when the CC core is initialized. Agents should allocate
18018  * any private data necessary for the call and assign it to the private_data
18019  * on the agent. Additionally, if any ast_cc_agent_flags are pertinent to the
18020  * specific agent type, they should be set in this function as well.
18021  *
18022  * \retval 0 on success.
18023  * \retval -1 on error.
18024  */
18025 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
18026 {
18027  struct dahdi_pvt *pvt;
18028  struct sig_pri_chan *pvt_chan;
18029  int res;
18030 
18031  ast_assert(!strcmp(ast_channel_tech(chan)->type, "DAHDI"));
18032 
18033  pvt = ast_channel_tech_pvt(chan);
18034  if (dahdi_sig_pri_lib_handles(pvt->sig)) {
18035  pvt_chan = pvt->sig_pvt;
18036  } else {
18037  pvt_chan = NULL;
18038  }
18039  if (!pvt_chan) {
18040  return -1;
18041  }
18042 
18044 
18045  res = sig_pri_cc_agent_init(agent, pvt_chan);
18046  if (res) {
18048  }
18049  return res;
18050 }
18051 #endif /* defined(HAVE_PRI_CCSS) */
18052 #endif /* defined(HAVE_PRI) */
18053 
18054 #if defined(HAVE_PRI)
18055 #if defined(HAVE_PRI_CCSS)
18056 /*!
18057  * \internal
18058  * \brief Destroy private data on the agent.
18059  * \since 1.8
18060  *
18061  * \param agent CC core agent control.
18062  *
18063  * \details
18064  * The core will call this function upon completion
18065  * or failure of CC.
18066  */
18067 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
18068 {
18070 
18072 }
18073 #endif /* defined(HAVE_PRI_CCSS) */
18074 #endif /* defined(HAVE_PRI) */
18075 
18076 #if defined(HAVE_PRI)
18077 #if defined(HAVE_PRI_CCSS)
18078 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
18080  .init = dahdi_pri_cc_agent_init,
18081  .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
18082  .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
18083  .respond = sig_pri_cc_agent_req_rsp,
18084  .status_request = sig_pri_cc_agent_status_req,
18085  .stop_ringing = sig_pri_cc_agent_stop_ringing,
18086  .party_b_free = sig_pri_cc_agent_party_b_free,
18087  .start_monitoring = sig_pri_cc_agent_start_monitoring,
18088  .callee_available = sig_pri_cc_agent_callee_available,
18089  .destructor = dahdi_pri_cc_agent_destructor,
18090 };
18091 #endif /* defined(HAVE_PRI_CCSS) */
18092 #endif /* defined(HAVE_PRI) */
18093 
18094 #if defined(HAVE_PRI)
18095 #if defined(HAVE_PRI_CCSS)
18096 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
18098  .request_cc = sig_pri_cc_monitor_req_cc,
18099  .suspend = sig_pri_cc_monitor_suspend,
18100  .unsuspend = sig_pri_cc_monitor_unsuspend,
18101  .status_response = sig_pri_cc_monitor_status_rsp,
18102  .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
18103  .destructor = sig_pri_cc_monitor_destructor,
18104 };
18105 #endif /* defined(HAVE_PRI_CCSS) */
18106 #endif /* defined(HAVE_PRI) */
18107 
18108 static int __unload_module(void)
18109 {
18110  struct dahdi_pvt *p;
18111 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18112  int i, j;
18113 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18114 
18115 #ifdef HAVE_PRI
18116  for (i = 0; i < NUM_SPANS; i++) {
18117  if (pris[i].pri.master != AST_PTHREADT_NULL) {
18118  pthread_cancel(pris[i].pri.master);
18119  pthread_kill(pris[i].pri.master, SIGURG);
18120  }
18121  }
18122  ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18123  ast_unregister_application(dahdi_send_keypad_facility_app);
18124 #ifdef HAVE_PRI_PROG_W_CAUSE
18125  ast_unregister_application(dahdi_send_callrerouting_facility_app);
18126 #endif
18127 #endif
18128 #if defined(HAVE_SS7)
18129  for (i = 0; i < NUM_SPANS; i++) {
18130  if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
18131  pthread_cancel(linksets[i].ss7.master);
18132  pthread_kill(linksets[i].ss7.master, SIGURG);
18133  }
18134  }
18135  ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18136 #endif /* defined(HAVE_SS7) */
18137 #if defined(HAVE_OPENR2)
18138  dahdi_r2_destroy_links();
18139  ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18140  ast_unregister_application(dahdi_accept_r2_call_app);
18141 #endif
18142 
18143  ast_custom_function_unregister(&polarity_function);
18144 
18145  ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18146  ast_manager_unregister("DAHDIDialOffhook");
18147  ast_manager_unregister("DAHDIHangup");
18148  ast_manager_unregister("DAHDITransfer");
18149  ast_manager_unregister("DAHDIDNDoff");
18150  ast_manager_unregister("DAHDIDNDon");
18151  ast_manager_unregister("DAHDIShowChannels");
18152  ast_manager_unregister("DAHDIShowStatus");
18153  ast_manager_unregister("DAHDIRestart");
18154 #if defined(HAVE_PRI)
18155  ast_manager_unregister("PRIShowSpans");
18156  ast_manager_unregister("PRIDebugSet");
18157  ast_manager_unregister("PRIDebugFileSet");
18158  ast_manager_unregister("PRIDebugFileUnset");
18159 #endif /* defined(HAVE_PRI) */
18160  ast_channel_unregister(&dahdi_tech);
18161 
18162  /* Hangup all interfaces if they have an owner */
18163  ast_mutex_lock(&iflock);
18164  for (p = iflist; p; p = p->next) {
18165  if (p->owner)
18167  }
18168  ast_mutex_unlock(&iflock);
18169 
18170  ast_mutex_lock(&monlock);
18171  if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
18172  pthread_cancel(monitor_thread);
18173  pthread_kill(monitor_thread, SIGURG);
18174  pthread_join(monitor_thread, NULL);
18175  }
18176  monitor_thread = AST_PTHREADT_STOP;
18177  ast_mutex_unlock(&monlock);
18178 
18179  destroy_all_channels();
18180 
18181 #if defined(HAVE_PRI)
18182  for (i = 0; i < NUM_SPANS; i++) {
18183  if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
18184  pthread_join(pris[i].pri.master, NULL);
18185  }
18186  for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
18187  dahdi_close_pri_fd(&(pris[i]), j);
18188  }
18189  sig_pri_stop_pri(&pris[i].pri);
18190  }
18191 #if defined(HAVE_PRI_CCSS)
18192  ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
18193  ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
18194 #endif /* defined(HAVE_PRI_CCSS) */
18195  sig_pri_unload();
18196 #endif
18197 
18198 #if defined(HAVE_SS7)
18199  for (i = 0; i < NUM_SPANS; i++) {
18200  if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
18201  pthread_join(linksets[i].ss7.master, NULL);
18202  }
18203  for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
18204  dahdi_close_ss7_fd(&(linksets[i]), j);
18205  }
18206  if (linksets[i].ss7.ss7) {
18207  ss7_destroy(linksets[i].ss7.ss7);
18208  linksets[i].ss7.ss7 = NULL;
18209  }
18210  }
18211 #endif /* defined(HAVE_SS7) */
18212  ast_cond_destroy(&ss_thread_complete);
18213 
18214  dahdi_native_unload();
18215 
18216  ao2_cleanup(dahdi_tech.capabilities);
18217  dahdi_tech.capabilities = NULL;
18218  STASIS_MESSAGE_TYPE_CLEANUP(dahdichannel_type);
18219  return 0;
18220 }
18221 
18222 static int unload_module(void)
18223 {
18224 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18225  int y;
18226 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18227 #ifdef HAVE_PRI
18228  for (y = 0; y < NUM_SPANS; y++)
18229  ast_mutex_destroy(&pris[y].pri.lock);
18230 #endif
18231 #if defined(HAVE_SS7)
18232  for (y = 0; y < NUM_SPANS; y++)
18233  ast_mutex_destroy(&linksets[y].ss7.lock);
18234 #endif /* defined(HAVE_SS7) */
18235  return __unload_module();
18236 }
18237 
18238 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno)
18239 {
18240  char *c, *chan;
18241  int x, start, finish;
18242  struct dahdi_pvt *tmp;
18243 
18244  if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
18245  ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
18246  return -1;
18247  }
18248 
18249  c = ast_strdupa(value);
18250 
18251  while ((chan = strsep(&c, ","))) {
18252  if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
18253  /* Range */
18254  } else if (sscanf(chan, "%30d", &start)) {
18255  /* Just one */
18256  finish = start;
18257  } else if (!strcasecmp(chan, "pseudo")) {
18258  finish = start = CHAN_PSEUDO;
18259  } else {
18260  ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
18261  return -1;
18262  }
18263  if (finish < start) {
18264  ast_log(LOG_WARNING, "Silliness: %d < %d\n", start, finish);
18265  x = finish;
18266  finish = start;
18267  start = x;
18268  }
18269 
18270  for (x = start; x <= finish; x++) {
18271  if (conf->wanted_channels_start &&
18272  (x < conf->wanted_channels_start ||
18273  x > conf->wanted_channels_end)
18274  ) {
18275  continue;
18276  }
18277  tmp = mkintf(x, conf, reload);
18278 
18279  if (tmp) {
18280  ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
18281  } else {
18282  ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
18283  (reload == 1) ? "reconfigure" : "register", value);
18284  return -1;
18285  }
18286  if (x == CHAN_PSEUDO) {
18287  has_pseudo = 1;
18288  }
18289  }
18290  }
18291 
18292  return 0;
18293 }
18294 
18295 /** The length of the parameters list of 'dahdichan'.
18296  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
18297 #define MAX_CHANLIST_LEN 80
18298 
18299 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
18300 {
18301  char *parse = ast_strdupa(data);
18302  char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
18303  unsigned int param_count;
18304  unsigned int x;
18305 
18306  if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
18307  return;
18308 
18309  memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
18310 
18311  /* first parameter is tap length, process it here */
18312 
18313  x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
18314 
18315  if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
18316  confp->chan.echocancel.head.tap_length = x;
18317  else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
18318  confp->chan.echocancel.head.tap_length = 128;
18319 
18320  /* now process any remaining parameters */
18321 
18322  for (x = 1; x < param_count; x++) {
18323  struct {
18324  char *name;
18325  char *value;
18326  } param;
18327 
18328  if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
18329  ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]);
18330  continue;
18331  }
18332 
18333  if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
18334  ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name);
18335  continue;
18336  }
18337 
18338  strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
18339 
18340  if (param.value) {
18341  if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
18342  ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value);
18343  continue;
18344  }
18345  }
18346  confp->chan.echocancel.head.param_count++;
18347  }
18348 }
18349 
18350 #if defined(HAVE_PRI)
18351 #if defined(HAVE_PRI_DISPLAY_TEXT)
18352 /*!
18353  * \internal
18354  * \brief Determine the configured display text options.
18355  * \since 10.0
18356  *
18357  * \param value Configuration value string.
18358  *
18359  * \return Configured display text option flags.
18360  */
18361 static unsigned long dahdi_display_text_option(const char *value)
18362 {
18363  char *val_str;
18364  char *opt_str;
18365  unsigned long options;
18366 
18367  options = 0;
18368  val_str = ast_strdupa(value);
18369 
18370  for (;;) {
18371  opt_str = strsep(&val_str, ",");
18372  if (!opt_str) {
18373  break;
18374  }
18375  opt_str = ast_strip(opt_str);
18376  if (!*opt_str) {
18377  continue;
18378  }
18379 
18380  if (!strcasecmp(opt_str, "block")) {
18381  options |= PRI_DISPLAY_OPTION_BLOCK;
18382  } else if (!strcasecmp(opt_str, "name_initial")) {
18383  options |= PRI_DISPLAY_OPTION_NAME_INITIAL;
18384  } else if (!strcasecmp(opt_str, "name_update")) {
18385  options |= PRI_DISPLAY_OPTION_NAME_UPDATE;
18386  } else if (!strcasecmp(opt_str, "name")) {
18387  options |= (PRI_DISPLAY_OPTION_NAME_INITIAL | PRI_DISPLAY_OPTION_NAME_UPDATE);
18388  } else if (!strcasecmp(opt_str, "text")) {
18389  options |= PRI_DISPLAY_OPTION_TEXT;
18390  }
18391  }
18392  return options;
18393 }
18394 #endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
18395 #endif /* defined(HAVE_PRI) */
18396 
18397 #if defined(HAVE_PRI)
18398 #if defined(HAVE_PRI_DATETIME_SEND)
18399 /*!
18400  * \internal
18401  * \brief Determine the configured date/time send policy option.
18402  * \since 10.0
18403  *
18404  * \param value Configuration value string.
18405  *
18406  * \return Configured date/time send policy option.
18407  */
18408 static int dahdi_datetime_send_option(const char *value)
18409 {
18410  int option;
18411 
18412  option = PRI_DATE_TIME_SEND_DEFAULT;
18413 
18414  if (ast_false(value)) {
18415  option = PRI_DATE_TIME_SEND_NO;
18416  } else if (!strcasecmp(value, "date")) {
18417  option = PRI_DATE_TIME_SEND_DATE;
18418  } else if (!strcasecmp(value, "date_hh")) {
18419  option = PRI_DATE_TIME_SEND_DATE_HH;
18420  } else if (!strcasecmp(value, "date_hhmm")) {
18421  option = PRI_DATE_TIME_SEND_DATE_HHMM;
18422  } else if (!strcasecmp(value, "date_hhmmss")) {
18423  option = PRI_DATE_TIME_SEND_DATE_HHMMSS;
18424  }
18425 
18426  return option;
18427 }
18428 #endif /* defined(HAVE_PRI_DATETIME_SEND) */
18429 #endif /* defined(HAVE_PRI) */
18430 
18431 /*! process_dahdi() - ignore keyword 'channel' and similar */
18432 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
18433 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
18434 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
18435 
18436 static void parse_busy_pattern(struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
18437 {
18438  int count_pattern = 0;
18439  int norval = 0;
18440  char *temp = NULL;
18441 
18442  for (; ;) {
18443  /* Scans the string for the next value in the pattern. If none, it checks to see if any have been entered so far. */
18444  if (!sscanf(v->value, "%30d", &norval) && count_pattern == 0) {
18445  ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
18446  break;
18447  }
18448 
18449  busy_cadence->pattern[count_pattern] = norval;
18450 
18451  count_pattern++;
18452  if (count_pattern == 4) {
18453  break;
18454  }
18455 
18456  temp = strchr(v->value, ',');
18457  if (temp == NULL) {
18458  break;
18459  }
18460  v->value = temp + 1;
18461  }
18462  busy_cadence->length = count_pattern;
18463 
18464  if (count_pattern % 2 != 0) {
18465  /* The pattern length must be divisible by two */
18466  ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
18467  }
18468 
18469 }
18470 
18471 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
18472 {
18473  struct dahdi_pvt *tmp;
18474  int y;
18475  struct ast_variable *dahdichan = NULL;
18476 
18477  /* Re-parse any cadences from beginning, rather than appending until we run out of room */
18478  user_has_defined_cadences = 0;
18479 
18480  for (; v; v = v->next) {
18481  if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
18482  continue;
18483 
18484  /* Create the interface list */
18485  if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
18486  if (options & PROC_DAHDI_OPT_NOCHAN) {
18487  ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
18488  continue;
18489  }
18490  if (build_channels(confp, v->value, reload, v->lineno)) {
18491  if (confp->ignore_failed_channels) {
18492  ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
18493  continue;
18494  } else {
18495  return -1;
18496  }
18497  }
18498  ast_debug(1, "Channel '%s' configured.\n", v->value);
18499  } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
18500  confp->ignore_failed_channels = ast_true(v->value);
18501  } else if (!strcasecmp(v->name, "buffers")) {
18502  if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
18503  ast_log(LOG_WARNING, "Using default buffer policy.\n");
18504  confp->chan.buf_no = numbufs;
18505  confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
18506  }
18507  } else if (!strcasecmp(v->name, "faxbuffers")) {
18508  if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
18509  confp->chan.usefaxbuffers = 1;
18510  }
18511  } else if (!strcasecmp(v->name, "dahdichan")) {
18512  /* Only process the last dahdichan value. */
18513  dahdichan = v;
18514  } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
18515  usedistinctiveringdetection = ast_true(v->value);
18516  } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
18517  distinctiveringaftercid = ast_true(v->value);
18518  } else if (!strcasecmp(v->name, "dring1context")) {
18519  ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
18520  } else if (!strcasecmp(v->name, "dring2context")) {
18521  ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
18522  } else if (!strcasecmp(v->name, "dring3context")) {
18523  ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
18524  } else if (!strcasecmp(v->name, "dring1range")) {
18525  confp->chan.drings.ringnum[0].range = atoi(v->value);
18526  } else if (!strcasecmp(v->name, "dring2range")) {
18527  confp->chan.drings.ringnum[1].range = atoi(v->value);
18528  } else if (!strcasecmp(v->name, "dring3range")) {
18529  confp->chan.drings.ringnum[2].range = atoi(v->value);
18530  } else if (!strcasecmp(v->name, "dring1")) {
18531  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]);
18532  } else if (!strcasecmp(v->name, "dring2")) {
18533  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]);
18534  } else if (!strcasecmp(v->name, "dring3")) {
18535  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]);
18536  } else if (!strcasecmp(v->name, "usecallerid")) {
18537  confp->chan.use_callerid = ast_true(v->value);
18538  } else if (!strcasecmp(v->name, "cidsignalling")) {
18539  if (!strcasecmp(v->value, "bell"))
18540  confp->chan.cid_signalling = CID_SIG_BELL;
18541  else if (!strcasecmp(v->value, "v23"))
18542  confp->chan.cid_signalling = CID_SIG_V23;
18543  else if (!strcasecmp(v->value, "dtmf"))
18544  confp->chan.cid_signalling = CID_SIG_DTMF;
18545  else if (!strcasecmp(v->value, "smdi"))
18546  confp->chan.cid_signalling = CID_SIG_SMDI;
18547  else if (!strcasecmp(v->value, "v23_jp"))
18548  confp->chan.cid_signalling = CID_SIG_V23_JP;
18549  else if (ast_true(v->value))
18550  confp->chan.cid_signalling = CID_SIG_BELL;
18551  } else if (!strcasecmp(v->name, "cidstart")) {
18552  if (!strcasecmp(v->value, "ring"))
18553  confp->chan.cid_start = CID_START_RING;
18554  else if (!strcasecmp(v->value, "polarity_in"))
18555  confp->chan.cid_start = CID_START_POLARITY_IN;
18556  else if (!strcasecmp(v->value, "polarity"))
18557  confp->chan.cid_start = CID_START_POLARITY;
18558  else if (!strcasecmp(v->value, "dtmf"))
18559  confp->chan.cid_start = CID_START_DTMF_NOALERT;
18560  else if (ast_true(v->value))
18561  confp->chan.cid_start = CID_START_RING;
18562  } else if (!strcasecmp(v->name, "threewaycalling")) {
18563  confp->chan.threewaycalling = ast_true(v->value);
18564  } else if (!strcasecmp(v->name, "threewaysilenthold")) {
18565  confp->chan.threewaysilenthold = ast_true(v->value);
18566  } else if (!strcasecmp(v->name, "cancallforward")) {
18567  confp->chan.cancallforward = ast_true(v->value);
18568  } else if (!strcasecmp(v->name, "relaxdtmf")) {
18569  if (ast_true(v->value))
18570  confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
18571  else
18572  confp->chan.dtmfrelax = 0;
18573  } else if (!strcasecmp(v->name, "mailbox")) {
18574  ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
18575  } else if (!strcasecmp(v->name, "description")) {
18576  ast_copy_string(confp->chan.description, v->value, sizeof(confp->chan.description));
18577  } else if (!strcasecmp(v->name, "hasvoicemail")) {
18578  if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
18579  /*
18580  * hasvoicemail is a users.conf legacy voicemail enable method.
18581  * hasvoicemail is only going to work for app_voicemail mailboxes.
18582  */
18583  if (strchr(cat, '@')) {
18584  ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
18585  } else {
18586  snprintf(confp->chan.mailbox, sizeof(confp->chan.mailbox),
18587  "%s@default", cat);
18588  }
18589  }
18590  } else if (!strcasecmp(v->name, "adsi")) {
18591  confp->chan.adsi = ast_true(v->value);
18592  } else if (!strcasecmp(v->name, "usesmdi")) {
18593  confp->chan.use_smdi = ast_true(v->value);
18594  } else if (!strcasecmp(v->name, "smdiport")) {
18595  ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
18596  } else if (!strcasecmp(v->name, "transfer")) {
18597  confp->chan.transfer = ast_true(v->value);
18598  } else if (!strcasecmp(v->name, "canpark")) {
18599  confp->chan.canpark = ast_true(v->value);
18600  } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
18601  confp->chan.echocanbridged = ast_true(v->value);
18602  } else if (!strcasecmp(v->name, "busydetect")) {
18603  confp->chan.busydetect = ast_true(v->value);
18604  } else if (!strcasecmp(v->name, "busycount")) {
18605  confp->chan.busycount = atoi(v->value);
18606  } else if (!strcasecmp(v->name, "busypattern")) {
18607  parse_busy_pattern(v, &confp->chan.busy_cadence);
18608  } else if (!strcasecmp(v->name, "calledsubscriberheld")) {
18609  confp->chan.calledsubscriberheld = ast_true(v->value);
18610  } else if (!strcasecmp(v->name, "callprogress")) {
18611  confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
18612  if (ast_true(v->value))
18613  confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
18614  } else if (!strcasecmp(v->name, "waitfordialtone")) {
18615  confp->chan.waitfordialtone = atoi(v->value);
18616  } else if (!strcasecmp(v->name, "dialtone_detect")) {
18617  if (!strcasecmp(v->value, "always")) {
18618  confp->chan.dialtone_detect = -1;
18619  } else if (ast_true(v->value)) {
18621  } else if (ast_false(v->value)) {
18622  confp->chan.dialtone_detect = 0;
18623  } else {
18624  confp->chan.dialtone_detect = ast_strlen_zero(v->value) ? 0 : (8 * atoi(v->value)) / READ_SIZE;
18625  }
18626  } else if (!strcasecmp(v->name, "faxdetect")) {
18627  confp->chan.callprogress &= ~CALLPROGRESS_FAX;
18628  if (!strcasecmp(v->value, "incoming")) {
18629  confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
18630  } else if (!strcasecmp(v->value, "outgoing")) {
18631  confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
18632  } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
18633  confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
18634  } else if (!strcasecmp(v->name, "faxdetect_timeout")) {
18635  if (sscanf(v->value, "%30u", &confp->chan.faxdetect_timeout) != 1) {
18636  confp->chan.faxdetect_timeout = 0;
18637  }
18638  } else if (!strcasecmp(v->name, "firstdigit_timeout")) {
18639  if (sscanf(v->value, "%30d", &confp->chan.firstdigit_timeout) != 1
18640  || confp->chan.firstdigit_timeout <= 0) {
18642  }
18643  } else if (!strcasecmp(v->name, "interdigit_timeout")) {
18644  if (sscanf(v->value, "%30d", &confp->chan.interdigit_timeout) != 1
18645  || confp->chan.interdigit_timeout <= 0) {
18647  }
18648  } else if (!strcasecmp(v->name, "matchdigit_timeout")) {
18649  if (sscanf(v->value, "%30d", &confp->chan.matchdigit_timeout) != 1
18650  || confp->chan.matchdigit_timeout <= 0) {
18652  }
18653  } else if (!strcasecmp(v->name, "echocancel")) {
18654  process_echocancel(confp, v->value, v->lineno);
18655  } else if (!strcasecmp(v->name, "echotraining")) {
18656  if (sscanf(v->value, "%30d", &y) == 1) {
18657  if ((y < 10) || (y > 4000)) {
18658  ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
18659  } else {
18660  confp->chan.echotraining = y;
18661  }
18662  } else if (ast_true(v->value)) {
18663  confp->chan.echotraining = 400;
18664  } else
18665  confp->chan.echotraining = 0;
18666  } else if (!strcasecmp(v->name, "hidecallerid")) {
18667  confp->chan.hidecallerid = ast_true(v->value);
18668  } else if (!strcasecmp(v->name, "hidecalleridname")) {
18669  confp->chan.hidecalleridname = ast_true(v->value);
18670  } else if (!strcasecmp(v->name, "pulsedial")) {
18671  confp->chan.pulse = ast_true(v->value);
18672  } else if (!strcasecmp(v->name, "callreturn")) {
18673  confp->chan.callreturn = ast_true(v->value);
18674  } else if (!strcasecmp(v->name, "callwaiting")) {
18675  confp->chan.callwaiting = ast_true(v->value);
18676  } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
18677  confp->chan.callwaitingcallerid = ast_true(v->value);
18678  } else if (!strcasecmp(v->name, "context")) {
18679  ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
18680  } else if (!strcasecmp(v->name, "language")) {
18681  ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
18682  } else if (!strcasecmp(v->name, "progzone")) {
18683  ast_copy_string(progzone, v->value, sizeof(progzone));
18684  } else if (!strcasecmp(v->name, "mohinterpret")
18685  ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
18686  ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
18687  } else if (!strcasecmp(v->name, "mohsuggest")) {
18688  ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
18689  } else if (!strcasecmp(v->name, "parkinglot")) {
18690  ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
18691  } else if (!strcasecmp(v->name, "stripmsd")) {
18692  ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
18693  confp->chan.stripmsd = atoi(v->value);
18694  } else if (!strcasecmp(v->name, "jitterbuffers")) {
18695  numbufs = atoi(v->value);
18696  } else if (!strcasecmp(v->name, "group")) {
18697  confp->chan.group = ast_get_group(v->value);
18698  } else if (!strcasecmp(v->name, "callgroup")) {
18699  if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18700  ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a call group\n");
18701  }
18702  if (!strcasecmp(v->value, "none"))
18703  confp->chan.callgroup = 0;
18704  else
18705  confp->chan.callgroup = ast_get_group(v->value);
18706  } else if (!strcasecmp(v->name, "pickupgroup")) {
18707  if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18708  ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a pickup group\n");
18709  }
18710  if (!strcasecmp(v->value, "none"))
18711  confp->chan.pickupgroup = 0;
18712  else
18713  confp->chan.pickupgroup = ast_get_group(v->value);
18714  } else if (!strcasecmp(v->name, "namedcallgroup")) {
18715  if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18716  ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a named call group\n");
18717  }
18718  confp->chan.named_callgroups = ast_get_namedgroups(v->value);
18719  } else if (!strcasecmp(v->name, "namedpickupgroup")) {
18720  if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18721  ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a named pickup group\n");
18722  }
18723  confp->chan.named_pickupgroups = ast_get_namedgroups(v->value);
18724  } else if (!strcasecmp(v->name, "setvar")) {
18725  if (v->value) {
18726  char *varval = NULL;
18727  struct ast_variable *tmpvar;
18728  char varname[strlen(v->value) + 1];
18729  strcpy(varname, v->value); /* safe */
18730  if ((varval = strchr(varname, '='))) {
18731  *varval++ = '\0';
18732  if ((tmpvar = ast_variable_new(varname, varval, ""))) {
18733  if (ast_variable_list_replace(&confp->chan.vars, tmpvar)) {
18734  tmpvar->next = confp->chan.vars;
18735  confp->chan.vars = tmpvar;
18736  }
18737  }
18738  }
18739  }
18740  } else if (!strcasecmp(v->name, "immediate")) {
18741  confp->chan.immediate = ast_true(v->value);
18742  } else if (!strcasecmp(v->name, "immediatering")) {
18743  confp->chan.immediatering = ast_true(v->value);
18744  } else if (!strcasecmp(v->name, "transfertobusy")) {
18745  confp->chan.transfertobusy = ast_true(v->value);
18746  } else if (!strcasecmp(v->name, "dialmode")) {
18747  if (!strcasecmp(v->value, "pulse")) {
18748  confp->chan.dialmode = ANALOG_DIALMODE_PULSE;
18749  } else if (!strcasecmp(v->value, "dtmf") || !strcasecmp(v->value, "tone")) {
18750  confp->chan.dialmode = ANALOG_DIALMODE_DTMF;
18751  } else if (!strcasecmp(v->value, "none")) {
18752  confp->chan.dialmode = ANALOG_DIALMODE_NONE;
18753  } else {
18754  confp->chan.dialmode = ANALOG_DIALMODE_BOTH;
18755  }
18756  } else if (!strcasecmp(v->name, "mwimonitor")) {
18757  confp->chan.mwimonitor_neon = 0;
18758  confp->chan.mwimonitor_fsk = 0;
18759  confp->chan.mwimonitor_rpas = 0;
18760  if (strcasestr(v->value, "fsk")) {
18761  confp->chan.mwimonitor_fsk = 1;
18762  }
18763  if (strcasestr(v->value, "rpas")) {
18764  confp->chan.mwimonitor_rpas = 1;
18765  }
18766  if (strcasestr(v->value, "neon")) {
18767  confp->chan.mwimonitor_neon = 1;
18768  }
18769  /* If set to true or yes, assume that simple fsk is desired */
18770  if (ast_true(v->value)) {
18771  confp->chan.mwimonitor_fsk = 1;
18772  }
18773  } else if (!strcasecmp(v->name, "hwrxgain")) {
18774  confp->chan.hwrxgain_enabled = 0;
18775  if (strcasecmp(v->value, "disabled")) {
18776  if (sscanf(v->value, "%30f", &confp->chan.hwrxgain) == 1) {
18777  confp->chan.hwrxgain_enabled = 1;
18778  } else {
18779  ast_log(LOG_WARNING, "Invalid hwrxgain: %s at line %d.\n", v->value, v->lineno);
18780  }
18781  }
18782  } else if (!strcasecmp(v->name, "hwtxgain")) {
18783  confp->chan.hwtxgain_enabled = 0;
18784  if (strcasecmp(v->value, "disabled")) {
18785  if (sscanf(v->value, "%30f", &confp->chan.hwtxgain) == 1) {
18786  confp->chan.hwtxgain_enabled = 1;
18787  } else {
18788  ast_log(LOG_WARNING, "Invalid hwtxgain: %s at line %d.\n", v->value, v->lineno);
18789  }
18790  }
18791  } else if (!strcasecmp(v->name, "cid_rxgain")) {
18792  if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
18793  ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
18794  }
18795  } else if (!strcasecmp(v->name, "rxgain")) {
18796  if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
18797  ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
18798  }
18799  } else if (!strcasecmp(v->name, "txgain")) {
18800  if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
18801  ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
18802  }
18803  } else if (!strcasecmp(v->name, "txdrc")) {
18804  if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
18805  ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
18806  }
18807  } else if (!strcasecmp(v->name, "rxdrc")) {
18808  if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
18809  ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
18810  }
18811  } else if (!strcasecmp(v->name, "tonezone")) {
18812  if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
18813  ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
18814  }
18815  } else if (!strcasecmp(v->name, "callerid")) {
18816  if (!strcasecmp(v->value, "asreceived")) {
18817  confp->chan.cid_num[0] = '\0';
18818  confp->chan.cid_name[0] = '\0';
18819  } else {
18820  ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
18821  }
18822  } else if (!strcasecmp(v->name, "fullname")) {
18823  ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
18824  } else if (!strcasecmp(v->name, "cid_number")) {
18825  ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
18826  } else if (!strcasecmp(v->name, "cid_tag")) {
18827  ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
18828  } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
18829  confp->chan.dahditrcallerid = ast_true(v->value);
18830  } else if (!strcasecmp(v->name, "restrictcid")) {
18831  confp->chan.restrictcid = ast_true(v->value);
18832  } else if (!strcasecmp(v->name, "usecallingpres")) {
18833  confp->chan.use_callingpres = ast_true(v->value);
18834  } else if (!strcasecmp(v->name, "accountcode")) {
18835  ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
18836  } else if (!strcasecmp(v->name, "amaflags")) {
18838  if (y < 0)
18839  ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
18840  else
18841  confp->chan.amaflags = y;
18842  } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
18843  confp->chan.polarityonanswerdelay = atoi(v->value);
18844  } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
18845  confp->chan.answeronpolarityswitch = ast_true(v->value);
18846  } else if (!strcasecmp(v->name, "ani_info_digits")) {
18847  confp->chan.ani_info_digits = atoi(v->value);
18848  } else if (!strcasecmp(v->name, "ani_wink_time")) {
18849  confp->chan.ani_wink_time = atoi(v->value);
18850  } else if (!strcasecmp(v->name, "ani_timeout")) {
18851  confp->chan.ani_timeout = atoi(v->value);
18852  } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
18853  confp->chan.hanguponpolarityswitch = ast_true(v->value);
18854  } else if (!strcasecmp(v->name, "autoreoriginate")) {
18855  confp->chan.reoriginate = ast_true(v->value);
18856  } else if (!strcasecmp(v->name, "sendcalleridafter")) {
18857  confp->chan.sendcalleridafter = atoi(v->value);
18858  } else if (!strcasecmp(v->name, "mwimonitornotify")) {
18860  } else if (ast_cc_is_config_param(v->name)) {
18861  ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
18862  } else if (!strcasecmp(v->name, "mwisendtype")) {
18863 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI /* backward compatibility for older dahdi VMWI implementation */
18864  if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
18865  mwisend_rpas = 1;
18866  } else {
18867  mwisend_rpas = 0;
18868  }
18869 #else
18870  /* Default is fsk, to turn it off you must specify nofsk */
18871  memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
18872  if (strcasestr(v->value, "nofsk")) { /* NoFSK */
18873  confp->chan.mwisend_fsk = 0;
18874  } else { /* Default FSK */
18875  confp->chan.mwisend_fsk = 1;
18876  }
18877  if (strcasestr(v->value, "rpas")) { /* Ring Pulse Alert Signal, normally followed by FSK */
18878  confp->chan.mwisend_rpas = 1;
18879  } else {
18880  confp->chan.mwisend_rpas = 0;
18881  }
18882  if (strcasestr(v->value, "lrev")) { /* Line Reversal */
18883  confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
18884  }
18885  if (strcasestr(v->value, "hvdc")) { /* HV 90VDC */
18886  confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
18887  }
18888  if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ) { /* 90V DC pulses */
18889  confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
18890  }
18891 #endif
18892  } else if (reload != 1) {
18893  if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
18894  int orig_radio = confp->chan.radio;
18895  int orig_outsigmod = confp->chan.outsigmod;
18896  int orig_auto = confp->is_sig_auto;
18897 
18898  confp->chan.radio = 0;
18899  confp->chan.outsigmod = -1;
18900  confp->is_sig_auto = 0;
18901  if (!strcasecmp(v->value, "em")) {
18902  confp->chan.sig = SIG_EM;
18903  } else if (!strcasecmp(v->value, "em_e1")) {
18904  confp->chan.sig = SIG_EM_E1;
18905  } else if (!strcasecmp(v->value, "em_w")) {
18906  confp->chan.sig = SIG_EMWINK;
18907  } else if (!strcasecmp(v->value, "fxs_ls")) {
18908  confp->chan.sig = SIG_FXSLS;
18909  } else if (!strcasecmp(v->value, "fxs_gs")) {
18910  confp->chan.sig = SIG_FXSGS;
18911  } else if (!strcasecmp(v->value, "fxs_ks")) {
18912  confp->chan.sig = SIG_FXSKS;
18913  } else if (!strcasecmp(v->value, "fxo_ls")) {
18914  confp->chan.sig = SIG_FXOLS;
18915  } else if (!strcasecmp(v->value, "fxo_gs")) {
18916  confp->chan.sig = SIG_FXOGS;
18917  } else if (!strcasecmp(v->value, "fxo_ks")) {
18918  confp->chan.sig = SIG_FXOKS;
18919  } else if (!strcasecmp(v->value, "fxs_rx")) {
18920  confp->chan.sig = SIG_FXSKS;
18921  confp->chan.radio = 1;
18922  } else if (!strcasecmp(v->value, "fxo_rx")) {
18923  confp->chan.sig = SIG_FXOLS;
18924  confp->chan.radio = 1;
18925  } else if (!strcasecmp(v->value, "fxs_tx")) {
18926  confp->chan.sig = SIG_FXSLS;
18927  confp->chan.radio = 1;
18928  } else if (!strcasecmp(v->value, "fxo_tx")) {
18929  confp->chan.sig = SIG_FXOGS;
18930  confp->chan.radio = 1;
18931  } else if (!strcasecmp(v->value, "em_rx")) {
18932  confp->chan.sig = SIG_EM;
18933  confp->chan.radio = 1;
18934  } else if (!strcasecmp(v->value, "em_tx")) {
18935  confp->chan.sig = SIG_EM;
18936  confp->chan.radio = 1;
18937  } else if (!strcasecmp(v->value, "em_rxtx")) {
18938  confp->chan.sig = SIG_EM;
18939  confp->chan.radio = 2;
18940  } else if (!strcasecmp(v->value, "em_txrx")) {
18941  confp->chan.sig = SIG_EM;
18942  confp->chan.radio = 2;
18943  } else if (!strcasecmp(v->value, "sf")) {
18944  confp->chan.sig = SIG_SF;
18945  } else if (!strcasecmp(v->value, "sf_w")) {
18946  confp->chan.sig = SIG_SFWINK;
18947  } else if (!strcasecmp(v->value, "sf_featd")) {
18948  confp->chan.sig = SIG_FEATD;
18949  } else if (!strcasecmp(v->value, "sf_featdmf")) {
18950  confp->chan.sig = SIG_FEATDMF;
18951  } else if (!strcasecmp(v->value, "sf_featb")) {
18952  confp->chan.sig = SIG_SF_FEATB;
18953  } else if (!strcasecmp(v->value, "sf")) {
18954  confp->chan.sig = SIG_SF;
18955  } else if (!strcasecmp(v->value, "sf_rx")) {
18956  confp->chan.sig = SIG_SF;
18957  confp->chan.radio = 1;
18958  } else if (!strcasecmp(v->value, "sf_tx")) {
18959  confp->chan.sig = SIG_SF;
18960  confp->chan.radio = 1;
18961  } else if (!strcasecmp(v->value, "sf_rxtx")) {
18962  confp->chan.sig = SIG_SF;
18963  confp->chan.radio = 2;
18964  } else if (!strcasecmp(v->value, "sf_txrx")) {
18965  confp->chan.sig = SIG_SF;
18966  confp->chan.radio = 2;
18967  } else if (!strcasecmp(v->value, "featd")) {
18968  confp->chan.sig = SIG_FEATD;
18969  } else if (!strcasecmp(v->value, "featdmf")) {
18970  confp->chan.sig = SIG_FEATDMF;
18971  } else if (!strcasecmp(v->value, "featdmf_ta")) {
18972  confp->chan.sig = SIG_FEATDMF_TA;
18973  } else if (!strcasecmp(v->value, "e911")) {
18974  confp->chan.sig = SIG_E911;
18975  } else if (!strcasecmp(v->value, "fgccama")) {
18976  confp->chan.sig = SIG_FGC_CAMA;
18977  } else if (!strcasecmp(v->value, "fgccamamf")) {
18978  confp->chan.sig = SIG_FGC_CAMAMF;
18979  } else if (!strcasecmp(v->value, "featb")) {
18980  confp->chan.sig = SIG_FEATB;
18981 #ifdef HAVE_PRI
18982  } else if (!strcasecmp(v->value, "pri_net")) {
18983  confp->chan.sig = SIG_PRI;
18984  confp->pri.pri.nodetype = PRI_NETWORK;
18985  } else if (!strcasecmp(v->value, "pri_cpe")) {
18986  confp->chan.sig = SIG_PRI;
18987  confp->pri.pri.nodetype = PRI_CPE;
18988  } else if (!strcasecmp(v->value, "bri_cpe")) {
18989  confp->chan.sig = SIG_BRI;
18990  confp->pri.pri.nodetype = PRI_CPE;
18991  } else if (!strcasecmp(v->value, "bri_net")) {
18992  confp->chan.sig = SIG_BRI;
18993  confp->pri.pri.nodetype = PRI_NETWORK;
18994  } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
18995  confp->chan.sig = SIG_BRI_PTMP;
18996  confp->pri.pri.nodetype = PRI_CPE;
18997  } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
18998 #if defined(HAVE_PRI_CALL_HOLD)
18999  confp->chan.sig = SIG_BRI_PTMP;
19000  confp->pri.pri.nodetype = PRI_NETWORK;
19001 #else
19002  ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
19003 #endif /* !defined(HAVE_PRI_CALL_HOLD) */
19004 #endif
19005 #if defined(HAVE_SS7)
19006  } else if (!strcasecmp(v->value, "ss7")) {
19007  confp->chan.sig = SIG_SS7;
19008 #endif /* defined(HAVE_SS7) */
19009 #ifdef HAVE_OPENR2
19010  } else if (!strcasecmp(v->value, "mfcr2")) {
19011  confp->chan.sig = SIG_MFCR2;
19012 #endif
19013  } else if (!strcasecmp(v->value, "auto")) {
19014  confp->is_sig_auto = 1;
19015  } else {
19016  confp->chan.outsigmod = orig_outsigmod;
19017  confp->chan.radio = orig_radio;
19018  confp->is_sig_auto = orig_auto;
19019  ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
19020  }
19021  } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
19022  if (!strcasecmp(v->value, "em")) {
19023  confp->chan.outsigmod = SIG_EM;
19024  } else if (!strcasecmp(v->value, "em_e1")) {
19025  confp->chan.outsigmod = SIG_EM_E1;
19026  } else if (!strcasecmp(v->value, "em_w")) {
19027  confp->chan.outsigmod = SIG_EMWINK;
19028  } else if (!strcasecmp(v->value, "sf")) {
19029  confp->chan.outsigmod = SIG_SF;
19030  } else if (!strcasecmp(v->value, "sf_w")) {
19031  confp->chan.outsigmod = SIG_SFWINK;
19032  } else if (!strcasecmp(v->value, "sf_featd")) {
19033  confp->chan.outsigmod = SIG_FEATD;
19034  } else if (!strcasecmp(v->value, "sf_featdmf")) {
19035  confp->chan.outsigmod = SIG_FEATDMF;
19036  } else if (!strcasecmp(v->value, "sf_featb")) {
19037  confp->chan.outsigmod = SIG_SF_FEATB;
19038  } else if (!strcasecmp(v->value, "sf")) {
19039  confp->chan.outsigmod = SIG_SF;
19040  } else if (!strcasecmp(v->value, "featd")) {
19041  confp->chan.outsigmod = SIG_FEATD;
19042  } else if (!strcasecmp(v->value, "featdmf")) {
19043  confp->chan.outsigmod = SIG_FEATDMF;
19044  } else if (!strcasecmp(v->value, "featdmf_ta")) {
19045  confp->chan.outsigmod = SIG_FEATDMF_TA;
19046  } else if (!strcasecmp(v->value, "e911")) {
19047  confp->chan.outsigmod = SIG_E911;
19048  } else if (!strcasecmp(v->value, "fgccama")) {
19049  confp->chan.outsigmod = SIG_FGC_CAMA;
19050  } else if (!strcasecmp(v->value, "fgccamamf")) {
19051  confp->chan.outsigmod = SIG_FGC_CAMAMF;
19052  } else if (!strcasecmp(v->value, "featb")) {
19053  confp->chan.outsigmod = SIG_FEATB;
19054  } else {
19055  ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
19056  }
19057 #ifdef HAVE_PRI
19058  } else if (!strcasecmp(v->name, "pridialplan")) {
19059  if (!strcasecmp(v->value, "national")) {
19060  confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
19061  } else if (!strcasecmp(v->value, "unknown")) {
19062  confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
19063  } else if (!strcasecmp(v->value, "private")) {
19064  confp->pri.pri.dialplan = PRI_PRIVATE + 1;
19065  } else if (!strcasecmp(v->value, "international")) {
19066  confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
19067  } else if (!strcasecmp(v->value, "local")) {
19068  confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
19069  } else if (!strcasecmp(v->value, "dynamic")) {
19070  confp->pri.pri.dialplan = -1;
19071  } else if (!strcasecmp(v->value, "redundant")) {
19072  confp->pri.pri.dialplan = -2;
19073  } else {
19074  ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
19075  }
19076  } else if (!strcasecmp(v->name, "prilocaldialplan")) {
19077  if (!strcasecmp(v->value, "national")) {
19078  confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
19079  } else if (!strcasecmp(v->value, "unknown")) {
19080  confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
19081  } else if (!strcasecmp(v->value, "private")) {
19082  confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
19083  } else if (!strcasecmp(v->value, "international")) {
19084  confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
19085  } else if (!strcasecmp(v->value, "local")) {
19086  confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
19087  } else if (!strcasecmp(v->value, "from_channel")) {
19088  confp->pri.pri.localdialplan = 0;
19089  } else if (!strcasecmp(v->value, "dynamic")) {
19090  confp->pri.pri.localdialplan = -1;
19091  } else if (!strcasecmp(v->value, "redundant")) {
19092  confp->pri.pri.localdialplan = -2;
19093  } else {
19094  ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
19095  }
19096  } else if (!strcasecmp(v->name, "pricpndialplan")) {
19097  if (!strcasecmp(v->value, "national")) {
19098  confp->pri.pri.cpndialplan = PRI_NATIONAL_ISDN + 1;
19099  } else if (!strcasecmp(v->value, "unknown")) {
19100  confp->pri.pri.cpndialplan = PRI_UNKNOWN + 1;
19101  } else if (!strcasecmp(v->value, "private")) {
19102  confp->pri.pri.cpndialplan = PRI_PRIVATE + 1;
19103  } else if (!strcasecmp(v->value, "international")) {
19104  confp->pri.pri.cpndialplan = PRI_INTERNATIONAL_ISDN + 1;
19105  } else if (!strcasecmp(v->value, "local")) {
19106  confp->pri.pri.cpndialplan = PRI_LOCAL_ISDN + 1;
19107  } else if (!strcasecmp(v->value, "from_channel")) {
19108  confp->pri.pri.cpndialplan = 0;
19109  } else if (!strcasecmp(v->value, "dynamic")) {
19110  confp->pri.pri.cpndialplan = -1;
19111  } else if (!strcasecmp(v->value, "redundant")) {
19112  confp->pri.pri.cpndialplan = -2;
19113  } else {
19114  ast_log(LOG_WARNING, "Unknown PRI cpndialplan '%s' at line %d.\n", v->value, v->lineno);
19115  }
19116  } else if (!strcasecmp(v->name, "switchtype")) {
19117  if (!strcasecmp(v->value, "national"))
19118  confp->pri.pri.switchtype = PRI_SWITCH_NI2;
19119  else if (!strcasecmp(v->value, "ni1"))
19120  confp->pri.pri.switchtype = PRI_SWITCH_NI1;
19121  else if (!strcasecmp(v->value, "dms100"))
19122  confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
19123  else if (!strcasecmp(v->value, "4ess"))
19124  confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
19125  else if (!strcasecmp(v->value, "5ess"))
19126  confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
19127  else if (!strcasecmp(v->value, "euroisdn"))
19128  confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
19129  else if (!strcasecmp(v->value, "qsig"))
19130  confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
19131  else {
19132  ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
19133  return -1;
19134  }
19135  } else if (!strcasecmp(v->name, "msn")) {
19136  ast_copy_string(confp->pri.pri.msn_list, v->value,
19137  sizeof(confp->pri.pri.msn_list));
19138  } else if (!strcasecmp(v->name, "nsf")) {
19139  if (!strcasecmp(v->value, "sdn"))
19140  confp->pri.pri.nsf = PRI_NSF_SDN;
19141  else if (!strcasecmp(v->value, "megacom"))
19142  confp->pri.pri.nsf = PRI_NSF_MEGACOM;
19143  else if (!strcasecmp(v->value, "tollfreemegacom"))
19144  confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
19145  else if (!strcasecmp(v->value, "accunet"))
19146  confp->pri.pri.nsf = PRI_NSF_ACCUNET;
19147  else if (!strcasecmp(v->value, "none"))
19148  confp->pri.pri.nsf = PRI_NSF_NONE;
19149  else {
19150  ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
19151  confp->pri.pri.nsf = PRI_NSF_NONE;
19152  }
19153  } else if (!strcasecmp(v->name, "priindication")) {
19154  if (!strcasecmp(v->value, "outofband"))
19155  confp->chan.priindication_oob = 1;
19156  else if (!strcasecmp(v->value, "inband"))
19157  confp->chan.priindication_oob = 0;
19158  else
19159  ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
19160  v->value, v->lineno);
19161  } else if (!strcasecmp(v->name, "priexclusive")) {
19162  confp->chan.priexclusive = ast_true(v->value);
19163  } else if (!strcasecmp(v->name, "internationalprefix")) {
19164  ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
19165  } else if (!strcasecmp(v->name, "nationalprefix")) {
19166  ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
19167  } else if (!strcasecmp(v->name, "localprefix")) {
19168  ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
19169  } else if (!strcasecmp(v->name, "privateprefix")) {
19170  ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
19171  } else if (!strcasecmp(v->name, "unknownprefix")) {
19172  ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
19173  } else if (!strcasecmp(v->name, "resetinterval")) {
19174  if (!strcasecmp(v->value, "never"))
19175  confp->pri.pri.resetinterval = -1;
19176  else if (atoi(v->value) >= 60)
19177  confp->pri.pri.resetinterval = atoi(v->value);
19178  else
19179  ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
19180  v->value, v->lineno);
19181  } else if (!strcasecmp(v->name, "force_restart_unavailable_chans")) {
19182  confp->pri.pri.force_restart_unavailable_chans = ast_true(v->value);
19183  } else if (!strcasecmp(v->name, "minunused")) {
19184  confp->pri.pri.minunused = atoi(v->value);
19185  } else if (!strcasecmp(v->name, "minidle")) {
19186  confp->pri.pri.minidle = atoi(v->value);
19187  } else if (!strcasecmp(v->name, "idleext")) {
19188  ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
19189  } else if (!strcasecmp(v->name, "idledial")) {
19190  ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
19191  } else if (!strcasecmp(v->name, "overlapdial")) {
19192  if (ast_true(v->value)) {
19193  confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
19194  } else if (!strcasecmp(v->value, "incoming")) {
19195  confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
19196  } else if (!strcasecmp(v->value, "outgoing")) {
19197  confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
19198  } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
19199  confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
19200  } else {
19201  confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
19202  }
19203 #ifdef HAVE_PRI_PROG_W_CAUSE
19204  } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
19205  if (!strcasecmp(v->value, "logical")) {
19206  confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
19207  } else if (!strcasecmp(v->value, "physical")) {
19208  confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
19209  } else {
19210  confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
19211  }
19212 #endif
19213  } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
19214  confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
19215 #if defined(HAVE_PRI_SERVICE_MESSAGES)
19216  } else if (!strcasecmp(v->name, "service_message_support")) {
19217  /* assuming switchtype for this channel group has been configured already */
19218  if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
19219  || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
19220  || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
19221  confp->pri.pri.enable_service_message_support = 1;
19222  } else {
19223  confp->pri.pri.enable_service_message_support = 0;
19224  }
19225 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
19226 #ifdef HAVE_PRI_INBANDDISCONNECT
19227  } else if (!strcasecmp(v->name, "inbanddisconnect")) {
19228  confp->pri.pri.inbanddisconnect = ast_true(v->value);
19229 #endif
19230  } else if (!strcasecmp(v->name, "pritimer")) {
19231 #ifdef PRI_GETSET_TIMERS
19232  char tmp[20];
19233  char *timerc;
19234  char *c;
19235  int timer;
19236  int timeridx;
19237 
19238  ast_copy_string(tmp, v->value, sizeof(tmp));
19239  c = tmp;
19240  timerc = strsep(&c, ",");
19241  if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
19242  timeridx = pri_timer2idx(timerc);
19243  timer = atoi(c);
19244  if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
19245  ast_log(LOG_WARNING,
19246  "'%s' is not a valid ISDN timer at line %d.\n", timerc,
19247  v->lineno);
19248  } else if (!timer) {
19249  ast_log(LOG_WARNING,
19250  "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
19251  c, timerc, v->lineno);
19252  } else {
19253  confp->pri.pri.pritimers[timeridx] = timer;
19254  }
19255  } else {
19256  ast_log(LOG_WARNING,
19257  "'%s' is not a valid ISDN timer configuration string at line %d.\n",
19258  v->value, v->lineno);
19259  }
19260 #endif /* PRI_GETSET_TIMERS */
19261  } else if (!strcasecmp(v->name, "facilityenable")) {
19262  confp->pri.pri.facilityenable = ast_true(v->value);
19263 #if defined(HAVE_PRI_AOC_EVENTS)
19264  } else if (!strcasecmp(v->name, "aoc_enable")) {
19265  confp->pri.pri.aoc_passthrough_flag = 0;
19266  if (strchr(v->value, 's') || strchr(v->value, 'S')) {
19267  confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
19268  }
19269  if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
19270  confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
19271  }
19272  if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
19273  confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
19274  }
19275  } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
19276  confp->pri.pri.aoce_delayhangup = ast_true(v->value);
19277 #endif /* defined(HAVE_PRI_AOC_EVENTS) */
19278 #if defined(HAVE_PRI_CALL_HOLD)
19279  } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
19280  confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
19281 #endif /* defined(HAVE_PRI_CALL_HOLD) */
19282  } else if (!strcasecmp(v->name, "moh_signaling")
19283  || !strcasecmp(v->name, "moh_signalling")) {
19284  if (!strcasecmp(v->value, "moh")) {
19285  confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
19286  } else if (!strcasecmp(v->value, "notify")) {
19287  confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_NOTIFY;
19288 #if defined(HAVE_PRI_CALL_HOLD)
19289  } else if (!strcasecmp(v->value, "hold")) {
19290  confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_HOLD;
19291 #endif /* defined(HAVE_PRI_CALL_HOLD) */
19292  } else {
19293  confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
19294  }
19295 #if defined(HAVE_PRI_CCSS)
19296  } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
19297  if (!strcasecmp(v->value, "global")) {
19298  confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
19299  } else if (!strcasecmp(v->value, "specific")) {
19300  confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
19301  } else {
19302  confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
19303  }
19304  } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
19305  if (!strcasecmp(v->value, "release")) {
19306  confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
19307  } else if (!strcasecmp(v->value, "retain")) {
19308  confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
19309  } else if (!strcasecmp(v->value, "do_not_care")) {
19310  confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
19311  } else {
19312  confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
19313  }
19314  } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
19315  if (!strcasecmp(v->value, "release")) {
19316  confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
19317  } else if (!strcasecmp(v->value, "retain")) {
19318  confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
19319  } else {
19320  confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
19321  }
19322 #endif /* defined(HAVE_PRI_CCSS) */
19323 #if defined(HAVE_PRI_CALL_WAITING)
19324  } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
19325  confp->pri.pri.max_call_waiting_calls = atoi(v->value);
19326  if (confp->pri.pri.max_call_waiting_calls < 0) {
19327  /* Negative values are not allowed. */
19328  confp->pri.pri.max_call_waiting_calls = 0;
19329  }
19330  } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
19331  confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
19332 #endif /* defined(HAVE_PRI_CALL_WAITING) */
19333 #if defined(HAVE_PRI_MWI)
19334  } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
19335  ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
19336  sizeof(confp->pri.pri.mwi_mailboxes));
19337  } else if (!strcasecmp(v->name, "mwi_vm_boxes")) {
19338  ast_copy_string(confp->pri.pri.mwi_vm_boxes, v->value,
19339  sizeof(confp->pri.pri.mwi_vm_boxes));
19340  } else if (!strcasecmp(v->name, "mwi_vm_numbers")) {
19341  ast_copy_string(confp->pri.pri.mwi_vm_numbers, v->value,
19342  sizeof(confp->pri.pri.mwi_vm_numbers));
19343 #endif /* defined(HAVE_PRI_MWI) */
19344  } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
19345  confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
19346  } else if (!strcasecmp(v->name, "inband_on_setup_ack")) {
19347  confp->pri.pri.inband_on_setup_ack = ast_true(v->value);
19348  } else if (!strcasecmp(v->name, "inband_on_proceeding")) {
19349  confp->pri.pri.inband_on_proceeding = ast_true(v->value);
19350 #if defined(HAVE_PRI_DISPLAY_TEXT)
19351  } else if (!strcasecmp(v->name, "display_send")) {
19352  confp->pri.pri.display_flags_send = dahdi_display_text_option(v->value);
19353  } else if (!strcasecmp(v->name, "display_receive")) {
19354  confp->pri.pri.display_flags_receive = dahdi_display_text_option(v->value);
19355 #endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
19356 #if defined(HAVE_PRI_MCID)
19357  } else if (!strcasecmp(v->name, "mcid_send")) {
19358  confp->pri.pri.mcid_send = ast_true(v->value);
19359 #endif /* defined(HAVE_PRI_MCID) */
19360 #if defined(HAVE_PRI_DATETIME_SEND)
19361  } else if (!strcasecmp(v->name, "datetime_send")) {
19362  confp->pri.pri.datetime_send = dahdi_datetime_send_option(v->value);
19363 #endif /* defined(HAVE_PRI_DATETIME_SEND) */
19364  } else if (!strcasecmp(v->name, "layer1_presence")) {
19365  if (!strcasecmp(v->value, "required")) {
19366  confp->pri.pri.layer1_ignored = 0;
19367  } else if (!strcasecmp(v->value, "ignore")) {
19368  confp->pri.pri.layer1_ignored = 1;
19369  } else {
19370  /* Default */
19371  confp->pri.pri.layer1_ignored = 0;
19372  }
19373 #if defined(HAVE_PRI_L2_PERSISTENCE)
19374  } else if (!strcasecmp(v->name, "layer2_persistence")) {
19375  if (!strcasecmp(v->value, "keep_up")) {
19376  confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
19377  } else if (!strcasecmp(v->value, "leave_down")) {
19378  confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
19379  } else {
19380  confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
19381  }
19382 #endif /* defined(HAVE_PRI_L2_PERSISTENCE) */
19383  } else if (!strcasecmp(v->name, "colp_send")) {
19384  if (!strcasecmp(v->value, "block")) {
19385  confp->pri.pri.colp_send = SIG_PRI_COLP_BLOCK;
19386  } else if (!strcasecmp(v->value, "connect")) {
19387  confp->pri.pri.colp_send = SIG_PRI_COLP_CONNECT;
19388  } else if (!strcasecmp(v->value, "update")) {
19389  confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
19390  } else {
19391  confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
19392  }
19393 #endif /* HAVE_PRI */
19394 #if defined(HAVE_SS7)
19395  } else if (!strcasecmp(v->name, "ss7type")) {
19396  if (!strcasecmp(v->value, "itu")) {
19397  cur_ss7type = SS7_ITU;
19398  } else if (!strcasecmp(v->value, "ansi")) {
19399  cur_ss7type = SS7_ANSI;
19400  } else {
19401  ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
19402  }
19403  } else if (!strcasecmp(v->name, "slc")) {
19404  cur_slc = atoi(v->value);
19405  } else if (!strcasecmp(v->name, "linkset")) {
19406  cur_linkset = atoi(v->value);
19407  } else if (!strcasecmp(v->name, "pointcode")) {
19408  cur_pointcode = parse_pointcode(v->value);
19409  } else if (!strcasecmp(v->name, "adjpointcode")) {
19410  cur_adjpointcode = parse_pointcode(v->value);
19411  } else if (!strcasecmp(v->name, "defaultdpc")) {
19412  cur_defaultdpc = parse_pointcode(v->value);
19413  } else if (!strcasecmp(v->name, "cicbeginswith")) {
19414  cur_cicbeginswith = atoi(v->value);
19415  } else if (!strcasecmp(v->name, "networkindicator")) {
19416  if (!strcasecmp(v->value, "national")) {
19417  cur_networkindicator = SS7_NI_NAT;
19418  } else if (!strcasecmp(v->value, "national_spare")) {
19419  cur_networkindicator = SS7_NI_NAT_SPARE;
19420  } else if (!strcasecmp(v->value, "international")) {
19421  cur_networkindicator = SS7_NI_INT;
19422  } else if (!strcasecmp(v->value, "international_spare")) {
19423  cur_networkindicator = SS7_NI_INT_SPARE;
19424  } else {
19425  cur_networkindicator = -1;
19426  }
19427  } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
19428  ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
19429  } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
19430  ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
19431  } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
19432  ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
19433  } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
19434  ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
19435  } else if (!strcasecmp(v->name, "ss7_networkroutedprefix")) {
19436  ast_copy_string(confp->ss7.ss7.networkroutedprefix, v->value, sizeof(confp->ss7.ss7.networkroutedprefix));
19437  } else if (!strcasecmp(v->name, "ss7_called_nai")) {
19438  if (!strcasecmp(v->value, "national")) {
19439  confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
19440  } else if (!strcasecmp(v->value, "international")) {
19441  confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
19442  } else if (!strcasecmp(v->value, "subscriber")) {
19443  confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
19444  } else if (!strcasecmp(v->value, "unknown")) {
19445  confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
19446  } else if (!strcasecmp(v->value, "dynamic")) {
19447  confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
19448  } else {
19449  ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
19450  }
19451  } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
19452  if (!strcasecmp(v->value, "national")) {
19453  confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
19454  } else if (!strcasecmp(v->value, "international")) {
19455  confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
19456  } else if (!strcasecmp(v->value, "subscriber")) {
19457  confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
19458  } else if (!strcasecmp(v->value, "unknown")) {
19459  confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
19460  } else if (!strcasecmp(v->value, "dynamic")) {
19461  confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
19462  } else {
19463  ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
19464  }
19465  } else if (!strcasecmp(v->name, "sigchan")) {
19466  int sigchan, res;
19467  sigchan = atoi(v->value);
19468  res = linkset_addsigchan(sigchan);
19469  if (res < 0) {
19470  return -1;
19471  }
19472  } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
19473  struct dahdi_ss7 *link;
19474  link = ss7_resolve_linkset(cur_linkset);
19475  if (!link) {
19476  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19477  return -1;
19478  }
19479  if (ast_true(v->value)) {
19480  link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
19481  } else {
19482  link->ss7.flags &= ~LINKSET_FLAG_EXPLICITACM;
19483  }
19484  } else if (!strcasecmp(v->name, "ss7_autoacm")) {
19485  struct dahdi_ss7 *link;
19486  link = ss7_resolve_linkset(cur_linkset);
19487  if (!link) {
19488  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19489  return -1;
19490  }
19491  if (ast_true(v->value)) {
19492  link->ss7.flags |= LINKSET_FLAG_AUTOACM;
19493  } else {
19494  link->ss7.flags &= ~LINKSET_FLAG_AUTOACM;
19495  }
19496  } else if (!strcasecmp(v->name, "ss7_initialhwblo")) {
19497  struct dahdi_ss7 *link;
19498  link = ss7_resolve_linkset(cur_linkset);
19499  if (!link) {
19500  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19501  return -1;
19502  }
19503  if (ast_true(v->value)) {
19504  link->ss7.flags |= LINKSET_FLAG_INITIALHWBLO;
19505  } else {
19506  link->ss7.flags &= ~LINKSET_FLAG_INITIALHWBLO;
19507  }
19508  } else if (!strcasecmp(v->name, "ss7_use_echocontrol")) {
19509  struct dahdi_ss7 *link;
19510  link = ss7_resolve_linkset(cur_linkset);
19511  if (!link) {
19512  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19513  return -1;
19514  }
19515  if (ast_true(v->value)) {
19516  link->ss7.flags |= LINKSET_FLAG_USEECHOCONTROL;
19517  } else {
19518  link->ss7.flags &= ~LINKSET_FLAG_USEECHOCONTROL;
19519  }
19520  } else if (!strcasecmp(v->name, "ss7_default_echocontrol")) {
19521  struct dahdi_ss7 *link;
19522  link = ss7_resolve_linkset(cur_linkset);
19523  if (!link) {
19524  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19525  return -1;
19526  }
19527  if (ast_true(v->value)) {
19528  link->ss7.flags |= LINKSET_FLAG_DEFAULTECHOCONTROL;
19529  } else {
19530  link->ss7.flags &= ~LINKSET_FLAG_DEFAULTECHOCONTROL;
19531  }
19532  } else if (!strncasecmp(v->name, "isup_timer.", 11)) {
19533  struct dahdi_ss7 *link;
19534  link = ss7_resolve_linkset(cur_linkset);
19535  if (!link) {
19536  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19537  return -1;
19538  }
19539  if (!link->ss7.ss7) {
19540  ast_log(LOG_ERROR, "Please specify isup timers after sigchan!\n");
19541  } else if (!ss7_set_isup_timer(link->ss7.ss7, strstr(v->name, ".") + 1, atoi(v->value))) {
19542  ast_log(LOG_ERROR, "Invalid isup timer %s\n", v->name);
19543  }
19544  } else if (!strncasecmp(v->name, "mtp3_timer.", 11)) {
19545  struct dahdi_ss7 *link;
19546  link = ss7_resolve_linkset(cur_linkset);
19547  if (!link) {
19548  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19549  return -1;
19550  }
19551  if (!link->ss7.ss7) {
19552  ast_log(LOG_ERROR, "Please specify mtp3 timers after sigchan!\n");
19553  } else if (!ss7_set_mtp3_timer(link->ss7.ss7, strstr(v->name, ".") + 1, atoi(v->value))) {
19554  ast_log(LOG_ERROR, "Invalid mtp3 timer %s\n", v->name);
19555  }
19556  } else if (!strcasecmp(v->name, "inr_if_no_calling")) {
19557  struct dahdi_ss7 *link;
19558  link = ss7_resolve_linkset(cur_linkset);
19559  if (!link) {
19560  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19561  return -1;
19562  }
19563  if (!link->ss7.ss7) {
19564  ast_log(LOG_ERROR, "Please specify inr_if_no_calling after sigchan!\n");
19565  } else if (ast_true(v->value)) {
19566  ss7_set_flags(link->ss7.ss7, SS7_INR_IF_NO_CALLING);
19567  } else {
19568  ss7_clear_flags(link->ss7.ss7, SS7_INR_IF_NO_CALLING);
19569  }
19570  } else if (!strcasecmp(v->name, "non_isdn_access")) {
19571  struct dahdi_ss7 *link;
19572  link = ss7_resolve_linkset(cur_linkset);
19573  if (!link) {
19574  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19575  return -1;
19576  }
19577  if (!link->ss7.ss7) {
19578  ast_log(LOG_ERROR, "Please specify non_isdn_access after sigchan!\n");
19579  } else if (ast_true(v->value)) {
19580  ss7_clear_flags(link->ss7.ss7, SS7_ISDN_ACCESS_INDICATOR);
19581  } else {
19582  ss7_set_flags(link->ss7.ss7, SS7_ISDN_ACCESS_INDICATOR);
19583  }
19584  } else if (!strcasecmp(v->name, "sls_shift")) {
19585  struct dahdi_ss7 *link;
19586  int sls_shift = atoi(v->value);
19587 
19588  if (sls_shift < 0 || sls_shift > 7) {
19589  ast_log(LOG_ERROR, "Invalid sls_shift value. Must be between 0 and 7\n");
19590  return -1;
19591  }
19592 
19593  link = ss7_resolve_linkset(cur_linkset);
19594  if (!link) {
19595  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19596  return -1;
19597  }
19598  if (!link->ss7.ss7) {
19599  ast_log(LOG_ERROR, "Please specify sls_shift after sigchan!\n");
19600  } else {
19601  ss7_set_sls_shift(link->ss7.ss7, sls_shift);
19602  }
19603  } else if (!strcasecmp(v->name, "cause_location")) {
19604  struct dahdi_ss7 *link;
19605  int cause_location = atoi(v->value);
19606 
19607  if (cause_location < 0 || cause_location > 15) {
19608  ast_log(LOG_ERROR, "Invalid cause_location value. Must be between 0 and 15\n");
19609  return -1;
19610  }
19611  link = ss7_resolve_linkset(cur_linkset);
19612  if (!link) {
19613  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19614  return -1;
19615  }
19616  if (!link->ss7.ss7) {
19617  ast_log(LOG_ERROR, "Please specify cause_location after sigchan!\n");
19618  } else {
19619  ss7_set_cause_location(link->ss7.ss7, cause_location);
19620  }
19621 #endif /* defined(HAVE_SS7) */
19622 #ifdef HAVE_OPENR2
19623  } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
19624  ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
19625  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);
19626  } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
19627  ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
19628  } else if (!strcasecmp(v->name, "mfcr2_variant")) {
19629  confp->mfcr2.variant = openr2_proto_get_variant(v->value);
19630  if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
19631  ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
19632  confp->mfcr2.variant = OR2_VAR_ITU;
19633  }
19634  } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
19635  confp->mfcr2.mfback_timeout = atoi(v->value);
19636  if (!confp->mfcr2.mfback_timeout) {
19637  ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
19638  confp->mfcr2.mfback_timeout = -1;
19639  } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
19640  ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
19641  }
19642  } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
19643  confp->mfcr2.metering_pulse_timeout = atoi(v->value);
19644  if (confp->mfcr2.metering_pulse_timeout > 500) {
19645  ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
19646  }
19647 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
19648  } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
19649  confp->mfcr2.dtmf_detection = ast_true(v->value) ? 1 : 0;
19650  } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
19651  confp->mfcr2.dtmf_dialing = ast_true(v->value) ? 1 : 0;
19652  } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
19653  confp->mfcr2.dtmf_time_on = atoi(v->value);
19654  } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
19655  confp->mfcr2.dtmf_time_off = atoi(v->value);
19656 #endif
19657 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
19658  } else if (!strcasecmp(v->name, "mfcr2_dtmf_end_timeout")) {
19659  confp->mfcr2.dtmf_end_timeout = atoi(v->value);
19660 #endif
19661  } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
19662  confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
19663  } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
19664  confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
19665  } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
19666  confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
19667  } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
19668  confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
19669  } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
19670  confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
19671  } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
19672  confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
19673  } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
19674  confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
19675 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
19676  } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
19677  confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
19678 #endif
19679  } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
19680  confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
19681  } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
19682  confp->mfcr2.max_ani = atoi(v->value);
19683  if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION) {
19684  confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
19685  }
19686  } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
19687  confp->mfcr2.max_dnis = atoi(v->value);
19688  if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION) {
19689  confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
19690  }
19691  } else if (!strcasecmp(v->name, "mfcr2_category")) {
19692  confp->mfcr2.category = openr2_proto_get_category(v->value);
19693  if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
19694  confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
19695  ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
19696  v->value, v->lineno);
19697  }
19698  } else if (!strcasecmp(v->name, "mfcr2_logging")) {
19699  openr2_log_level_t tmplevel;
19700  char *clevel;
19701  char *logval;
19702  char copy[strlen(v->value) + 1];
19703  strcpy(copy, v->value); /* safe */
19704  logval = copy;
19705  while (logval) {
19706  clevel = strsep(&logval,",");
19707  if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
19708  ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
19709  continue;
19710  }
19711  confp->mfcr2.loglevel |= tmplevel;
19712  }
19713 #endif /* HAVE_OPENR2 */
19714  } else if (!strcasecmp(v->name, "cadence")) {
19715  /* setup to scan our argument */
19716  int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
19717  int i;
19718  struct dahdi_ring_cadence new_cadence;
19719  int cid_location = -1;
19720  int firstcadencepos = 0;
19721  char original_args[80];
19722  int cadence_is_ok = 1;
19723 
19724  ast_copy_string(original_args, v->value, sizeof(original_args));
19725  /* 16 cadences allowed (8 pairs) */
19726  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]);
19727 
19728  /* Cadence must be even (on/off) */
19729  if (element_count % 2 == 1) {
19730  ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
19731  cadence_is_ok = 0;
19732  }
19733 
19734  /* This check is only needed to satisfy the compiler that element_count can't cause an out of bounds */
19735  if (element_count > ARRAY_LEN(c)) {
19736  element_count = ARRAY_LEN(c);
19737  }
19738 
19739  /* Ring cadences cannot be negative */
19740  for (i = 0; i < element_count; i++) {
19741  if (c[i] == 0) {
19742  ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
19743  cadence_is_ok = 0;
19744  break;
19745  } else if (c[i] < 0) {
19746  if (i % 2 == 1) {
19747  /* Silence duration, negative possibly okay */
19748  if (cid_location == -1) {
19749  cid_location = i;
19750  c[i] *= -1;
19751  } else {
19752  ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
19753  cadence_is_ok = 0;
19754  break;
19755  }
19756  } else {
19757  if (firstcadencepos == 0) {
19758  firstcadencepos = i; /* only recorded to avoid duplicate specification */
19759  /* duration will be passed negative to the DAHDI driver */
19760  } else {
19761  ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
19762  cadence_is_ok = 0;
19763  break;
19764  }
19765  }
19766  }
19767  }
19768 
19769  /* Substitute our scanned cadence */
19770  for (i = 0; i < 16; i++) {
19771  new_cadence.ringcadence[i] = c[i];
19772  }
19773 
19774  if (cadence_is_ok) {
19775  /* ---we scanned it without getting annoyed; now some sanity checks--- */
19776  if (element_count < 2) {
19777  ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
19778  } else {
19779  if (cid_location == -1) {
19780  /* user didn't say; default to first pause */
19781  cid_location = 1;
19782  } else {
19783  /* convert element_index to cidrings value */
19784  cid_location = (cid_location + 1) / 2;
19785  }
19786  /* ---we like their cadence; try to install it--- */
19787  if (!user_has_defined_cadences++)
19788  /* this is the first user-defined cadence; clear the default user cadences */
19789  num_cadence = 0;
19790  if ((num_cadence+1) >= NUM_CADENCE_MAX)
19791  ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
19792  else {
19793  cadences[num_cadence] = new_cadence;
19794  cidrings[num_cadence++] = cid_location;
19795  ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
19796  }
19797  }
19798  }
19799  } else if (!strcasecmp(v->name, "ringtimeout")) {
19800  ringt_base = (atoi(v->value) * 8) / READ_SIZE;
19801  } else if (!strcasecmp(v->name, "prewink")) {
19802  confp->timing.prewinktime = atoi(v->value);
19803  } else if (!strcasecmp(v->name, "preflash")) {
19804  confp->timing.preflashtime = atoi(v->value);
19805  } else if (!strcasecmp(v->name, "wink")) {
19806  confp->timing.winktime = atoi(v->value);
19807  } else if (!strcasecmp(v->name, "flash")) {
19808  confp->timing.flashtime = atoi(v->value);
19809  } else if (!strcasecmp(v->name, "start")) {
19810  confp->timing.starttime = atoi(v->value);
19811  } else if (!strcasecmp(v->name, "rxwink")) {
19812  confp->timing.rxwinktime = atoi(v->value);
19813  } else if (!strcasecmp(v->name, "rxflash")) {
19814  confp->timing.rxflashtime = atoi(v->value);
19815  } else if (!strcasecmp(v->name, "debounce")) {
19816  confp->timing.debouncetime = atoi(v->value);
19817  } else if (!strcasecmp(v->name, "toneduration")) {
19818  int toneduration;
19819  int ctlfd;
19820  int res;
19821  struct dahdi_dialparams dps;
19822 
19823  ctlfd = open("/dev/dahdi/ctl", O_RDWR);
19824  if (ctlfd == -1) {
19825  ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
19826  return -1;
19827  }
19828 
19829  toneduration = atoi(v->value);
19830  if (toneduration > -1) {
19831  memset(&dps, 0, sizeof(dps));
19832 
19833  dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
19834  res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
19835  if (res < 0) {
19836  ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
19837  close(ctlfd);
19838  return -1;
19839  }
19840  }
19841  close(ctlfd);
19842  } else if (!strcasecmp(v->name, "defaultcic")) {
19843  ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
19844  } else if (!strcasecmp(v->name, "defaultozz")) {
19845  ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
19846  } else if (!strcasecmp(v->name, "mwilevel")) {
19847  mwilevel = atoi(v->value);
19848  } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
19849  dtmfcid_level = atoi(v->value);
19850  } else if (!strcasecmp(v->name, "reportalarms")) {
19851  if (!strcasecmp(v->value, "all"))
19852  report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
19853  if (!strcasecmp(v->value, "none"))
19854  report_alarms = 0;
19855  else if (!strcasecmp(v->value, "channels"))
19856  report_alarms = REPORT_CHANNEL_ALARMS;
19857  else if (!strcasecmp(v->value, "spans"))
19858  report_alarms = REPORT_SPAN_ALARMS;
19859  }
19860  } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
19861  ast_log(LOG_NOTICE, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
19862  }
19863 
19864  if (dahdichan) {
19865  /* Process the deferred dahdichan value. */
19866  if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno)) {
19867  if (confp->ignore_failed_channels) {
19868  ast_log(LOG_WARNING,
19869  "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
19870  dahdichan->value);
19871  } else {
19872  return -1;
19873  }
19874  }
19875  }
19876 
19877  /*
19878  * Since confp has already filled individual dahdi_pvt objects with channels
19879  * at this point, clear the variables in confp's pvt.
19880  */
19881  if (confp->chan.vars) {
19882  ast_variables_destroy(confp->chan.vars);
19883  confp->chan.vars = NULL;
19884  }
19885 
19886  /* mark the first channels of each DAHDI span to watch for their span alarms */
19887  for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
19888  if (!tmp->destroy && tmp->span != y) {
19889  tmp->manages_span_alarms = 1;
19890  y = tmp->span;
19891  } else {
19892  tmp->manages_span_alarms = 0;
19893  }
19894  }
19895 
19896  /*< \todo why check for the pseudo in the per-channel section.
19897  * Any actual use for manual setup of the pseudo channel? */
19898  if (!has_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
19899  /* use the default configuration for a channel, so
19900  that any settings from real configured channels
19901  don't "leak" into the pseudo channel config
19902  */
19903  struct dahdi_chan_conf conf = dahdi_chan_conf_default();
19904 
19905  if (conf.chan.cc_params) {
19906  tmp = mkintf(CHAN_PSEUDO, &conf, reload);
19907  } else {
19908  tmp = NULL;
19909  }
19910  if (tmp) {
19911  ast_verb(3, "Automatically generated pseudo channel\n");
19912  has_pseudo = 1;
19913  } else {
19914  ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
19915  }
19916  ast_cc_config_params_destroy(conf.chan.cc_params);
19917  }
19918 
19919  /* Since named callgroup and named pickup group are ref'd to dahdi_pvt at this point, unref container in confp's pvt. */
19920  confp->chan.named_callgroups = ast_unref_namedgroups(confp->chan.named_callgroups);
19921  confp->chan.named_pickupgroups = ast_unref_namedgroups(confp->chan.named_pickupgroups);
19922 
19923  return 0;
19924 }
19925 
19926 /*!
19927  * \internal
19928  * \brief Deep copy struct dahdi_chan_conf.
19929  * \since 1.8
19930  *
19931  * \param dest Destination.
19932  * \param src Source.
19933  */
19934 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
19935 {
19936  struct ast_cc_config_params *cc_params;
19937 
19938  cc_params = dest->chan.cc_params;
19939  *dest = *src;
19940  dest->chan.cc_params = cc_params;
19941  ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
19942 }
19943 
19944 /*!
19945  * \internal
19946  * \brief Setup DAHDI channel driver.
19947  *
19948  * \param reload enum: load_module(0), reload(1), restart(2).
19949  * \param default_conf Default config parameters. So cc_params can be properly destroyed.
19950  * \param base_conf Default config parameters per section. So cc_params can be properly destroyed.
19951  * \param conf Local config parameters. So cc_params can be properly destroyed.
19952  *
19953  * \retval 0 on success.
19954  * \retval -1 on error.
19955  */
19956 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
19957 {
19958  struct ast_config *cfg;
19959  struct ast_config *ucfg;
19960  struct ast_variable *v;
19961  struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
19962  const char *chans;
19963  const char *cat;
19964  int res;
19965 
19966 #ifdef HAVE_PRI
19967  char *c;
19968  int spanno;
19969  int i;
19970  int logicalspan;
19971  int trunkgroup;
19972  int dchannels[SIG_PRI_NUM_DCHANS];
19973 #endif
19974  int have_cfg_now;
19975  static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
19976 
19977  cfg = ast_config_load(config, config_flags);
19978  have_cfg_now = !!cfg;
19979  if (!cfg) {
19980  /* Error if we have no config file */
19981  if (had_cfg_before) {
19982  ast_log(LOG_ERROR, "Unable to load config %s\n", config);
19983  ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
19984  }
19985  cfg = ast_config_new();/* Dummy config */
19986  if (!cfg) {
19987  return 0;
19988  }
19989  ucfg = ast_config_load("users.conf", config_flags);
19990  if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
19991  ast_config_destroy(cfg);
19992  return 0;
19993  }
19994  if (ucfg == CONFIG_STATUS_FILEINVALID) {
19995  ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
19996  ast_config_destroy(cfg);
19997  return 0;
19998  }
19999  } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
20000  ucfg = ast_config_load("users.conf", config_flags);
20001  if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
20002  return 0;
20003  }
20004  if (ucfg == CONFIG_STATUS_FILEINVALID) {
20005  ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
20006  return 0;
20007  }
20008  ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
20009  cfg = ast_config_load(config, config_flags);
20010  have_cfg_now = !!cfg;
20011  if (!cfg) {
20012  if (had_cfg_before) {
20013  /* We should have been able to load the config. */
20014  ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
20015  ast_config_destroy(ucfg);
20016  return 0;
20017  }
20018  cfg = ast_config_new();/* Dummy config */
20019  if (!cfg) {
20020  ast_config_destroy(ucfg);
20021  return 0;
20022  }
20023  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
20024  ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
20025  ast_config_destroy(ucfg);
20026  return 0;
20027  }
20028  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
20029  ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
20030  return 0;
20031  } else {
20032  ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
20033  ucfg = ast_config_load("users.conf", config_flags);
20034  if (ucfg == CONFIG_STATUS_FILEINVALID) {
20035  ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
20036  ast_config_destroy(cfg);
20037  return 0;
20038  }
20039  }
20040  had_cfg_before = have_cfg_now;
20041 
20042  /* It's a little silly to lock it, but we might as well just to be sure */
20043  ast_mutex_lock(&iflock);
20044 #ifdef HAVE_PRI
20045  if (reload != 1) {
20046  /* Process trunkgroups first */
20047  v = ast_variable_browse(cfg, "trunkgroups");
20048  while (v) {
20049  if (!strcasecmp(v->name, "trunkgroup")) {
20050  trunkgroup = atoi(v->value);
20051  if (trunkgroup > 0) {
20052  if ((c = strchr(v->value, ','))) {
20053  i = 0;
20054  memset(dchannels, 0, sizeof(dchannels));
20055  while (c && (i < SIG_PRI_NUM_DCHANS)) {
20056  dchannels[i] = atoi(c + 1);
20057  if (dchannels[i] < 0) {
20058  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);
20059  } else
20060  i++;
20061  c = strchr(c + 1, ',');
20062  }
20063  if (i) {
20064  if (pri_create_trunkgroup(trunkgroup, dchannels)) {
20065  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);
20066  } else
20067  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");
20068  } else
20069  ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
20070  } else
20071  ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
20072  } else
20073  ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
20074  } else if (!strcasecmp(v->name, "spanmap")) {
20075  spanno = atoi(v->value);
20076  if (spanno > 0) {
20077  if ((c = strchr(v->value, ','))) {
20078  trunkgroup = atoi(c + 1);
20079  if (trunkgroup > 0) {
20080  if ((c = strchr(c + 1, ',')))
20081  logicalspan = atoi(c + 1);
20082  else
20083  logicalspan = 0;
20084  if (logicalspan >= 0) {
20085  if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
20086  ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
20087  } else
20088  ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
20089  } else
20090  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);
20091  } else
20092  ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
20093  } else
20094  ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
20095  } else
20096  ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
20097  } else {
20098  ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
20099  }
20100  v = v->next;
20101  }
20102  }
20103 #endif
20104 
20105  /* Copy the default jb config over global_jbconf */
20106  memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
20107 
20108  mwimonitornotify[0] = '\0';
20109 
20110  v = ast_variable_browse(cfg, "channels");
20111  if ((res = process_dahdi(base_conf,
20112  "" /* Must be empty for the channels category. Silly voicemail mailbox. */,
20113  v, reload, 0))) {
20114  ast_mutex_unlock(&iflock);
20115  ast_config_destroy(cfg);
20116  if (ucfg) {
20117  ast_config_destroy(ucfg);
20118  }
20119  return res;
20120  }
20121 
20122  /* Now get configuration from all normal sections in chan_dahdi.conf: */
20123  for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
20124  /* [channels] and [trunkgroups] are used. Let's also reserve
20125  * [globals] and [general] for future use
20126  */
20127  if (!strcasecmp(cat, "general") ||
20128  !strcasecmp(cat, "trunkgroups") ||
20129  !strcasecmp(cat, "globals") ||
20130  !strcasecmp(cat, "channels")) {
20131  continue;
20132  }
20133 
20134  chans = ast_variable_retrieve(cfg, cat, "dahdichan");
20135  if (ast_strlen_zero(chans)) {
20136  /* Section is useless without a dahdichan value present. */
20137  continue;
20138  }
20139 
20140  /* Copy base_conf to conf. */
20141  deep_copy_dahdi_chan_conf(conf, base_conf);
20142 
20143  if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
20144  ast_mutex_unlock(&iflock);
20145  ast_config_destroy(cfg);
20146  if (ucfg) {
20147  ast_config_destroy(ucfg);
20148  }
20149  return res;
20150  }
20151  }
20152 
20153  ast_config_destroy(cfg);
20154 
20155  if (ucfg) {
20156  /* Reset base_conf, so things don't leak from chan_dahdi.conf */
20157  deep_copy_dahdi_chan_conf(base_conf, default_conf);
20158  process_dahdi(base_conf,
20159  "" /* Must be empty for the general category. Silly voicemail mailbox. */,
20160  ast_variable_browse(ucfg, "general"), 1, 0);
20161 
20162  for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
20163  if (!strcasecmp(cat, "general")) {
20164  continue;
20165  }
20166 
20167  chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
20168  if (ast_strlen_zero(chans)) {
20169  /* Section is useless without a dahdichan value present. */
20170  continue;
20171  }
20172 
20173  /* Copy base_conf to conf. */
20174  deep_copy_dahdi_chan_conf(conf, base_conf);
20175 
20176  if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
20177  ast_config_destroy(ucfg);
20178  ast_mutex_unlock(&iflock);
20179  return res;
20180  }
20181  }
20182  ast_config_destroy(ucfg);
20183  }
20184  ast_mutex_unlock(&iflock);
20185 
20186 #ifdef HAVE_PRI
20187  if (reload != 1) {
20188  int x;
20189  for (x = 0; x < NUM_SPANS; x++) {
20190  if (pris[x].pri.pvts[0] &&
20191  pris[x].pri.master == AST_PTHREADT_NULL) {
20192  prepare_pri(pris + x);
20193  if (sig_pri_start_pri(&pris[x].pri)) {
20194  ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
20195  return -1;
20196  } else
20197  ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
20198  }
20199  }
20200  }
20201 #endif
20202 #if defined(HAVE_SS7)
20203  if (reload != 1) {
20204  int x;
20205  for (x = 0; x < NUM_SPANS; x++) {
20206  if (linksets[x].ss7.ss7) {
20207  if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
20208  ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
20209  return -1;
20210  } else
20211  ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
20212  }
20213  }
20214  }
20215 #endif /* defined(HAVE_SS7) */
20216 #ifdef HAVE_OPENR2
20217  if (reload != 1) {
20218  struct r2link_entry *cur;
20219  int x = 0;
20220  AST_LIST_LOCK(&r2links);
20221  AST_LIST_TRAVERSE(&r2links, cur, list) {
20222  struct dahdi_mfcr2 *r2 = &cur->mfcr2;
20223  if (r2->r2master == AST_PTHREADT_NULL) {
20224  if (ast_pthread_create(&r2->r2master, NULL, mfcr2_monitor, r2)) {
20225  ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
20226  return -1;
20227  } else {
20228  ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
20229  }
20230  x++;
20231  }
20232  }
20233  AST_LIST_UNLOCK(&r2links);
20234  }
20235 #endif
20236  /* And start the monitor for the first time */
20237  restart_monitor();
20238  return 0;
20239 }
20240 
20241 /*!
20242  * \internal
20243  * \brief Setup DAHDI channel driver.
20244  *
20245  * \param reload enum: load_module(0), reload(1), restart(2).
20246  *
20247  * \retval 0 on success.
20248  * \retval -1 on error.
20249  */
20250 static int setup_dahdi(int reload)
20251 {
20252  int res;
20253  struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
20254  struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
20255  struct dahdi_chan_conf conf = dahdi_chan_conf_default();
20256 
20257  if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
20258  res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
20259  } else {
20260  res = -1;
20261  }
20262  ast_cc_config_params_destroy(default_conf.chan.cc_params);
20263  ast_cc_config_params_destroy(base_conf.chan.cc_params);
20264  ast_cc_config_params_destroy(conf.chan.cc_params);
20265 
20266  return res;
20267 }
20268 
20269 /*!
20270  * \brief Load the module
20271  *
20272  * Module loading including tests for configuration or dependencies.
20273  * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
20274  * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
20275  * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
20276  * configuration file or other non-critical problem return
20277  * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
20278  */
20279 static int load_module(void)
20280 {
20281  int res;
20282 #if defined(HAVE_PRI) || defined(HAVE_SS7)
20283  int y;
20284 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
20285 
20286  if (STASIS_MESSAGE_TYPE_INIT(dahdichannel_type)) {
20287  return AST_MODULE_LOAD_DECLINE;
20288  }
20289 
20291  return AST_MODULE_LOAD_DECLINE;
20292  }
20296 
20297  if (dahdi_native_load(&dahdi_tech)) {
20298  ao2_ref(dahdi_tech.capabilities, -1);
20299  return AST_MODULE_LOAD_DECLINE;
20300  }
20301 
20302 #ifdef HAVE_PRI
20303  memset(pris, 0, sizeof(pris));
20304  for (y = 0; y < NUM_SPANS; y++) {
20305  sig_pri_init_pri(&pris[y].pri);
20306  }
20307  pri_set_error(dahdi_pri_error);
20308  pri_set_message(dahdi_pri_message);
20309  ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
20310 #ifdef HAVE_PRI_PROG_W_CAUSE
20311  ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
20312 #endif
20313 #if defined(HAVE_PRI_CCSS)
20314  if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
20315  || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
20316  __unload_module();
20317  return AST_MODULE_LOAD_DECLINE;
20318  }
20319 #endif /* defined(HAVE_PRI_CCSS) */
20320  if (sig_pri_load(
20321 #if defined(HAVE_PRI_CCSS)
20322  dahdi_pri_cc_type
20323 #else
20324  NULL
20325 #endif /* defined(HAVE_PRI_CCSS) */
20326  )) {
20327  __unload_module();
20328  return AST_MODULE_LOAD_DECLINE;
20329  }
20330 #endif
20331 #if defined(HAVE_SS7)
20332  memset(linksets, 0, sizeof(linksets));
20333  for (y = 0; y < NUM_SPANS; y++) {
20334  sig_ss7_init_linkset(&linksets[y].ss7);
20335  }
20336  ss7_set_error(dahdi_ss7_error);
20337  ss7_set_message(dahdi_ss7_message);
20338  ss7_set_hangup(sig_ss7_cb_hangup);
20339  ss7_set_notinservice(sig_ss7_cb_notinservice);
20340  ss7_set_call_null(sig_ss7_cb_call_null);
20341 #endif /* defined(HAVE_SS7) */
20342  res = setup_dahdi(0);
20343  /* Make sure we can register our DAHDI channel type */
20344  if (res) {
20345  __unload_module();
20346  return AST_MODULE_LOAD_DECLINE;
20347  }
20348  if (ast_channel_register(&dahdi_tech)) {
20349  ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
20350  __unload_module();
20351  return AST_MODULE_LOAD_DECLINE;
20352  }
20353 #ifdef HAVE_PRI
20354  ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
20355 #endif
20356 #if defined(HAVE_SS7)
20357  ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
20358 #endif /* defined(HAVE_SS7) */
20359 #ifdef HAVE_OPENR2
20360  ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
20361  ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
20362 #endif
20363 
20364  ast_custom_function_register(&polarity_function);
20365 
20366  ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
20367  memset(round_robin, 0, sizeof(round_robin));
20368  ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
20369  ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
20370  ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
20371  ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
20372  ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
20373  ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
20374  ast_manager_register_xml("DAHDIShowStatus", 0, action_dahdishowstatus);
20375  ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
20376 #if defined(HAVE_PRI)
20377  ast_manager_register_xml("PRIShowSpans", 0, action_prishowspans);
20378  ast_manager_register_xml("PRIDebugSet", 0, action_pri_debug_set);
20379  ast_manager_register_xml("PRIDebugFileSet", EVENT_FLAG_SYSTEM, action_pri_debug_file_set);
20380  ast_manager_register_xml("PRIDebugFileUnset", 0, action_pri_debug_file_unset);
20381 #endif /* defined(HAVE_PRI) */
20382 
20383  ast_cond_init(&ss_thread_complete, NULL);
20384 
20385  return res;
20386 }
20387 
20388 static int dahdi_sendtext(struct ast_channel *c, const char *text)
20389 {
20390 #define END_SILENCE_LEN 400
20391 #define HEADER_MS 50
20392 #define TRAILER_MS 5
20393 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
20394 #define ASCII_BYTES_PER_CHAR 80
20395 
20396  unsigned char *buf,*mybuf;
20397  struct dahdi_pvt *p = ast_channel_tech_pvt(c);
20398  struct pollfd fds[1];
20399  int size,res,fd,len,x;
20400  int bytes=0;
20401  int idx;
20402 
20403  /*
20404  * Initial carrier (imaginary)
20405  *
20406  * Note: The following float variables are used by the
20407  * PUT_CLID_MARKMS and PUT_CLID() macros.
20408  */
20409  float cr = 1.0;
20410  float ci = 0.0;
20411  float scont = 0.0;
20412 
20413  if (!text[0]) {
20414  return(0); /* if nothing to send, don't */
20415  }
20416  idx = dahdi_get_index(c, p, 0);
20417  if (idx < 0) {
20418  ast_log(LOG_WARNING, "Huh? I don't exist?\n");
20419  return -1;
20420  }
20421  if ((!p->tdd) && (!p->mate)) {
20422 #if defined(HAVE_PRI)
20423 #if defined(HAVE_PRI_DISPLAY_TEXT)
20424  ast_mutex_lock(&p->lock);
20425  if (dahdi_sig_pri_lib_handles(p->sig)) {
20426  sig_pri_sendtext(p->sig_pvt, text);
20427  }
20428  ast_mutex_unlock(&p->lock);
20429 #endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
20430 #endif /* defined(HAVE_PRI) */
20431  return(0); /* if not in TDD mode, just return */
20432  }
20433  if (p->mate)
20434  buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
20435  else
20436  buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
20437  if (!buf)
20438  return -1;
20439  mybuf = buf;
20440  if (p->mate) {
20441  /* PUT_CLI_MARKMS is a macro and requires a format ptr called codec to be present */
20442  struct ast_format *codec = AST_LAW(p);
20443 
20444  for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
20445  PUT_CLID_MARKMS;
20446  }
20447  /* Put actual message */
20448  for (x = 0; text[x]; x++) {
20449  PUT_CLID(text[x]);
20450  }
20451  for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
20452  PUT_CLID_MARKMS;
20453  }
20454  len = bytes;
20455  buf = mybuf;
20456  } else {
20457  len = tdd_generate(p->tdd, buf, text);
20458  if (len < 1) {
20459  ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
20460  ast_free(mybuf);
20461  return -1;
20462  }
20463  }
20464  memset(buf + len, 0x7f, END_SILENCE_LEN);
20465  len += END_SILENCE_LEN;
20466  fd = p->subs[idx].dfd;
20467  while (len) {
20468  if (ast_check_hangup(c)) {
20469  ast_free(mybuf);
20470  return -1;
20471  }
20472  size = len;
20473  if (size > READ_SIZE)
20474  size = READ_SIZE;
20475  fds[0].fd = fd;
20476  fds[0].events = POLLOUT | POLLPRI;
20477  fds[0].revents = 0;
20478  res = poll(fds, 1, -1);
20479  if (!res) {
20480  ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
20481  continue;
20482  }
20483  /* if got exception */
20484  if (fds[0].revents & POLLPRI) {
20485  ast_free(mybuf);
20486  return -1;
20487  }
20488  if (!(fds[0].revents & POLLOUT)) {
20489  ast_debug(1, "write fd not ready on channel %d\n", p->channel);
20490  continue;
20491  }
20492  res = write(fd, buf, size);
20493  if (res != size) {
20494  if (res == -1) {
20495  ast_free(mybuf);
20496  return -1;
20497  }
20498  ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
20499  break;
20500  }
20501  len -= size;
20502  buf += size;
20503  }
20504  ast_free(mybuf);
20505  return(0);
20506 }
20507 
20508 
20509 static int reload(void)
20510 {
20511  int res = 0;
20512 
20513  res = setup_dahdi(1);
20514  if (res) {
20515  ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
20516  return -1;
20517  }
20518  return 0;
20519 }
20520 
20521 /* This is a workaround so that menuselect displays a proper description
20522  * AST_MODULE_INFO(, , "DAHDI Telephony"
20523  */
20524 
20525 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
20526  .support_level = AST_MODULE_SUPPORT_CORE,
20527  .load = load_module,
20528  .unload = unload_module,
20529  .reload = reload,
20530  .load_pri = AST_MODPRI_CHANNEL_DRIVER,
20531  .requires = "ccss",
20532  .optional_modules = "res_smdi",
20533 );
int cidpos
Position in the cidspill buffer to send out next.
Definition: chan_dahdi.h:599
int max_call_waiting_calls
Number of extra outgoing calls to allow on a span before considering that span congested.
Definition: sig_pri.h:569
const char * name
Definition: pbx.h:119
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:1562
A-Law to Signed linear conversion.
char defcontext[AST_MAX_CONTEXT]
Default distinctive ring context.
Definition: chan_dahdi.h:500
unsigned int outgoing
TRUE if we originated the call leg.
Definition: chan_dahdi.h:328
int outsigmod
Definition: chan_dahdi.h:150
unsigned int digital
TRUE if the transfer capability of the call is digital.
Definition: chan_dahdi.h:260
static void pri_queue_for_destruction(struct sig_pri_span *pri)
Queue a span for destruction.
Definition: chan_dahdi.c:1313
int ast_cc_agent_register(const struct ast_cc_agent_callbacks *callbacks)
Register a set of agent callbacks with the core.
Definition: ccss.c:1217
struct ast_variable * next
int dialtone_scanning_time_elapsed
Definition: chan_dahdi.h:670
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1574
enum analog_dialmode dialmode
Definition: sig_analog.h:321
int matchdigit_timeout
Time (ms) to wait, in case of ambiguous match (in an analog phone)
Definition: chan_dahdi.h:690
char description[32]
A description for the channel configuration.
Definition: chan_dahdi.h:496
Struct containing info for an AMI event to send out.
Definition: manager.h:502
int dtmfrelax
Definition: chan_dahdi.h:720
unsigned int priexclusive
TRUE if PRI B channels are always exclusively selected.
Definition: chan_dahdi.h:349
int presentation
Q.931 encoded presentation-indicator encoded field.
Definition: channel.h:277
void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value)
int nodetype
Definition: sig_pri.h:555
#define POLARITY_IDLE
Definition: sig_analog.c:62
int dchan_logical_span[SIG_PRI_NUM_DCHANS]
Definition: sig_pri.h:456
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:7334
long resetinterval
Definition: sig_pri.h:515
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:4195
unsigned int use_callerid
Definition: sig_analog.h:307
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:1499
Main Channel structure associated with a channel.
unsigned long display_flags_send
Definition: sig_pri.h:517
Music on hold handling.
char calling_nai
Definition: sig_ss7.h:338
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:696
struct ast_smdi_interface * smdi_iface
The SMDI interface to get SMDI messages from.
Definition: sig_analog.h:315
char cid_subaddr[AST_MAX_EXTENSION]
Caller ID subaddress from an incoming call.
Definition: chan_dahdi.h:537
const char * type
Type of monitor the callbacks belong to.
Definition: ccss.h:549
char * str
Subscriber phone number (Malloced)
Definition: channel.h:291
#define CIDCW_EXPIRE_SAMPLES
Definition: chan_dahdi.c:802
General Asterisk channel transcoding definitions.
#define PROC_DAHDI_OPT_NOWARN
Definition: chan_dahdi.c:18434
void ast_cc_agent_unregister(const struct ast_cc_agent_callbacks *callbacks)
Unregister a set of agent callbacks with the core.
Definition: ccss.c:1232
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1293
unsigned int permhidecallerid
TRUE if the outgoing caller ID is blocked/restricted/hidden.
Definition: chan_dahdi.h:339
unsigned int cancallforward
TRUE if support for call forwarding enabled. Dial *72 to enable call forwarding. Dial *73 to disable ...
Definition: chan_dahdi.h:238
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define CID_TYPE_MDMF
Definition: callerid.h:75
unsigned int priexclusive
Definition: sig_pri.h:283
static struct ast_jb_conf default_jbconf
Definition: chan_dahdi.c:618
Asterisk locking-related definitions:
int cc_qsig_signaling_link_req
Definition: sig_pri.h:561
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3310
int cid_ton
Caller ID Q.931 TON/NPI field values. Set by PRI. Zero otherwise.
Definition: chan_dahdi.h:533
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:579
void sig_pri_dial_complete(struct sig_pri_chan *pvt, struct ast_channel *ast)
DTMF dial string complete.
Definition: sig_pri.c:8726
int tonezone
Definition: chan_dahdi.h:167
unsigned int reoriginate
TRUE if FXS (FXO-signalled) channel should reoriginate for user to make a new call.
Definition: chan_dahdi.h:289
void * ast_mwi_unsubscribe(struct ast_mwi_subscriber *sub)
Unsubscribe from the stasis topic and MWI.
Definition: mwi.c:254
struct sig_pri_callback sig_pri_callbacks
Definition: chan_dahdi.c:3310
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:226
int congestion_devstate
Congestion device state of the span.
Definition: sig_pri.h:627
enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee, struct ast_channel *to_transfer_target)
Attended transfer.
Definition: bridge.c:4677
char * str
Subscriber phone number (Malloced)
Definition: channel.h:386
char chan_name[AST_CHANNEL_NAME]
int callwaitcas
TRUE if Call Waiting (CW) CPE Alert Signal (CAS) is being sent.
Definition: chan_dahdi.h:622
int firstdigit_timeout
Time (ms) to detect first digit (in an analog phone)
Definition: chan_dahdi.h:680
static const char dahdi_db[]
The AstDB family.
Definition: sig_pri.h:275
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
unsigned int dialing
TRUE if in the process of dialing digits or sending something.
Definition: chan_dahdi.h:258
#define AST_OPTION_TXGAIN
struct dahdi_subchannel subs[3]
Definition: chan_dahdi.h:131
unsigned int use_callingpres
Definition: sig_pri.h:286
int presentation
Q.931 presentation-indicator and screening-indicator encoded fields.
Definition: channel.h:295
int callwaitrings
Number of call waiting rings.
Definition: chan_dahdi.h:624
void ast_cc_config_params_destroy(struct ast_cc_config_params *params)
Free memory from CCSS configuration params.
Definition: ccss.c:692
unsigned int dpc
Definition: sig_ss7.h:202
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
Call Parking API.
struct ast_party_id id
Connected party ID.
Definition: channel.h:458
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int sig_pri_cc_agent_start_offer_timer(struct ast_cc_agent *agent)
Start the offer timer.
Definition: sig_pri.c:9467
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
#define SIG_PRI_DEBUG_NORMAL
Definition: sig_pri.h:36
char parkinglot[AST_MAX_EXTENSION]
Definition: chan_dahdi.h:518
int cid_signalling
Definition: chan_dahdi.h:588
unsigned int callwaitingcallerid
TRUE if send caller ID for Call Waiting.
Definition: chan_dahdi.h:231
static struct dahdi_pvt * fxo_pvt(struct ast_channel *chan)
Return DAHDI pivot if channel is FXO signalled.
Definition: chan_dahdi.c:2842
Device state management.
unsigned int use_callerid
Definition: sig_pri.h:285
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:169
unsigned int hardwaredtmf
TRUE if DTMF detection needs to be done by hardware.
Definition: chan_dahdi.h:295
char idleext[AST_MAX_EXTENSION]
Definition: sig_pri.h:550
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:340
#define DSP_DIGITMODE_DTMF
Definition: dsp.h:31
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:527
int interdigit_timeout
Time (ms) to detect following digits (in an analog phone)
Definition: chan_dahdi.h:685
int ast_dsp_get_tcount(struct ast_dsp *dsp)
Get tcount (Threshold counter)
Definition: dsp.c:1916
unsigned int hold_disconnect_transfer
TRUE if held calls are transferred on disconnect.
Definition: sig_pri.h:472
struct ast_json * blob
int cid_start
Definition: chan_dahdi.h:589
char unknownprefix[20]
Definition: sig_ss7.h:342
int ringt
Ring timeout timer??
Definition: chan_dahdi.h:603
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1493
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1216
char dnid[AST_MAX_EXTENSION]
Dialed Number Identifier.
Definition: chan_dahdi.h:547
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:280
#define CALLWAITING_SUPPRESS_SAMPLES
Definition: chan_dahdi.c:801
char mwi_vm_boxes[SIG_PRI_MAX_MWI_VM_NUMBER_STR]
Comma separated list of mailbox numbers sent over ISDN span for MWI.
Definition: sig_pri.h:536
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2471
int pattern[4]
Definition: dsp.h:68
#define DSP_DIGITMODE_MF
Definition: dsp.h:32
unsigned int transfer
TRUE if call transfer is enabled for the span.
Definition: sig_pri.h:478
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
unsigned int allow_call_waiting_calls
TRUE if we will allow incoming ISDN call waiting calls.
Definition: sig_pri.h:481
#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:990
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:3467
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
struct dahdi_pvt * master
Definition: chan_dahdi.h:135
int facilityenable
Definition: sig_pri.h:451
int ast_cc_is_config_param(const char *const name)
Is this a CCSS configuration parameter?
Definition: ccss.c:840
descriptor for a cli entry.
Definition: cli.h:171
Interface header for PRI signaling module.
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4708
int sig_pri_cc_monitor_status_rsp(struct ast_cc_monitor *monitor, enum ast_device_state devstate)
Status response to an ast_cc_monitor_status_request().
Definition: sig_pri.c:9917
static int ast_fdisset(struct pollfd *pfds, int fd, int maximum, int *start)
Helper function for migrating select to poll.
Definition: channel.h:2827
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
struct ast_mwi_subscriber * mwi_event_sub
Opaque event subscription parameters for message waiting indication support.
Definition: chan_dahdi.h:711
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
int sig_pri_cc_agent_callee_available(struct ast_cc_agent *agent)
Alert the caller that it is time to try recalling.
Definition: sig_pri.c:9709
unsigned int locallyblocked
Bitmask for the channel being locally blocked.
Definition: chan_dahdi.h:451
static int debug
Global debug status.
Definition: res_xmpp.c:441
AST_JSON_INT_T ast_json_int_t
Primarily used to cast when packing to an "I" type.
Definition: json.h:87
char nationalprefix[10]
Definition: sig_pri.h:508
q931_call * call
Definition: sig_pri.h:356
#define DSP_PROGRESS_TALK
Definition: dsp.h:39
char callwait_name[AST_MAX_EXTENSION]
Call waiting name.
Definition: chan_dahdi.h:543
float txdrc
Definition: chan_dahdi.h:164
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
Native DAHDI bridging support.
void ast_party_caller_set(struct ast_party_caller *dest, const struct ast_party_caller *src, const struct ast_set_party_caller *update)
Set the caller information based on another caller source.
Definition: channel.c:2007
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1758
unsigned int inservice
TRUE if channel is out of reset and ready.
Definition: chan_dahdi.h:442
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
int channel
Definition: sig_ss7.h:200
#define SRVST_TYPE_OOS
The out-of-service SERVICE state.
Definition: sig_pri.h:260
Structure for variables, used for configurations and for channel variables.
int buf_no
Definition: chan_dahdi.h:139
int dsp_features
DSP feature flags: DSP_FEATURE_xxx.
Definition: chan_dahdi.h:738
unsigned int mcid_send
TRUE if allow sending MCID request on this span.
Definition: sig_pri.h:496
struct ast_cc_config_params * cc_params
Definition: sig_pri.h:446
unsigned int dahditrcallerid
TRUE if we should use the callerid from incoming call on dahdi transfer.
Definition: chan_dahdi.h:408
unsigned int hidecalleridname
Definition: sig_pri.h:573
int sig_pri_cc_agent_status_req(struct ast_cc_agent *agent)
Request the status of the agent's device.
Definition: sig_pri.c:9584
unsigned int dnd
TRUE if Do-Not-Disturb is enabled, present only for non sig_analog.
Definition: chan_dahdi.h:262
unsigned int usefaxbuffers
Definition: chan_dahdi.h:276
int law_default
Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW.
Definition: chan_dahdi.h:554
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4257
int minidle
Definition: sig_pri.h:554
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1515
struct analog_callback analog_callbacks
Definition: chan_dahdi.c:3616
void ast_dsp_digitreset(struct ast_dsp *dsp)
Reset DTMF detector.
Definition: dsp.c:1810
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:1906
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)'s Caller*ID(tm) ...
Definition: callerid.c:1242
unsigned int immediate
TRUE if the channel should be answered immediately without attempting to gather any digits...
Definition: chan_dahdi.h:316
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:604
unsigned int enable_service_message_support
Definition: sig_pri.h:465
struct sig_ss7_callback sig_ss7_callbacks
unsigned int aoce_delayhangup
Definition: sig_pri.h:461
Interface header for SS7 signaling module.
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
Definition: pbx.c:6879
int cid_signalling
Definition: sig_analog.h:323
void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value)
ast_channel_state
ast_channel states
Definition: channelstate.h:35
char * str
Subscriber name (Malloced)
Definition: channel.h:264
unsigned int immediatering
TRUE if audible ringback should be provided when immediate = yes.
Definition: chan_dahdi.h:322
float cid_rxgain
Amount of gain to increase during caller id.
Definition: chan_dahdi.h:158
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:361
int callingpres
Definition: chan_dahdi.h:592
Definition of a media format.
Definition: format.c:43
int mastertrunkgroup
Definition: chan_dahdi.c:895
void ast_party_caller_free(struct ast_party_caller *doomed)
Destroy the caller party contents.
Definition: channel.c:2015
struct ast_dsp_busy_pattern busy_cadence
Busy cadence pattern description.
Definition: chan_dahdi.h:646
unsigned int ani_wink_time
INTEGER, length of time to wait before sending ANI wink in ms.
Definition: chan_dahdi.h:200
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
int bufsize
Definition: chan_dahdi.h:138
unsigned char valid
TRUE if the subaddress information is valid/present.
Definition: channel.h:328
unsigned int no_b_channel
TRUE if this interface has no B channel. (call hold and call waiting)
Definition: sig_pri.h:343
unsigned int inalarm
TRUE if channel is associated with a link that is down.
Definition: sig_ss7.h:288
pthread_t master
Definition: sig_ss7.h:319
unsigned int transfertobusy
TRUE if allowed to flash-transfer to busy channels.
Definition: chan_dahdi.h:413
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
#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.
int sig_pri_cc_agent_party_b_free(struct ast_cc_agent *agent)
Let the caller know that the callee has become free but that the caller cannot attempt to call back b...
Definition: sig_pri.c:9653
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
int ast_channel_get_up_time(struct ast_channel *chan)
Obtain how long it has been since the channel was answered.
Definition: channel.c:2845
unsigned int transfertobusy
Definition: sig_analog.h:306
unsigned int ani_info_digits
INTEGER, number of ANI INFO digits on a CAMA trunk. older switches use 1 INFO digit, newer switches use 2 INFO digits.
Definition: chan_dahdi.h:190
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
#define CID_MWI_TYPE_MDMF_FULL
Definition: callerid.h:83
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3421
int whichwink
Definition: chan_dahdi.h:697
int dialplan
Definition: sig_pri.h:504
int dchannels[SIG_PRI_NUM_DCHANS]
Definition: chan_dahdi.c:894
int localdialplan
Definition: sig_pri.h:505
char * origcid_num
Definition: chan_dahdi.h:538
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
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:107
char localprefix[20]
Definition: sig_pri.h:509
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define AST_OPTION_TDD
DAHDI internal API definitions.
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
int switchtype
Definition: sig_pri.h:556
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3326
int law
Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW.
Definition: chan_dahdi.h:556
char * str
Malloced subaddress string.
Definition: channel.h:313
int callwaitingrepeat
Definition: chan_dahdi.h:593
const char * data
int qsigchannelmapping
Definition: sig_pri.h:449
unsigned int mwioverride_active
TRUE if a manual MWI override is active for a channel.
Definition: chan_dahdi.h:435
char mwi_vm_numbers[SIG_PRI_MAX_MWI_VM_NUMBER_STR]
Comma separated list of voicemail access controlling numbers for MWI.
Definition: sig_pri.h:542
int sig_pri_load(const char *cc_type_name)
Load the sig_pri submodule.
Definition: sig_pri.c:10007
enum sig_pri_colp_signaling colp_send
Definition: sig_pri.h:514
unsigned int adsi
TRUE if ADSI (Analog Display Services Interface) available.
Definition: chan_dahdi.h:178
Common implementation-independent jitterbuffer stuff.
ast_transfer_result
Definition: bridge.h:1098
#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:856
struct ast_frame f
Definition: chan_dahdi.h:82
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:7422
unsigned int restartpending
Definition: chan_dahdi.h:357
const char * ast_redirecting_reason_name(const struct ast_party_redirecting_reason *data)
Convert redirecting reason value to text code.
Definition: callerid.c:1449
void sig_pri_chan_delete(struct sig_pri_chan *doomed)
Delete the sig_pri private channel structure.
Definition: sig_pri.c:9219
unsigned int inband_on_setup_ack
Definition: sig_pri.h:491
void * chan_pvt
Definition: sig_pri.h:374
struct dahdi_pvt * oprpeer
Definition: chan_dahdi.h:152
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:608
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7776
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
int ast_callerid_callwaiting_full_generate(unsigned char *buf, const char *name, const char *number, const char *ddn, int redirecting, int pres, int qualifier, struct ast_format *codec)
Generate Caller-ID spill but in a format suitable for Call Waiting(tm)'s Caller*ID(tm) ...
Definition: callerid.c:1253
float txgain
Software Tx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:162
static struct dahdi_pvt * ifend
Definition: chan_dahdi.c:923
struct timeval dtmfcid_delay
Definition: chan_dahdi.h:591
int code
enum AST_REDIRECTING_REASON value for redirection
Definition: channel.h:510
unsigned int hidecalleridname
TRUE if hide just the name not the number for legacy PBX use.
Definition: chan_dahdi.h:308
int inconference
Definition: chan_dahdi.h:136
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
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:10563
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:757
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
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:4190
#define ast_publish_mwi_state(mailbox, context, new_msgs, old_msgs)
Publish a MWI state update via stasis.
Definition: mwi.h:378
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:205
struct ast_frame_subclass subclass
unsigned int use_smdi
TRUE if SMDI (Simplified Message Desk Interface) is enabled.
Definition: sig_analog.h:313
unsigned int pulse
TRUE if we will pulse dial.
Definition: chan_dahdi.h:354
ast_mutex_t lock
Definition: sig_pri.h:616
int oprmode
Definition: chan_dahdi.h:151
Utility functions.
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
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.
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:3050
enum ast_cc_monitor_policies ast_get_cc_monitor_policy(struct ast_cc_config_params *config)
Get the cc_monitor_policy.
Definition: ccss.c:876
ast_group_t pickupgroup
Bitmapped pickup groups this belongs to.
Definition: chan_dahdi.h:569
All configuration options for http media cache.
char cid_name[AST_MAX_EXTENSION]
Caller ID name from an incoming call.
Definition: chan_dahdi.h:535
struct ast_channel * owner
Definition: sig_analog.h:277
char finaldial[64]
Second part of SIG_FEATDMF_TA wink operation.
Definition: chan_dahdi.h:699
void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
Set number of required cadences for busy.
Definition: dsp.c:1793
unsigned int hwtxgain_enabled
TRUE if hardware Tx gain set by Asterisk.
Definition: chan_dahdi.h:469
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
int cc_qsig_signaling_link_rsp
Definition: sig_pri.h:562
Number structure.
Definition: app_followme.c:154
enum ama_flags ast_channel_string2amaflag(const char *flag)
Convert a string to a detail record AMA flag.
Definition: channel.c:4360
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:316
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:1113
static int dahdi_wait_event(int fd)
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition: chan_dahdi.c:782
struct ast_party_id id
Caller party ID.
Definition: channel.h:420
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:1162
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:184
Configuration File Parser.
#define NEED_MFDETECT(p)
Signaling types that need to use MF detection should be placed in this macro.
Definition: chan_dahdi.c:646
#define DSP_DIGITMODE_RELAXDTMF
Definition: dsp.h:37
ast_mutex_t lock
Definition: sig_ss7.h:320
int dtmfcid_holdoff_state
Definition: chan_dahdi.h:590
unsigned int didtdd
Definition: chan_dahdi.h:251
unsigned int bufferoverrideinuse
Definition: chan_dahdi.h:278
static ast_mutex_t monlock
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing some...
Definition: chan_dahdi.c:757
char smdi_port[SMDI_MAX_FILENAME_LEN]
The serial port to listen for SMDI data on.
Definition: chan_dahdi.c:974
int polarity
Current line interface polarity. POLARITY_IDLE, POLARITY_REV.
Definition: chan_dahdi.h:736
unsigned int hanguponpolarityswitch
TRUE if the call will be considered "hung up" on a polarity reversal.
Definition: chan_dahdi.h:285
void sig_pri_cc_agent_destructor(struct ast_cc_agent *agent)
Destroy private data on the agent.
Definition: sig_pri.c:9736
unsigned int callreturn
TRUE if call return is enabled. (*69, if your dialplan doesn't catch this first)
Definition: chan_dahdi.h:219
char unknownprefix[20]
Definition: sig_pri.h:511
u-Law to Signed linear conversion
unsigned int transfer
TRUE if call transfer is enabled.
Definition: chan_dahdi.h:382
#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
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:264
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:9843
Definition: logger.c:172
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_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:14146
struct ast_module * self
Definition: module.h:356
struct ast_party_id ani
Automatic Number Identification (ANI)
Definition: channel.h:427
int amaflags
Definition: chan_dahdi.h:701
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 ast_tdd_gen_ecdisa(unsigned char *outbuf, int len)
Definition: tdd.c:148
struct dahdi_pvt * slaves[MAX_SLAVES]
Definition: chan_dahdi.h:134
unsigned int inband_on_proceeding
Definition: sig_pri.h:493
int sig_pri_cc_monitor_unsuspend(struct ast_cc_monitor *monitor)
Unsuspend monitoring.
Definition: sig_pri.c:9887
struct dahdi_pvt::@112 echocancel
Echo cancel parameters.
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:761
void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force)
Set the source of the hangup in this channel and it's bridge.
Definition: channel.c:2499
Asterisk file paths, configured in asterisk.conf.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
const char * src
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3475
char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Voice mailbox location.
Definition: chan_dahdi.h:709
#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:667
char echorest[20]
Filled with 'w'. XXX Purpose??
Definition: chan_dahdi.h:636
int cidlen
Length of the cidspill buffer containing samples.
Definition: chan_dahdi.h:601
#define SRVST_DBKEY
Persistent Service State.
Definition: sig_pri.h:258
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
struct timeval flashtime
Definition: chan_dahdi.h:692
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
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:2378
#define SIG_SS7_DEBUG
Definition: sig_ss7.h:43
struct dahdi_confinfo saveconf
Definition: chan_dahdi.h:132
int sig_pri_is_chan_available(struct sig_pri_chan *pvt)
Determine if a private channel structure is available.
Definition: sig_pri.c:1218
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
static struct dahdi_pvt * round_robin[64]
Definition: chan_dahdi.c:3690
unsigned int mwimonitoractive
TRUE if an MWI monitor thread is currently active.
Definition: chan_dahdi.h:431
int echotraining
Echo training time. 0 = disabled.
Definition: chan_dahdi.h:634
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define AST_MAX_EXTENSION
Definition: channel.h:134
int cc_ptmp_recall_mode
Definition: sig_pri.h:560
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
struct stasis_cache * ast_mwi_state_cache(void)
Backend cache for ast_mwi_topic_cached().
Definition: mwi.c:94
void ast_party_number_init(struct ast_party_number *init)
Initialize the given number structure.
Definition: channel.c:1644
Caller Party information.
Definition: channel.h:418
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2969
int cid_ani2
Automatic Number Identification code from PRI.
Definition: chan_dahdi.h:524
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:701
ast_mutex_t lock
Definition: chan_dahdi.h:125
#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:87
static int ringt_base
Configured ring timeout base.
Definition: chan_dahdi.c:811
In case you didn't read that giant block of text above the mansession_session struct, the 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:1785
#define MIN_MS_SINCE_FLASH
Definition: chan_dahdi.c:803
unsigned int immediatering
Definition: sig_analog.h:299
struct dahdi_vmwi_info mwisend_setting
Definition: chan_dahdi.h:715
static ast_mutex_t iflock
Protect the interface list (of dahdi_pvt's)
Definition: chan_dahdi.c:746
unsigned char * cidspill
Analog caller ID waveform sample buffer.
Definition: chan_dahdi.h:597
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:334
int ast_callerid_full_generate(unsigned char *buf, const char *name, const char *number, const char *ddn, int redirecting, int pres, int qualifier, int format, struct ast_format *codec)
Generate Caller-ID spill from the "callerid" field of asterisk (in e-mail address like format) ...
Definition: callerid.c:1247
char internationalprefix[10]
Definition: sig_pri.h:507
static struct stasis_rest_handlers events
REST handler for /api-docs/events.json.
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:801
void sig_pri_cc_monitor_destructor(void *monitor_pvt)
Destroy PRI private data on the monitor.
Definition: sig_pri.c:9985
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:283
void ast_channel_amaflags_set(struct ast_channel *chan, enum ama_flags value)
unsigned int busydetect
TRUE if busy detection is enabled. (Listens for the beep-beep busy pattern.)
Definition: chan_dahdi.h:206
void * chan_pvt
Definition: sig_ss7.h:190
unsigned int mwimonitor_fsk
TRUE if the FXO port monitors for fsk type MWI indications from the other end.
Definition: chan_dahdi.h:423
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
int sig_pri_cc_agent_start_monitoring(struct ast_cc_agent *agent)
Begin monitoring a busy device.
Definition: sig_pri.c:9682
#define ast_debug(level,...)
Log a DEBUG message.
char privateprefix[20]
Definition: sig_pri.h:510
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:833
analog_sub
Definition: sig_analog.h:108
int ast_dsp_get_tstate(struct ast_dsp *dsp)
Get tstate (Tone State)
Definition: dsp.c:1911
void * no_b_chan_end
Definition: sig_pri.h:612
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:4175
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
unsigned int use_callingpres
TRUE if we will use the calling presentation setting from the Asterisk channel for outgoing calls...
Definition: chan_dahdi.h:397
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
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
void sig_pri_cc_agent_req_rsp(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
Response to a CC request.
Definition: sig_pri.c:9514
char cid_tag[AST_MAX_EXTENSION]
Caller ID tag from incoming call.
Definition: chan_dahdi.h:531
int prilogicalspan
Definition: chan_dahdi.c:896
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3274
char subscriberprefix[20]
Definition: sig_ss7.h:341
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Definition: channel.h:628
#define AST_LIST_MOVE_CURRENT(newhead, field)
Move the current list entry to another list.
Definition: linkedlists.h:582
int overlapdial
Definition: sig_pri.h:448
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:10451
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition: channel.c:1139
int sig_pri_is_alarm_ignored(struct sig_pri_span *pri)
Determine if layer 1 alarms are ignored.
Definition: sig_pri.c:9189
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 AST_CC_GENERIC_MONITOR_TYPE
Definition: ccss.h:455
static int load_module(void)
Load the module.
Definition: chan_dahdi.c:20279
#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:291
unsigned int calledsubscriberheld
TRUE if Called Subscriber held is enabled. This allows a single incoming call to hold a DAHDI channel...
Definition: chan_dahdi.h:213
unsigned int use_callingpres
Definition: sig_pri.h:578
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:235
unsigned int use_smdi
TRUE if SMDI (Simplified Message Desk Interface) is enabled.
Definition: chan_dahdi.h:479
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define AST_OPTION_ECHOCAN
unsigned int threewaysilenthold
TRUE if a three way dial tone should time out to silence.
Definition: chan_dahdi.h:373
#define DEFAULT_DIALTONE_DETECT_TIMEOUT
Definition: chan_dahdi.c:805
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:8057
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
struct dahdi_pvt * prev
Definition: chan_dahdi.h:170
struct ast_party_subaddress subaddress
Subscriber subaddress.
Definition: channel.h:344
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
int waitfordialtoneduration
Transient variable. Stored off waitfordialtone duration at runtime.
Definition: chan_dahdi.h:664
struct timeval waitingfordt
Definition: chan_dahdi.h:691
const char * type
Type of agent the callbacks belong to.
Definition: ccss.h:857
#define AST_OPTION_DIGIT_DETECT
void sig_pri_stop_pri(struct sig_pri_span *pri)
Stop PRI span.
Definition: sig_pri.c:8872
#define DSP_DIGITMODE_MUTEMAX
Definition: dsp.h:36
static void notify_message(char *mailbox, int thereornot)
Send MWI state change.
Definition: chan_dahdi.c:3553
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:694
int busycount
Number of times to see "busy" tone before hanging up.
Definition: chan_dahdi.h:641
unsigned int destroy
TRUE if the channel is to be destroyed on hangup. (Used by pseudo channels.)
Definition: chan_dahdi.h:250
struct ast_namedgroups * ast_get_namedgroups(const char *s)
Create an ast_namedgroups set with group names from comma separated string.
Definition: channel.c:7675
int new_msgs
Definition: mwi.h:459
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
unsigned int faxhandled
TRUE if a fax tone has already been handled.
Definition: chan_dahdi.h:274
int ast_pickup_call(struct ast_channel *chan)
Pickup a call.
Definition: pickup.c:199
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: utils.c:2199
#define PROC_DAHDI_OPT_NOCHAN
Definition: chan_dahdi.c:18432
char mohinterpret[MAX_MUSICCLASS]
The configured music-on-hold class to use for calls.
Definition: chan_dahdi.h:512
pthread_t master
Definition: sig_pri.h:615
void ast_party_caller_set_init(struct ast_party_caller *init, const struct ast_party_caller *guide)
Initialize the given caller structure using the given guide for a set update operation.
Definition: channel.c:1999
Support for dynamic strings.
Definition: strings.h:623
enum DAHDI_IFLIST which_iflist
Definition: chan_dahdi.h:168
char cid_num[AST_MAX_EXTENSION]
Caller ID number from an incoming call.
Definition: chan_dahdi.h:526
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
unsigned int force_restart_unavailable_chans
TRUE if forcing RESTART when receive cause 44 on this span.
Definition: sig_pri.h:499
#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:553
int plan
Q.931 Type-Of-Number and Numbering-Plan encoded fields.
Definition: channel.h:293
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
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: utils.c:2281
void sig_pri_unload(void)
Unload the sig_pri submodule.
Definition: sig_pri.c:10030
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
#define SIG_SS7_NUM_DCHANS
Definition: sig_ss7.h:56
void ast_party_name_init(struct ast_party_name *init)
Initialize the given name structure.
Definition: channel.c:1591
unsigned int use_callerid
TRUE if caller ID is used on this channel.
Definition: chan_dahdi.h:390
int ani2
Automatic Number Identification 2 (Info Digits)
Definition: channel.h:433
#define SUB_REAL
Definition: chan_dahdi.h:57
int confno
Definition: chan_dahdi.h:557
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:1804
unsigned int inbanddisconnect
Definition: sig_pri.h:468
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:239
int propconfno
Definition: chan_dahdi.h:559
struct stasis_message_type * ast_mwi_state_type(void)
Get the Stasis Message Bus API message type for MWI messages.
const ast_string_field name
int cpndialplan
Definition: sig_pri.h:506
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:7766
struct sig_pri_chan * pvts[SIG_PRI_MAX_CHANNELS]
Definition: sig_pri.h:614
void analog_delete(struct analog_pvt *doomed)
Delete the analog private structure.
Definition: sig_analog.c:4104
void ast_party_name_free(struct ast_party_name *doomed)
Destroy the party name contents.
Definition: channel.c:1638
#define READ_SIZE
Definition: chan_dahdi.c:794
char idledial[AST_MAX_EXTENSION]
Definition: sig_pri.h:552
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:2501
unsigned int immediate
Definition: sig_pri.h:282
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
Definition: linkedlists.h:429
#define ast_module_ref(mod)
Hold a reference to the module.
Definition: module.h:457
#define DEFAULT_CIDRINGS
Typically, how many rings before we should send Caller*ID.
Definition: chan_dahdi.c:640
struct ast_format_cap * capabilities
Definition: channel.h:632
char * origcid_name
Definition: chan_dahdi.h:539
char exten[AST_MAX_EXTENSION]
Extension to use in the dialplan.
Definition: chan_dahdi.h:502
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:410
int muting
TRUE if confrence is muted.
Definition: chan_dahdi.h:763
int distinctivering
Definition: chan_dahdi.h:719
int ast_parking_provider_registered(void)
Check whether a parking provider is registered.
Definition: parking.c:241
unsigned long display_flags_receive
Definition: sig_pri.h:518
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:809
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1768
union ast_frame::@224 data
unsigned int usedistinctiveringdetection
TRUE if distinctive rings are to be detected.
Definition: chan_dahdi.h:403
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)
Output AMI show spans response events for the given PRI span.
Definition: sig_pri.c:7540
char call_forward[AST_MAX_EXTENSION]
Accumulated call forwarding number.
Definition: chan_dahdi.h:704
char * command
Definition: cli.h:186
unsigned int hidecalleridname
Definition: sig_pri.h:281
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
int sig_pri_cc_agent_stop_ringing(struct ast_cc_agent *agent)
Request for an agent's phone to stop ringing.
Definition: sig_pri.c:9619
unsigned int append_msn_to_user_tag
Definition: sig_pri.h:489
#define AST_CHANNEL_NAME
Definition: channel.h:171
unsigned int faxdetect_timeout
The number of seconds into call to disable fax detection. (0 = disabled)
Definition: chan_dahdi.h:675
unsigned int restrictcid
TRUE if caller ID is restricted.
Definition: chan_dahdi.h:363
char initial_user_tag[AST_MAX_EXTENSION]
Initial user tag for party id's sent from this device driver.
Definition: sig_pri.h:548
static int dahdi_answer(struct ast_channel *ast)
Definition: chan_dahdi.c:6699
char called_nai
Definition: sig_ss7.h:337
static int get_alarms(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7567
unsigned int dahditrcallerid
Definition: sig_analog.h:296
static int dahdi_get_event(int fd)
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition: chan_dahdi.c:773
#define AST_OPTION_AUDIO_MODE
char mwi_mailboxes[SIG_PRI_MAX_MWI_MAILBOX_STR]
Comma separated list of mailboxes to indicate MWI.
Definition: sig_pri.h:529
Call Completion Supplementary Services API.
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
char context[AST_MAX_CONTEXT]
The configured context for incoming calls.
Definition: chan_dahdi.h:491
unsigned int remotelyblocked
Bitmask for the channel being remotely blocked. 1 maintenance, 2 blocked in hardware.
Definition: chan_dahdi.h:460
Channel configuration from chan_dahdi.conf . This struct is used for parsing the [channels] section o...
Definition: chan_dahdi.c:952
int redirecting_reason
Definition: sig_analog.h:356
unsigned int threewaycalling
TRUE if three way calling is enabled.
Definition: chan_dahdi.h:368
int msgstate
-1 = unknown, 0 = no messages, 1 = new messages available
Definition: sig_analog.h:284
SMDI support for Asterisk.
unsigned int permhidecallerid
Definition: sig_analog.h:301
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
int wanted_channels_start
Don't create channels below this number.
Definition: chan_dahdi.c:980
int l2_persistence
Definition: sig_pri.h:454
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:854
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:427
int stripmsd
Number of most significant digits/characters to strip from the dialed number.
Definition: chan_dahdi.h:615
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:1941
char msn_list[AST_MAX_EXTENSION]
Definition: sig_pri.h:549
struct ast_namedgroups * named_callgroups
Named call groups this belongs to.
Definition: chan_dahdi.h:574
struct ast_party_redirecting_reason reason
Reason for the redirection.
Definition: channel.h:542
struct ast_smdi_interface * smdi_iface
The SMDI interface to get SMDI messages from.
Definition: chan_dahdi.h:482
Structure used to handle boolean flags.
Definition: utils.h:199
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:582
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2426
char nationalprefix[10]
Definition: sig_ss7.h:340
struct ast_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel's bridge pointer.
Definition: channel.c:10582
struct timeval delivery
int buf_policy
Definition: chan_dahdi.h:140
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
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:310
int numchans
Definition: sig_pri.h:613
#define CHECK_BLOCKING(c)
Set the blocking indication on the channel.
Definition: channel.h:2871
#define CALLWAITING_REPEAT_SAMPLES
Definition: chan_dahdi.c:800
int fake_event
Holding place for event injected from outside normal operation.
Definition: chan_dahdi.h:722
const char * usage
Definition: cli.h:177
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:483
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...
Definition: astman.c:88
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:245
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3175
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:2356
void callerid_free(struct callerid_state *cid)
This function frees callerid_state cid.
Definition: callerid.c:833
int wanted_channels_end
Don't create channels above this number (infinity by default)
Definition: chan_dahdi.c:986
int sig_pri_cc_monitor_req_cc(struct ast_cc_monitor *monitor, int *available_timer_id)
Request CCSS.
Definition: sig_pri.c:9818
char * tag
User-set "tag".
Definition: channel.h:354
unsigned int mwimonitor_neon
TRUE if the FXO port monitors for neon type MWI indications from the other end.
Definition: chan_dahdi.h:418
#define ANALOG_FIRST_DIGIT_TIMEOUT
Default time (ms) to detect first digit.
Definition: sig_analog.h:38
STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_sync_message_type)
A message type used to synchronize with the CDR topic.
int waitfordialtone
Number of milliseconds to wait for dialtone.
Definition: chan_dahdi.h:656
struct tdd_state * tdd
Definition: chan_dahdi.h:702
unsigned int locallyblocked
Bitmask for the channel being locally blocked.
Definition: sig_ss7.h:228
unsigned int immediate
Definition: sig_ss7.h:221
float hwtxgain
Hardware Tx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:156
Structure that contains information regarding a channel in a bridge.
int waitfordialtonetemp
Transient variable. Same as waitfordialtone, but temporarily set for a specific call, rather than permanently for the channel.
Definition: chan_dahdi.h:660
#define AST_OPTION_FAX_DETECT
static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
Definition: chan_dahdi.c:6843
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3162
int sig_pri_cc_agent_init(struct ast_cc_agent *agent, struct sig_pri_chan *pvt_chan)
PRI CC agent initialization.
Definition: sig_pri.c:9423
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:407
void sig_pri_chan_alarm_notify(struct sig_pri_chan *p, int noalarm)
Notify new alarm status.
Definition: sig_pri.c:9163
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:476
unsigned int priexclusive
Definition: sig_pri.h:575
static int has_voicemail(const char *mailbox, const char *folder)
Determines if the given folder has messages.
void callerid_get_with_redirecting(struct callerid_state *cid, char **name, char **number, int *flags, int *redirecting)
Extract info out of callerID state machine. Flags are listed above.
Definition: callerid.c:189
struct dahdi_distRings drings
Distinctive Ring data.
Definition: chan_dahdi.h:485
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
unsigned int echocanon
TRUE if echo cancellation is turned on.
Definition: chan_dahdi.h:272
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:80
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
unsigned int callwaitingcallerid
Definition: sig_analog.h:309
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:235
static struct dahdi_pvt * iflist
Definition: chan_dahdi.c:922
int num_call_waiting_calls
Number of outstanding call waiting calls.
Definition: sig_pri.h:588
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
Definition: channel.c:10564
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
Definition: utils.c:2216
unsigned int call_qualifier
Definition: sig_analog.h:349
int cidcwexpire
Definition: chan_dahdi.h:594
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1840
int ignore_failed_channels
Definition: chan_dahdi.c:968
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:952
void sig_pri_sendtext(struct sig_pri_chan *p, const char *text)
Send display text.
Definition: sig_pri.c:9391
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7386
Asterisk MWI API.
int sig_pri_cc_monitor_cancel_available_timer(struct ast_cc_monitor *monitor, int *sched_id)
Cancel the running available timer.
Definition: sig_pri.c:9962
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:6969
struct ast_party_dialed::@206 number
Dialed/Called number.
int discardremoteholdretrieval
Definition: sig_pri.h:450
int cid_suppress_expire
Definition: chan_dahdi.h:595
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.
unsigned int use_callerid
Definition: sig_pri.h:577
unsigned int doreoriginate
Internal flag for if we should actually process a reorigination.
Definition: chan_dahdi.h:293
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:4755
ast_group_t groupmatch
Definition: chan_dahdi.c:13726
struct ast_variable * vars
Channel variable list with associated values to set when a channel is created.
Definition: chan_dahdi.h:584
unsigned int dialednone
TRUE if analog type line dialed no digits in Dial()
Definition: chan_dahdi.h:253
Data structure associated with a single frame of data.
unsigned int manages_span_alarms
TRUE if the channel alarms will be managed also as Span ones.
Definition: chan_dahdi.h:465
Internal Asterisk hangup causes.
unsigned int priindication_oob
TRUE if PRI congestion/busy indications are sent out-of-band.
Definition: chan_dahdi.h:344
#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
char internationalprefix[10]
Definition: sig_ss7.h:339
struct timeval polaritydelaytv
Start delay time if polarityonanswerdelay is nonzero.
Definition: chan_dahdi.h:729
Abstract JSON element (object, array, string, int, ...).
unsigned int hidecallerid
TRUE if the outgoing caller ID is blocked/hidden.
Definition: chan_dahdi.h:302
char callwait_num[AST_MAX_EXTENSION]
Call waiting number.
Definition: chan_dahdi.h:541
struct isup_call * ss7call
Opaque libss7 call control structure.
Definition: sig_ss7.h:195
int faxbuf_policy
Definition: chan_dahdi.h:142
#define AST_OPTION_TONE_VERIFY
char cid_ani[AST_MAX_EXTENSION]
Automatic Number Identification number (Alternate PRI caller ID number)
Definition: chan_dahdi.h:521
unsigned int layer1_ignored
Definition: sig_pri.h:484
Definition: search.h:40
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:342
void ast_cc_monitor_unregister(const struct ast_cc_monitor_callbacks *callbacks)
Unregister a set of monitor callbacks with the core.
Definition: ccss.c:1195
void * no_b_chan_iflist
Definition: sig_pri.h:607
unsigned int echocanbridged
TRUE if echo cancellation enabled when bridged.
Definition: chan_dahdi.h:270
int polarityonanswerdelay
Minimal time period (ms) between the answer polarity switch and hangup polarity switch.
Definition: chan_dahdi.h:727
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
enum ast_frame_type frametype
float rxgain
Software Rx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:160
Callbacks defined by CC monitors.
Definition: ccss.h:542
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:279
int tdd_generate(struct tdd_state *tdd, unsigned char *buf, const char *string)
Definition: tdd.c:296
void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message.
Call Parking and Pickup API Includes code and algorithms from the Zapata library. ...
struct analog_subchannel subs[3]
Definition: sig_analog.h:279
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:12493
struct ast_format * format
static const char dahdi_pri_cc_type[]
Definition: chan_dahdi.c:904
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
void callerid_get_dtmf(char *cidstring, char *number, int *flags)
Get and parse DTMF-based callerid.
Definition: callerid.c:211
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
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2458
#define AST_LIST_HEAD_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD.
Definition: linkedlists.h:234
void ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()'s, .'s, and -'s...
Definition: callerid.c:1101
struct callerid_state * callerid_new(int cid_signalling)
Create a callerID state machine.
Definition: callerid.c:130
The structure that contains MWI state.
Definition: mwi.h:455
int radio
Nonzero if the signaling type is sent over a radio.
Definition: chan_dahdi.h:148
int new_chan_seq
Definition: sig_pri.h:596
int aoc_passthrough_flag
Definition: sig_pri.h:460
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:191
Say numbers and dates (maybe words one day too)
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
unsigned int allocated
TRUE when this channel is allocated.
Definition: sig_pri.h:339
char rdnis[AST_MAX_EXTENSION]
Redirecting Directory Number Information Service (RDNIS) number.
Definition: chan_dahdi.h:545
Bridging API.
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1258
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:601
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3389
Asterisk module definitions.
#define SRVST_NEAREND
SRVST_NEAREND is used to indicate that the near end was put out-of-service.
Definition: sig_pri.h:268
int callprogress
Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
Definition: chan_dahdi.h:651
float hwrxgain
Hardware Rx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:154
#define DEFAULT_RINGT
Definition: chan_dahdi.c:804
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
Definition: json.c:332
char language[MAX_LANGUAGE]
Language configured for calls.
Definition: chan_dahdi.h:507
unsigned int hwrxgain_enabled
TRUE if hardware Rx gain set by Asterisk.
Definition: chan_dahdi.h:467
ast_group_t group
Bitmapped groups this belongs to.
Definition: chan_dahdi.h:552
#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:941
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:235
int dialtone_detect
Number of frames to watch for dialtone in incoming calls.
Definition: chan_dahdi.h:669
int sig_pri_cc_agent_stop_offer_timer(struct ast_cc_agent *agent)
Stop the offer timer.
Definition: sig_pri.c:9488
void sig_pri_extract_called_num_subaddr(struct sig_pri_chan *p, const char *rdest, char *called, size_t called_buff_size)
Extract the called number and subaddress from the dial string.
Definition: sig_pri.c:7694
time_t guardtime
Definition: chan_dahdi.h:587
int dialmode
Definition: chan_dahdi.h:149
int ast_active_channels(void)
returns number of active/allocated channels
Definition: channel.c:499
unsigned int inalarm
TRUE if in an alarm condition.
Definition: chan_dahdi.h:324
Persistent data storage (akin to *doze registry)
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
int datetime_send
Configured date/time ie send policy option.
Definition: sig_pri.h:502
int channel
Definition: chan_dahdi.h:585
static char mwimonitornotify[PATH_MAX]
Definition: chan_dahdi.c:721
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:297
int sendcalleridafter
Send caller ID on FXS after this many rings. Set to 1 for US.
Definition: chan_dahdi.h:734
struct pri * pri
Definition: sig_pri.h:602
General jitterbuffer configuration.
Definition: abstract_jb.h:69
unsigned int immediate
Definition: sig_pri.h:574
int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
Set zone for doing progress detection.
Definition: dsp.c:1892
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:4346
unsigned int calledsubscriberheld
Definition: sig_analog.h:292
ast_group_t callgroup
Bitmapped call groups this belongs to.
Definition: chan_dahdi.h:564
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
char dialdest[256]
Delayed dialing for E911. Overlap digits for ISDN.
Definition: chan_dahdi.h:713
unsigned int permcallwaiting
Definition: sig_analog.h:300
unsigned int mate
TRUE if TDD in MATE mode.
Definition: chan_dahdi.h:326
char exten[AST_MAX_EXTENSION]
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:640
unsigned int canpark
TRUE if support for call parking is enabled.
Definition: chan_dahdi.h:243
int ast_dsp_set_digitmode(struct ast_dsp *dsp, int digitmode)
Set digit mode.
Definition: dsp.c:1857
int channel
Definition: sig_pri.h:290
int fds[SIG_PRI_NUM_DCHANS]
Definition: sig_pri.h:457
int sig_pri_cc_monitor_suspend(struct ast_cc_monitor *monitor)
Suspend monitoring.
Definition: sig_pri.c:9861
int trunkgroup
Definition: sig_pri.h:558
unsigned int ani_timeout
INTEGER, length of ANI failure timeout in ms.
Definition: chan_dahdi.h:195
unsigned int pulsedial
TRUE if a pulsed digit was detected. (Pulse dial phone detected)
Definition: chan_dahdi.h:356
void ast_manager_publish_event(const char *type, int class_type, struct ast_json *obj)
Publish an event to AMI.
Definition: manager.c:2063
char mohsuggest[MAX_MUSICCLASS]
Suggested music-on-hold class for peer channel to use for calls.
Definition: chan_dahdi.h:517
unsigned int mwisend_rpas
Definition: chan_dahdi.h:717
Media Format Cache API.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
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:570
char begindigit
DTMF digit in progress. 0 when no digit in progress.
Definition: chan_dahdi.h:761
#define SRVST_FAREND
SRVST_FAREND is used to indicate that the far end was taken out-of-service.
Definition: sig_pri.h:270
Configuration relating to call pickup.
#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 'n' samples.
Definition: callerid.c:271
unsigned int mwioverride_disposition
Manual MWI disposition (on/off)
Definition: chan_dahdi.h:437
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_dahdi.h:700
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:3431
int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, const char *rdest, int timeout, int layer1)
Definition: sig_pri.c:7780
#define SUB_CALLWAIT
Definition: chan_dahdi.h:58
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:342
int tdd_feed(struct tdd_state *tdd, unsigned char *ubuf, int samples)
Definition: tdd.c:161
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:429
unsigned int mwisendactive
TRUE if a MWI message sending thread is active.
Definition: chan_dahdi.h:433