Asterisk - The Open Source Telephony Project GIT-master-f45f878
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"
119#include "asterisk/abstract_jb.h"
120#include "asterisk/smdi.h"
121#include "asterisk/devicestate.h"
122#include "asterisk/paths.h"
123#include "asterisk/ccss.h"
125#include "asterisk/bridge.h"
127#include "asterisk/parking.h"
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
605static 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};
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
648static 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
669static 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
685static int num_cadence = 4;
687
688static int has_pseudo;
689
690static 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
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 */
709static 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
717static char defaultcic[64] = "";
718static char defaultozz[64] = "";
719
720/*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
721static char mwimonitornotify[PATH_MAX] = "";
722#ifndef HAVE_DAHDI_LINEREVERSE_VMWI
723static int mwisend_rpas = 0;
724#endif
725
726static char progzone[10] = "";
727
730
731static int numbufs = 4;
732
733static int mwilevel = 512;
734static int dtmfcid_level = 256;
735
736#define REPORT_CHANNEL_ALARMS 1
737#define REPORT_SPAN_ALARMS 2
739
740#ifdef HAVE_PRI
741static int pridebugfd = -1;
742static char pridebugfilename[1024] = "";
743#endif
744
745/*! \brief Protect the interface list (of dahdi_pvt's) */
747
748
749static int ifcount = 0;
750
751#ifdef HAVE_PRI
752AST_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. */
758
759/*! \brief This is the thread for the monitor which checks for input on the channels
760 which are not currently in use. */
765static int ss_thread_count = 0;
766static int num_restart_pending = 0;
767
768static int restart_monitor(void);
769
770static int dahdi_sendtext(struct ast_channel *c, const char *text);
771
772/*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
773static 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 */
782static 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
815struct dahdi_ss7 {
816 struct sig_ss7_linkset ss7;
817};
818
819static struct dahdi_ss7 linksets[NUM_SPANS];
820
821static int cur_ss7type = -1;
822static int cur_slc = -1;
823static int cur_linkset = -1;
824static int cur_pointcode = -1;
825static int cur_cicbeginswith = -1;
826static int cur_adjpointcode = -1;
827static int cur_networkindicator = -1;
828static int cur_defaultdpc = -1;
829#endif /* defined(HAVE_SS7) */
830
831#ifdef HAVE_OPENR2
832struct 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 */
867struct 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
878struct r2link_entry {
879 struct dahdi_mfcr2 mfcr2;
880 AST_LIST_ENTRY(r2link_entry) list;
881};
882static AST_LIST_HEAD_STATIC(r2links, r2link_entry);
883static struct r2links nodev_r2links = AST_LIST_HEAD_INIT_VALUE;
884
885
886/* how many r2links have been malloc'd */
887static int r2links_count = 0;
888
889#endif /* HAVE_OPENR2 */
890
891#ifdef HAVE_PRI
892
893struct 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
900static struct dahdi_pri pris[NUM_SPANS];
901
902#if defined(HAVE_PRI_CCSS)
903/*! DAHDI PRI CCSS agent and monitor type name. */
904static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
905#endif /* defined(HAVE_PRI_CCSS) */
906
907#else
908/*! Shut up the compiler */
909struct dahdi_pri;
910#endif
911
912/* Polarity states */
913#define POLARITY_IDLE 0
914#define POLARITY_REV 1
915
916const char * const subnames[] = {
917 "Real",
918 "Callwait",
919 "Threeway"
920};
921
922static struct dahdi_pvt *iflist = NULL; /*!< Main interface list start */
923static struct dahdi_pvt *ifend = NULL; /*!< Main interface list end */
924
925#if defined(HAVE_PRI)
926struct doomed_pri {
927 struct sig_pri_span *pri;
928 AST_LIST_ENTRY(doomed_pri) list;
929};
930static AST_LIST_HEAD_STATIC(doomed_pris, doomed_pri);
931
932static void pri_destroy_span(struct sig_pri_span *pri);
933
934static 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 */
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 */
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
1136static 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);
1139static int dahdi_digit_begin(struct ast_channel *ast, char digit);
1140static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
1141static int dahdi_sendtext(struct ast_channel *c, const char *text);
1142static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout);
1143static int dahdi_hangup(struct ast_channel *ast);
1144static int dahdi_answer(struct ast_channel *ast);
1145static struct ast_frame *dahdi_read(struct ast_channel *ast);
1146static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
1147static struct ast_frame *dahdi_exception(struct ast_channel *ast);
1148static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
1149static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
1150static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
1151static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
1152static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
1153static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
1154static int dahdi_devicestate(const char *data);
1155static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
1156
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
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
1234{
1235 switch (tone) {
1237 return DAHDI_TONE_RINGTONE;
1239 return DAHDI_TONE_STUTTER;
1241 return DAHDI_TONE_CONGESTION;
1243 return DAHDI_TONE_DIALTONE;
1245 return DAHDI_TONE_DIALRECALL;
1246 case ANALOG_TONE_INFO:
1247 return DAHDI_TONE_INFO;
1248 default:
1249 return -1;
1250 }
1251}
1252
1253static 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;
1262 index = SUB_CALLWAIT;
1263 break;
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 */
1283static void release_doomed_pris(void)
1284{
1285#ifdef HAVE_PRI
1286 struct doomed_pri *entry;
1287
1288 AST_LIST_LOCK(&doomed_pris);
1289 while ((entry = AST_LIST_REMOVE_HEAD(&doomed_pris, list))) {
1290 /* The span destruction must be done with this lock not held */
1291 AST_LIST_UNLOCK(&doomed_pris);
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);
1296 AST_LIST_LOCK(&doomed_pris);
1297 }
1298 AST_LIST_UNLOCK(&doomed_pris);
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 */
1313static void pri_queue_for_destruction(struct sig_pri_span *pri)
1314{
1315 struct doomed_pri *entry;
1316
1317 AST_LIST_LOCK(&doomed_pris);
1318 AST_LIST_TRAVERSE(&doomed_pris, entry, list) {
1319 if (entry->pri == pri) {
1320 AST_LIST_UNLOCK(&doomed_pris);
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");
1328 AST_LIST_UNLOCK(&doomed_pris);
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);
1334 AST_LIST_UNLOCK(&doomed_pris);
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 */
1350static 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
1393static int bump_gains(struct dahdi_pvt *p);
1394static int dahdi_setlinear(int dfd, int linear);
1395
1396static int my_start_cid_detect(void *pvt, int cid_signalling)
1397{
1398 struct dahdi_pvt *p = pvt;
1399 int index = SUB_REAL;
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
1411static int restore_gains(struct dahdi_pvt *p);
1412
1413static 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
1429static 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) {
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;
1488 if (name)
1490 if (num)
1491 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
1492
1494 /* If we got a presentation, we must set it on the channel */
1495 struct ast_party_caller caller;
1496
1498 caller.id.name.presentation = caller.id.number.presentation = (flags & CID_PRIVATE_NUMBER) ?
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
1524static const char *event2str(int event);
1525
1526static 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
1650static 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
1660static int send_callerid(struct dahdi_pvt *p);
1661static int save_conference(struct dahdi_pvt *p);
1662static int restore_conference(struct dahdi_pvt *p);
1663
1664static 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
1698static 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
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,
1723 NULL,
1724 analog_p->redirecting_reason,
1725 pres,
1726 analog_p->call_qualifier,
1728 AST_LAW(p));
1729 } else {
1730 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
1732 p->callwaitcas = 0;
1733 p->cidcwexpire = 0;
1735 caller->id.name.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
1752{
1753 struct dahdi_pvt *p = pvt;
1754 if (p->dsp)
1756
1757 return 0;
1758}
1759
1760static 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
1799static int dahdi_wink(struct dahdi_pvt *p, int index);
1800
1801static 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
1811static void wakeup_sub(struct dahdi_pvt *p, int a);
1812
1813static int reset_conf(struct dahdi_pvt *p);
1814
1815static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
1816
1817static 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 */
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
1891static void my_lock_private(void *pvt)
1892{
1893 struct dahdi_pvt *p = pvt;
1894 ast_mutex_lock(&p->lock);
1895}
1896
1897static void my_unlock_private(void *pvt)
1898{
1899 struct dahdi_pvt *p = pvt;
1901}
1902
1903static void my_deadlock_avoidance_private(void *pvt)
1904{
1905 struct dahdi_pvt *p = pvt;
1906
1908}
1909
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),
1932 (unsigned int)ast_json_integer_get(span),
1933 ast_json_string_get(channel));
1934}
1935
1938 );
1939
1940/*! \brief Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages */
1941static 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 */
1968static 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 */
1994static 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*/
2005static 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
2017static 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
2025static int get_alarms(struct dahdi_pvt *p);
2026static void handle_alarms(struct dahdi_pvt *p, int alms);
2027static 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
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
2050static 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
2057static 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
2076static void my_set_alarm(void *pvt, int in_alarm)
2077{
2078 struct dahdi_pvt *p = pvt;
2079
2080 p->inalarm = in_alarm;
2081}
2082
2083static void my_set_dialing(void *pvt, int is_dialing)
2084{
2085 struct dahdi_pvt *p = pvt;
2086
2087 p->dialing = is_dialing;
2088}
2089
2090static 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)
2098static 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)
2107static 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)
2116static 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)
2125static 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
2133static void my_set_ringtimeout(void *pvt, int ringt)
2134{
2135 struct dahdi_pvt *p = pvt;
2136 p->ringt = ringt;
2137}
2138
2139static 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
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
2179static 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
2190static void my_set_confirmanswer(void *pvt, int flag)
2191{
2192 struct dahdi_pvt *p = pvt;
2193 p->confirmanswer = flag;
2194}
2195
2196static 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
2206static void my_set_callwaiting(void *pvt, int callwaiting_enable)
2207{
2208 struct dahdi_pvt *p = pvt;
2209
2210 p->callwaiting = callwaiting_enable;
2211}
2212
2213static void my_cancel_cidspill(void *pvt)
2214{
2215 struct dahdi_pvt *p = pvt;
2216
2217 ast_free(p->cidspill);
2218 p->cidspill = NULL;
2220}
2221
2222static int my_confmute(void *pvt, int mute)
2223{
2224 struct dahdi_pvt *p = pvt;
2225 return dahdi_confmute(p, mute);
2226}
2227
2228static void my_set_pulsedial(void *pvt, int flag)
2229{
2230 struct dahdi_pvt *p = pvt;
2231 p->pulsedial = flag;
2232}
2233
2234static 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
2241static const char *my_get_orig_dialstring(void *pvt)
2242{
2243 struct dahdi_pvt *p = pvt;
2244
2245 return p->dialstring;
2246}
2247
2248static void my_increase_ss_count(void)
2249{
2253}
2254
2255static void my_decrease_ss_count(void)
2256{
2261}
2262
2263static 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
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) {
2298 }
2299}
2300
2301static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
2302
2303static 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
2311static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
2312
2313static 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
2321static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
2322
2323static 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)) {
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
2371static int check_for_conference(struct dahdi_pvt *p);
2372
2373static int my_check_for_conference(void *pvt)
2374{
2375 struct dahdi_pvt *p = pvt;
2376 return check_for_conference(p);
2377}
2378
2379static 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
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 */
2419static 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
2421static 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
2423static 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)
2434static 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)
2445static 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) {
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
2494static 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 */
2504static 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 */
2555static 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
2569static int unalloc_sub(struct dahdi_pvt *p, int x);
2570
2571static 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
2578static int alloc_sub(struct dahdi_pvt *p, int x);
2579
2580static 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
2587static int has_voicemail(struct dahdi_pvt *p);
2588
2589static int my_has_voicemail(void *pvt)
2590{
2591 struct dahdi_pvt *p = pvt;
2592
2593 return has_voicemail(p);
2594}
2595
2596static 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
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:
2616 break;
2617 case DAHDI_EVENT_WINKFLASH:
2619 break;
2620 case DAHDI_EVENT_ALARM:
2621 res = ANALOG_EVENT_ALARM;
2622 break;
2623 case DAHDI_EVENT_NOALARM:
2625 break;
2626 case DAHDI_EVENT_DIALCOMPLETE:
2628 break;
2629 case DAHDI_EVENT_RINGERON:
2631 break;
2632 case DAHDI_EVENT_RINGEROFF:
2634 break;
2635 case DAHDI_EVENT_HOOKCOMPLETE:
2637 break;
2638 case DAHDI_EVENT_PULSE_START:
2640 break;
2641 case DAHDI_EVENT_POLARITY:
2643 break;
2644 case DAHDI_EVENT_RINGBEGIN:
2646 break;
2647 case DAHDI_EVENT_EC_DISABLED:
2649 break;
2650 case DAHDI_EVENT_REMOVED:
2652 break;
2653 case DAHDI_EVENT_NEONMWI_ACTIVE:
2655 break;
2656 case DAHDI_EVENT_NEONMWI_INACTIVE:
2658 break;
2659#ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
2660 case DAHDI_EVENT_TX_CED_DETECTED:
2662 break;
2663 case DAHDI_EVENT_RX_CED_DETECTED:
2665 break;
2666 case DAHDI_EVENT_EC_NLP_DISABLED:
2668 break;
2669 case DAHDI_EVENT_EC_NLP_ENABLED:
2671 break;
2672#endif
2673 case DAHDI_EVENT_PULSEDIGIT:
2675 break;
2676 case DAHDI_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
2701static inline int dahdi_wait_event(int fd);
2702
2703static 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
2710static 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
2724static 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
2753static 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
2761
2762 return 0;
2763}
2764
2765static int dahdi_ring_phone(struct dahdi_pvt *p);
2766
2767static int my_ring(void *pvt)
2768{
2769 struct dahdi_pvt *p = pvt;
2770
2771 return dahdi_ring_phone(p);
2772}
2773
2774static 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
2781static inline int dahdi_set_hook(int fd, int hs);
2782
2783static 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
2789static void my_set_needringing(void *pvt, int value)
2790{
2791 struct dahdi_pvt *p = pvt;
2793}
2794
2795static 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
2806static void my_start_polarityswitch(void *pvt)
2807{
2808 struct dahdi_pvt *p = pvt;
2809
2811 my_set_polarity(pvt, 0);
2812 }
2813}
2814
2815static 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
2826static 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 */
2842static 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
2874static 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
2888static 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")) {
2900 } else if (!strcasecmp(value, "reverse")) {
2902 } else {
2903 polarity = atoi(value);
2904 }
2905
2907 ast_log(LOG_WARNING, "Invalid polarity: '%s'\n", value);
2908 return -1;
2909 }
2910
2912 return 0;
2913}
2914
2916 .name = "POLARITY",
2917 .write = polarity_write,
2918 .read = polarity_read,
2919};
2920
2921static 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
2929static 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
2947static void dahdi_train_ec(struct dahdi_pvt *p);
2948
2949static 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
2958static 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
2974static 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)
2981static 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)
3015static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
3016{
3017 switch (tone) {
3019 return DAHDI_TONE_RINGTONE;
3021 return DAHDI_TONE_STUTTER;
3023 return DAHDI_TONE_CONGESTION;
3025 return DAHDI_TONE_DIALTONE;
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)
3039static 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:
3067 pri_queue_for_destruction(pri);
3068 break;
3069 default:
3070 break;
3071 }
3072}
3073#endif /* defined(HAVE_PRI) */
3074
3075#if defined(HAVE_PRI)
3076static 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 */
3093static 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;
3108 if (caller->id.tag) {
3109 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
3110 }
3111 ast_copy_string(p->cid_ani,
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 */
3127static 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 */
3144static 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 */
3179static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
3180{
3181 char *dial;
3182 struct dahdi_pvt *pvt;
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 */
3224static 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
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 */
3286static 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 */
3298static 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)
3306static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
3307#endif /* defined(HAVE_PRI_CALL_WAITING) */
3308static 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 */
3353static 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)
3384static 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 */
3406static 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 */
3439static 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)
3477static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
3478{
3479 switch (tone) {
3481 return DAHDI_TONE_RINGTONE;
3483 return DAHDI_TONE_STUTTER;
3485 return DAHDI_TONE_CONGESTION;
3487 return DAHDI_TONE_DIALTONE;
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)
3501static 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{
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 */
3553static 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);
3563 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
3564 ast_safe_system(s);
3565 }
3566}
3567
3568static 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
3590static int my_have_progressdetect(void *pvt)
3591{
3592 struct dahdi_pvt *p = pvt;
3593
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
3613
3614#undef gen_pvt_field_callback
3615
3617{
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. */
3690static struct dahdi_pvt *round_robin[64]; /* groups can range from 0-63 */
3691
3692int _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)
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 */
3724static 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
3740static void wakeup_sub(struct dahdi_pvt *p, int a)
3741{
3743 if (p->subs[a].owner) {
3746 }
3747}
3748
3749static 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)) {
3755 } else {
3756 ast_queue_frame(p->owner, f);
3758 break;
3759 }
3760 } else
3761 break;
3762 }
3763}
3764
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
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
3796static void handle_clear_alarms(struct dahdi_pvt *p)
3797{
3798#if defined(HAVE_PRI)
3800 return;
3801 }
3802#endif /* defined(HAVE_PRI) */
3803
3806 }
3809 }
3810}
3811
3812#ifdef HAVE_OPENR2
3813static 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
3829static 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 */
3856static 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
3875static 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) {
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;
3902 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
3903}
3904
3905static 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 {
3919 }
3921}
3922
3923static 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 }
3938}
3939
3940static 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) {
3947 }
3948 ast_mutex_lock(&p->lock);
3949 p->mfcr2call = 0;
3951}
3952
3953static 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;
3963 }
3964}
3965
3966static 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 }
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
4022dahdi_r2_on_call_offered_cleanup:
4024}
4025
4026static 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;
4033}
4034
4035static 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
4078dahdi_r2_on_call_accepted_cleanup:
4080}
4081
4082static 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
4089static 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
4094static 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:
4103 case OR2_CAUSE_UNALLOCATED_NUMBER:
4105 case OR2_CAUSE_NO_ANSWER:
4106 return AST_CAUSE_NO_ANSWER;
4107 case OR2_CAUSE_NORMAL_CLEARING:
4109 case OR2_CAUSE_UNSPECIFIED:
4110 default:
4111 return AST_CAUSE_NOTDEFINED;
4112 }
4113}
4114
4115static 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) {
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);
4137 ast_copy_string(cause_code->code, cause_str, datalen + 1 - sizeof(*cause_code));
4139 ast_channel_hangupcause_hash_set(p->owner, cause_code, datalen);
4141
4142 /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
4143 be done in dahdi_hangup */
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:
4160 break;
4161 default:
4163 }
4165 } else {
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
4173static 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
4199static 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;
4205 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
4206}
4207
4208static 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;
4214 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
4215}
4216
4217static 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)));
4219static 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
4230static 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)));
4232static 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
4243static 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))) &&
4259 return 0;
4260 }
4261 /* otherwise keep going */
4262 return 1;
4263}
4264
4265static 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
4275static 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
4280static 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
4301static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
4302{
4303 return AST_ALAW(sample);
4304}
4305
4306static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
4307{
4308 return AST_LIN2A(sample);
4309}
4310
4311static 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
4318static 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
4346static 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
4393static void dahdi_close(int fd)
4394{
4395 if (fd > 0)
4396 close(fd);
4397}
4398
4399static 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)
4406static 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)
4414static 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
4421static int dahdi_setlinear(int dfd, int linear)
4422{
4423 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
4424}
4425
4426
4427static 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
4464static 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;
4477 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
4478 return 0;
4479}
4480
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
4497static 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) {
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
4553out:
4554 ast_mutex_unlock(&pvt->lock);
4555
4556 return 0;
4557}
4558
4559static 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
4591out:
4592 ast_mutex_unlock(&pvt->lock);
4593
4594 return res;
4595}
4596
4597static 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
4619static struct {
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" },
4631
4632static 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
4642static 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
4651static 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
4717static 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
4755static 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
4766static 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
4785static 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
4829static 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
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)) {
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
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)
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)
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
4953static 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
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
4988static 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 */
4998static 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
5018static 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
5068static 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
5116static 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
5133static 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
5150static 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
5155static 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
5169static 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
5182static 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
5199static 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)
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
5236static 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
5262static 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
5277static int send_cwcidspill(struct dahdi_pvt *p)
5278{
5279 p->callwaitcas = 0;
5280 p->cidcwexpire = 0;
5281 p->cid_suppress_expire = 0;
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
5293static 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 {
5316 }
5317
5318 return new_msgs;
5319}
5320
5321
5322
5323static 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;
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
5356 return 0;
5357}
5358
5359static 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
5393static 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;
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)
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;
5435 return 0;
5436 }
5438 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
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 */
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
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
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);
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);
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);
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*/
5493 break;
5494 case SIG_MFCR2:
5495 break;
5496 default:
5497 ast_debug(1, "not yet implemented\n");
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) {
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);
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) {
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 */
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 */
5552static 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 */
5600static 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 */
5639static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
5640{
5641 struct dahdi_pvt *cur;
5642
5643 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
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 */
5690static 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 */
5723static 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 */
5753static 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 */
5782static 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
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
5827static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
5828{
5829 struct dahdi_pvt *p = pvt;
5830
5831 if (p->manages_span_alarms) {
5833 if (next) {
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:
5853 break;
5854#if defined(HAVE_PRI)
5855 case DAHDI_IFLIST_NO_B_CHAN:
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)) {
5866 }
5867 switch (p->sig) {
5868#if defined(HAVE_PRI)
5871 break;
5872#endif /* defined(HAVE_PRI) */
5873#if defined(HAVE_SS7)
5874 case SIG_SS7:
5876 break;
5877#endif /* defined(HAVE_SS7) */
5878 default:
5879 break;
5880 }
5881 }
5882 ast_free(p->cidspill);
5883 if (p->use_smdi) {
5885 }
5886 if (p->mwi_event_sub) {
5888 }
5889 if (p->vars) {
5891 }
5892 if (p->cc_params) {
5894 }
5895
5898
5901 if (p->owner) {
5903 }
5904 ast_free(p);
5905}
5906
5907static 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
5925static 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
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 */
5963 ast_verb(3, "Unregistered channel %d\n", chan);
5964 }
5965 ifcount = 0;
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 */
5981 }
5982 ast_mutex_unlock(&pri->lock);
5983 }
5984#endif /* defined(HAVE_PRI) */
5985}
5986
5987#if defined(HAVE_PRI)
5988static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
5989
5990static 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
6008
6009 return 0;
6010}
6011#endif /* defined(HAVE_PRI) */
6012
6013#if defined(HAVE_PRI)
6014#if defined(HAVE_PRI_PROG_W_CAUSE)
6015static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
6016
6017static 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;
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) {
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);
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
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)
6085static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
6086
6087static 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;
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);
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) {
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) {
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)) {
6138 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
6139 return -1;
6140 }
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) {
6178 ast_debug(1, "Accepted MFC/R2 call!\n");
6179 break;
6180 }
6182 }
6183 if (res == -1) {
6184 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
6185 }
6186 return res;
6187}
6188
6189static 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) {
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
6201 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
6202 break;
6203
6205 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
6206 break;
6207
6210 r2cause = OR2_CAUSE_OUT_OF_ORDER;
6211 break;
6212
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
6228static 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
6250static 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)
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;
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);
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';
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) {
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;
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);
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
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) {
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));
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));
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;
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. */
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");
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. */
6473 p->owner = p->subs[SUB_REAL].owner;
6475 p->subs[SUB_REAL].needanswer = 1;
6477 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
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) {
6499 }
6501 /* Make it the call wait now */
6504 } else
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) {
6512 }
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 */
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:
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. */
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)
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;
6624 p->waitingfordt.tv_sec = 0;
6625 p->dialing = 0;
6626 p->rdnis[0] = '\0';
6628 reset_conf(p);
6629 /* Restore data mode */
6630 switch (p->sig) {
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)
6641 }
6642
6643 p->callwaitingrepeat = 0;
6644 p->cidcwexpire = 0;
6645 p->cid_suppress_expire = 0;
6646 p->oprmode = 0;
6647hangup_out:
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
6683 ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast));
6684
6686 if (p->restartpending) {
6688 }
6689
6690 if (p->destroy) {
6691 destroy_channel(p, 0);
6692 }
6694
6696 return 0;
6697}
6698
6699static 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))) {
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);
6718 return res;
6719 }
6720
6721 switch (p->sig) {
6722#if defined(HAVE_PRI)
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:
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 }
6760 return res;
6761}
6762
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
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) {
6791 }
6792}
6793
6794static 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;
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)
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
6843static 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));
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)
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;
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",
7006 errno = EINVAL;
7007 return -1;
7008 }
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",
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));
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) {
7038 } else {
7040 }
7041 break;
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) {
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
7062static 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);
7077 } else if (!strcasecmp(data, "txgain")) {
7078 ast_mutex_lock(&p->lock);
7079 snprintf(buf, len, "%f", p->txgain);
7081 } else if (!strcasecmp(data, "dahdi_channel")) {
7082 ast_mutex_lock(&p->lock);
7083 snprintf(buf, len, "%d", p->channel);
7085 } else if (!strcasecmp(data, "dahdi_span")) {
7086 ast_mutex_lock(&p->lock);
7087 snprintf(buf, len, "%d", p->span);
7089 } else if (!strcasecmp(data, "dahdi_group")) {
7090 ast_mutex_lock(&p->lock);
7091 snprintf(buf, len, "%llu", p->group);
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)
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 }
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) {
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 }
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) {
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 }
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) {
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 }
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) {
7175 ast_copy_string(buf, "both", len);
7176 break;
7178 ast_copy_string(buf, "pulse", len);
7179 break;
7181 ast_copy_string(buf, "dtmf", len);
7182 break;
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 }
7193 } else {
7194 *buf = '\0';
7195 res = -1;
7196 }
7197
7198 return res;
7199}
7200
7201
7202static 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
7231static 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);
7266 } else if (!strcasecmp(value, "off")) {
7267 ast_mutex_lock(&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 }
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 }
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);
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 }
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);
7332 return -1;
7333 }
7334 /* Only set the temp waitfordialtone setting, not the permanent one. */
7335 p->waitfordialtonetemp = atoi(value);
7337 } else {
7338 res = -1;
7339 }
7340
7341 return res;
7342}
7343
7344void 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
7400void 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
7424static 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) {
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 }
7455
7457
7458 if (ast_channel_state(newchan) == AST_STATE_RINGING) {
7460 }
7461 return 0;
7462}
7463
7464static 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
7494static 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 */
7508static 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);
7524
7525 xfer_res = ast_bridge_transfer_attended(owner_3way, owner_real);
7526 if (xfer_res != AST_BRIDGE_TRANSFER_SUCCESS) {
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
7541static 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 */
7567static 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
7594static 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 */
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 */
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
7694static 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
7708static 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
7725}
7726
7727static void handle_alarms(struct dahdi_pvt *p, int alms)
7728{
7729 const char *alarm_str;
7730
7731#if defined(HAVE_PRI)
7733 return;
7734 }
7735#endif /* defined(HAVE_PRI) */
7736
7737 alarm_str = alarm2str(alms);
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
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
7749static 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)
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);
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)
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)
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 */
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 */
7914 break;
7915 } else { /* if to state wait for offhook to dial rest */
7916 /* we now wait for off hook */
7918 }
7919 }
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) {
7937 /* If aops=0 and hops=1, this is necessary */
7939 } else {
7940 /* Start clean, so we can catch the change to REV polarity when party answers */
7942 }
7943 }
7944 }
7945 }
7946 break;
7947 case DAHDI_EVENT_ALARM:
7948 switch (p->sig) {
7949#if defined(HAVE_PRI)
7952 break;
7953#endif /* defined(HAVE_PRI) */
7954#if defined(HAVE_SS7)
7955 case SIG_SS7:
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) {
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);
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 */
8014 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
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 */
8026 p->dialing = 1;
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 */
8033 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
8034 DLA_UNLOCK(&p->lock);
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)
8057 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
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;
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) {
8067 /* Swap subs and dis-own channel */
8069 p->owner = NULL;
8070 /* Ring the phone */
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 {
8082 if (p->subs[SUB_THREEWAY].owner)
8084 }
8085 } else {
8087 /* Swap subs and dis-own channel */
8089 p->owner = NULL;
8090 /* Ring the phone */
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:
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);
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 {
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);
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;
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
8199 return &p->subs[idx].f;
8200 case AST_STATE_DOWN:
8202 ast_channel_rings_set(ast, 1);
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*/
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);
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");
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 {
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)
8296 break;
8297#endif /* defined(HAVE_PRI) */
8298#if defined(HAVE_SS7)
8299 case SIG_SS7:
8301 break;
8302#endif /* defined(HAVE_SS7) */
8303 default:
8304 p->inalarm = 0;
8305 break;
8306 }
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",
8340
8341 /* Cancel any running CallerID spill */
8342 ast_free(p->cidspill);
8343 p->cidspill = NULL;
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 */
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) {
8368 }
8369 p->subs[SUB_CALLWAIT].needhold = 1;
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) {
8389 sizeof(cid_num));
8390 }
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 */
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)
8424 if (!p->origcid_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 */
8431 /* Disable echo canceller for better dialing */
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 */
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*/
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));
8467 p->subs[SUB_REAL].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)) &&
8473 int otherindex = SUB_THREEWAY;
8474
8475 ast_verb(3, "Building conference call with %s and %s\n",
8478 /* Put them in the threeway, and flip */
8480 p->subs[SUB_REAL].inthreeway = 1;
8481 if (ast_channel_state(ast) == AST_STATE_UP) {
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));
8494 p->owner = p->subs[SUB_REAL].owner;
8495 if (p->subs[SUB_REAL].owner) {
8497 }
8498 p->subs[SUB_REAL].needunhold = 1;
8499 dahdi_ec_enable(p);
8500 }
8501 }
8502 }
8503winkflashdone:
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,
8525 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
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) {
8611 if (p->answeronpolarityswitch &&
8614 ast_debug(1, "Answering on polarity switch!\n");
8616 if (p->hanguponpolarityswitch) {
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) &&
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);
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 {
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
8651static 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) {
8692 }
8693 p->subs[SUB_REAL].needunhold = 1;
8694 }
8695 switch (res) {
8696 case DAHDI_EVENT_ONHOOK:
8698 if (p->owner) {
8699 ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
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");
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));
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;
8737 p->subs[SUB_REAL].needunhold = 1;
8738 } else
8739 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
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 */
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
8773static 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 }
8785 return f;
8786}
8787
8788static 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)) {
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");
8828 return NULL;
8829 }
8830
8831 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
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) {
8854 return NULL;
8855 }
8856 p->firstradio = 1;
8858 if (ps.rxisoffhook)
8859 {
8861 }
8862 else
8863 {
8865 }
8867 return &p->subs[idx].f;
8868 }
8869 if (p->ringt > 0) {
8870 if (!(--p->ringt)) {
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)) {
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;
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;
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;
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;
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 */
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;
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;
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;
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 }
8983 return f;
8984 }
8985
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);
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 */
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 }
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 }
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");
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;
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");
9065 }
9066 }
9067 if (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;
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
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) {
9137 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
9139 }
9140 }
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) {
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
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;
9185 p->waitingfordt.tv_sec = 0;
9186 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
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';
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) {
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 }
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
9246 return f;
9247}
9248
9249static 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
9271static 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) {
9297 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast_channel_name(ast));
9298 return -1;
9299 }
9300
9301 if (p->dialing) {
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) {
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) {
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 {
9340 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n",
9342 return -1;
9343 }
9345 if (res < 0) {
9346 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
9347 return -1;
9348 }
9349 return 0;
9350}
9351
9352static 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)
9364 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
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);
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) {
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;
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;
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)) {
9422 case 0:/* Cause has not been set. */
9423 /* Supply a more appropriate cause. */
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;
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;
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 }
9470 return res;
9471}
9472
9473#if defined(HAVE_PRI)
9474static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
9475#else
9476static 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
9521static 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
9526
9527 return new_channel;
9528}
9529
9530static 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
9580#if defined(HAVE_PRI)
9581 if (i->pri) {
9583 }
9584#endif /* defined(HAVE_PRI) */
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) {
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);
9613 ao2_ref(caps, -1);
9614 /* Start out assuming ulaw since it's smaller :) */
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;
9626 features |= DSP_FEATURE_CALL_PROGRESS;
9628 features |= DSP_FEATURE_WAITDIALTONE;
9629 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
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);
9665 if (i->busydetect && CANBUSYDETECT(i)) {
9668 }
9669 }
9670 }
9671 }
9672
9674
9675 if (state == AST_STATE_RING)
9678 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
9679 /* Only FXO signalled stuff can be picked up */
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;
9692 ast_channel_accountcode_set(tmp, i->accountcode);
9693 if (i->amaflags)
9695 i->subs[idx].owner = tmp;
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)
9703 if (!ast_strlen_zero(i->exten))
9705 if (!ast_strlen_zero(i->rdnis)) {
9708 }
9709 if (!ast_strlen_zero(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)) {
9719 } else if (!ast_strlen_zero(i->cid_num)) {
9722 }
9723#else
9724 if (!ast_strlen_zero(i->cid_num)) {
9727 }
9728#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
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 */
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 }
9750
9751 for (v = i->vars ; v ; v = v->next)
9753
9755
9757
9759
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
9777static 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
9796static 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
9814static 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
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 */
9843static 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
9862static 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
9889static 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
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)
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)
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 */
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;
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 */
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;
10415
10416 ast_verb(3, "%s: Parked call\n", ast_channel_name(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;
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 =
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 }
10461 p->owner = 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);
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;
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) {
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 &&
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);
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);
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)) {
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 */
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 */
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));
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));
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 */
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));
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);
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 */
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 }
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));
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)
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);
11075quit:
11080 return NULL;
11081}
11082
11085 unsigned char buf[READ_SIZE];
11086 size_t len;
11087};
11088
11089static 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
11103static 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;
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)) {
11178 } else {
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
11241quit:
11242 callerid_free(cs);
11243
11244 restore_gains(mtd->pvt);
11245
11246quit_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*/
11260static 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) {
11268 pvt->mwisendactive = 1;
11269 } else if (pvt->mwisend_fsk) {
11271 pvt->mwisendactive = 1;
11272 } else {
11273 pvt->mwisendactive = 0;
11274 return 0;
11275 }
11276#else
11277 if (mwisend_rpas) {
11279 } else {
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 }
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
11313static 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) {
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);
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) {
11345 }
11346#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11347 } else { /* support for mwisendtype=nofsk */
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) {
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 */
11373 break;
11374 default:
11375 /* Should not get here, punt*/
11376 goto quit;
11377 }
11378 }
11379
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;
11390quit:
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
11401static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11402{
11403 int handled = 0;
11404
11406 switch (event) {
11407 case DAHDI_EVENT_RINGEROFF:
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;
11416 pvt->mwisendactive = 0;
11417 } else {
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 }
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 */
11445static 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
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 }
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
11481static 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);
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
11514static int setup_dahdi(int reload);
11515static 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 */
11527static 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);
11537 for (cur = iflist; cur; cur = cur->next) {
11538 if (cur->channel >= start && cur->channel <= end) {
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) {
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 }
11586out:
11589 ast_cc_config_params_destroy(conf.chan.cc_params);
11591 return ret;
11592}
11593
11594
11595static 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;
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
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
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)
11717 ast_mutex_lock(&i->lock);
11720 break;
11721#endif /* defined(HAVE_PRI) */
11722#if defined(HAVE_SS7)
11723 case SIG_SS7:
11725 break;
11726#endif /* defined(HAVE_SS7) */
11727 default:
11728 i->inalarm = 0;
11729 break;
11730 }
11732 break;
11733 case DAHDI_EVENT_ALARM:
11734 switch (i->sig) {
11735#if defined(HAVE_PRI)
11737 ast_mutex_lock(&i->lock);
11740 break;
11741#endif /* defined(HAVE_PRI) */
11742#if defined(HAVE_SS7)
11743 case SIG_SS7:
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:
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:
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);
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 }
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 */
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
11854static void monitor_pfds_clean(void *arg) {
11855 struct pollfd **pfds = arg;
11856 ast_free(*pfds);
11857}
11858
11859static 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 */
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)))) {
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 }
11939 }
11940 /* Okay, now that we know what to do, release the interface lock */
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 */
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) {
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 */
12016 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode))
12018 else
12019 doomed = handle_init_event(i, res);
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 }
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;
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 */
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 }
12102 }
12104 }
12105 }
12106 }
12107 if (i->mwisendactive) {
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 */
12126 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
12127 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode))
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)) {
12147 } else {
12148 doomed = handle_init_event(i, res);
12149 }
12150 }
12151 }
12153 }
12154 }
12155 }
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
12168static int restart_monitor(void)
12169{
12170 /* If we're supposed to be stopped -- stay stopped */
12172 return 0;
12174 if (monitor_thread == pthread_self()) {
12176 ast_log(LOG_WARNING, "Cannot kill myself\n");
12177 return -1;
12178 }
12180 /* Wake up the thread */
12181 pthread_kill(monitor_thread, SIGURG);
12182 } else {
12183 /* Start a new monitor */
12186 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12187 return -1;
12188 }
12189 }
12191 return 0;
12192}
12193
12194#if defined(HAVE_PRI)
12195static 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)
12241static 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)
12305static 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)
12318static 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)
12334static 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
12344static 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
12362static 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
12412static 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 */
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 */
12493static 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);
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));
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));
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) {
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));
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);
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");
12634 return NULL;
12635 }
12636 ss7_chan = sig_ss7_chan_new(tmp, &ss7->ss7);
12637 if (!ss7_chan) {
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");
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");
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");
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));
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));
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);
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));
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);
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));
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));
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));
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);
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);
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);
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);
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);
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) {
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) {
12811 return NULL;
12812 }
12813 }
12814 ast_cc_copy_config_params(tmp->pri->cc_params,
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) */
12902 pris[span].pri.force_restart_unavailable_chans = conf->pri.pri.force_restart_unavailable_chans;
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);
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));
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) {
13112 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
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. */
13157 tmp->mwi_event_sub = ast_mwi_subscribe_pool(tmp->mailbox, stasis_subscription_cb_noop, NULL);
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)
13202 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13204 if (!here) {
13205 switch (chan_sig) {
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
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;
13244 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
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;
13248 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
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)
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)
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:
13384 break;
13387 break;
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. */
13435 }
13436 return tmp;
13437}
13438
13439static 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
13472static 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)
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 */
13537static 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 */
13568static 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 }
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) {
13651 "Unable to set buffer policy on no B channel interface: %s\n",
13652 strerror(errno));
13653 }
13654 } else
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*/
13678static 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. */
13692 if (!p->cc_params) {
13693 ast_free(p);
13694 return NULL;
13695 }
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));
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;
13721 return p;
13722}
13723
13725 /*! Group matching mask. Zero if not specified. */
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. */
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};
13742static 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;
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
13903static 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
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! */
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) {
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;
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);
14001
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) {
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;
14021 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
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
14040next:
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 }
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 */
14084static 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 */
14146static 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
14155 p = determine_starting_point(dest, &start);
14156 if (!p) {
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
14172 break;
14176#if defined(HAVE_PRI)
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 }
14233 return 0;
14234}
14235
14236#if defined(HAVE_SS7)
14237static 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)
14254static 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)
14271static 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)
14366static 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)
14417static 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)
14468static 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)
14535static 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)
14556static 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)
14563static 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)
14601static 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)
14632static 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)
14650static 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)
14728static 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)
14818static 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 */
14874 for (tmp = iflist; tmp; tmp = tmp->next) {
14875 if (tmp->pri && tmp->channel == channel) {
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 }
14920
14921 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14922 return CLI_FAILURE;
14923}
14924
14925static 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
14942static 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)
14962static 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
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)
14994static 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 */
15035static 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);
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 }
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 }
15079 ast_debug(1, "PRI span %d destroyed\n", pri->span);
15080}
15081
15082static 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)
15124static 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)
15158static 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)
15200static 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)
15220static 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
15238static 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
15254static 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
15282static 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");
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 }
15354 return CLI_SUCCESS;
15355#undef FORMAT
15356}
15357
15358static 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 }
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 }
15420 return CLI_SUCCESS;
15421}
15422
15423static 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;
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 }
15475 return CLI_SUCCESS;
15476}
15477
15478static 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;
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;
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 }
15516 return CLI_SUCCESS;
15517}
15518
15519static 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;
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;
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 }
15556 return CLI_SUCCESS;
15557}
15558
15559static 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
15641static 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
15661static 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
15706static 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
15720static 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 }
15761 return CLI_SUCCESS;
15762}
15763
15764static 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
15813static void dahdi_softhangup_all(void)
15814{
15815 struct dahdi_pvt *p;
15816retry:
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 */
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;
15835 }
15837 }
15839}
15840
15841static 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
15850 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
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
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
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
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 }
15905 }
15906
15907 /* ensure any created channels before monitor threads were stopped are hungup */
15909 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
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
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");
15949 return 1;
15950 }
15953 return 0;
15954}
15955
15956static 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
15979static 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
15989static 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");
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 }
16065 return CLI_SUCCESS;
16066#undef FORMAT
16067#undef FORMAT2
16068}
16069
16070static 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
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 }
16264 return CLI_SUCCESS;
16265 }
16266 }
16268
16269 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16270 return CLI_FAILURE;
16271}
16272
16273static 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
16309static 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 */
16348static 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
16405static 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
16438static 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
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));
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
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
16517static 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
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);
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 }
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
16595static 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
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 }
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
16652static 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
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 }
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
16721static struct ast_cli_entry dahdi_cli[] = {
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
16739static 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}
16755static struct dahdi_pvt *find_channel(int channel)
16756{
16757 struct dahdi_pvt *p;
16758
16760 for (p = iflist; p; p = p->next) {
16761 if (p->channel == channel) {
16762 break;
16763 }
16764 }
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 */
16778static 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
16790static 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 }
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
16809static 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 }
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
16828static 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 }
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 }
16847 astman_send_ack(s, m, "DAHDITransfer");
16848 return 0;
16849}
16850
16851static 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 }
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 }
16870 astman_send_ack(s, m, "DAHDIHangup");
16871 return 0;
16872}
16873
16874static 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 }
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
16906static 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
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),
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
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
16994static 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)
17063static 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)
17112static 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)
17227static 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)
17269static 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)
17345static 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)
17420static 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)
17519static 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)
17594static 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)
17634static 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)
17688static 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)
17743static 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)
17789static 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)
17835static 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
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)
17865static 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:");
17929 strcat(blocking, "M");
17930 } else {
17931 strcat(blocking, " ");
17932 }
17933
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:");
17946 strcat(blocking, "M");
17947 } else {
17948 strcat(blocking, " ");
17949 }
17950
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)
17969static 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)
17989static 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 */
18025static 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 */
18067static 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)
18078static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
18079 .type = dahdi_pri_cc_type,
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)
18096static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
18097 .type = dahdi_pri_cc_type,
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
18108static 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
18144
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) */
18161
18162 /* Hangup all interfaces if they have an owner */
18164 for (p = iflist; p; p = p->next) {
18165 if (p->owner)
18167 }
18169
18172 pthread_cancel(monitor_thread);
18173 pthread_kill(monitor_thread, SIGURG);
18174 pthread_join(monitor_thread, NULL);
18175 }
18178
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) */
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) */
18213
18215
18218 STASIS_MESSAGE_TYPE_CLEANUP(dahdichannel_type);
18219 return 0;
18220}
18221
18222static 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
18238static 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
18299static 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 */
18361static 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 */
18408static 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
18436static 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
18471static 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 */
18479
18480 for (; v; v = v->next) {
18482 continue;
18483
18484 /* Create the interface list */
18485 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
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")) {
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")) {
18516 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
18518 } else if (!strcasecmp(v->name, "dring1context")) {
18520 } else if (!strcasecmp(v->name, "dring2context")) {
18522 } else if (!strcasecmp(v->name, "dring3context")) {
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"))
18541 else if (!strcasecmp(v->value, "v23"))
18543 else if (!strcasecmp(v->value, "dtmf"))
18545 else if (!strcasecmp(v->value, "smdi"))
18547 else if (!strcasecmp(v->value, "v23_jp"))
18549 else if (ast_true(v->value))
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"))
18556 else if (!strcasecmp(v->value, "polarity"))
18558 else if (!strcasecmp(v->value, "dtmf"))
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")) {
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))
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")) {
18608 } else if (!strcasecmp(v->name, "calledsubscriberheld")) {
18610 } else if (!strcasecmp(v->name, "callprogress")) {
18611 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
18612 if (ast_true(v->value))
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")) {
18630 } else if (!strcasecmp(v->value, "outgoing")) {
18632 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
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")) {
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 }
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 }
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")) {
18749 } else if (!strcasecmp(v->value, "dtmf") || !strcasecmp(v->value, "tone")) {
18751 } else if (!strcasecmp(v->value, "none")) {
18753 } else {
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")) {
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")) {
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) {
19246 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
19247 v->lineno);
19248 } else if (!timer) {
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 {
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--- */
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")) {
19844 } else if (!strcasecmp(v->name, "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"))
19853 if (!strcasecmp(v->value, "none"))
19854 report_alarms = 0;
19855 else if (!strcasecmp(v->value, "channels"))
19857 else if (!strcasecmp(v->value, "spans"))
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) {
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) {
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 */
19904
19905 if (conf.chan.cc_params) {
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. */
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 */
19934static 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;
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 */
19956static 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);
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 }
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 {
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 */
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))) {
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))) {
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
20177 ast_config_destroy(ucfg);
20179 return res;
20180 }
20181 }
20182 ast_config_destroy(ucfg);
20183 }
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 */
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 */
20250static 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();
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 }
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 */
20279static 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)) {
20288 }
20289
20292 }
20296
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)) {
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 )) {
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) {
20347 }
20349 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
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
20365
20367 memset(round_robin, 0, sizeof(round_robin));
20368 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
20370 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
20373 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
20374 ast_manager_register_xml("DAHDIShowStatus", 0, action_dahdishowstatus);
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
20384
20385 return res;
20386}
20387
20388static 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);
20426 sig_pri_sendtext(p->sig_pvt, text);
20427 }
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)
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 */
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 */
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);
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
20509static 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
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",
Common implementation-independent jitterbuffer stuff.
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
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
ADSI Support (built upon Caller*ID)
A-Law to Signed linear conversion.
#define AST_LIN2A(a)
Definition: alaw.h:50
#define AST_ALAW(a)
Definition: alaw.h:84
char digit
jack_status_t status
Definition: app_jack.c:146
const char * str
Definition: app_jack.c:147
char * text
Definition: app_queue.c:1639
struct sla_ringing_trunk * last
Definition: app_sla.c:332
static int copy(char *infile, char *outfile)
Utility function to copy a file.
Persistent data storage (akin to *doze registry)
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:342
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 ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:476
Asterisk main include file. File version handling, generic pbx functions.
#define AST_FILE_MODE
Definition: asterisk.h:32
#define PATH_MAX
Definition: asterisk.h:40
static struct chans chans
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ast_log
Definition: astobj2.c:42
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
Bridging API.
ast_transfer_result
Definition: bridge.h:1098
@ AST_BRIDGE_TRANSFER_SUCCESS
Definition: bridge.h:1100
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
void dahdi_native_unload(void)
int dahdi_native_load(const struct ast_channel_tech *tech)
Native DAHDI bridging support.
static int tmp()
Definition: bt_open.c:389
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
#define PUT_CLID(byte)
Definition: callerid.h:412
#define CID_SIG_V23_JP
Definition: callerid.h:63
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
#define CID_TYPE_MDMF
Definition: callerid.h:75
#define CID_UNKNOWN_NUMBER
Definition: callerid.h:55
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
#define CID_SIG_SMDI
Definition: callerid.h:64
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
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
#define AST_PRES_USER_NUMBER_UNSCREENED
Definition: callerid.h:426
#define AST_PRES_UNAVAILABLE
Definition: callerid.h:434
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
#define AST_PRES_RESTRICTED
Definition: callerid.h:433
void callerid_free(struct callerid_state *cid)
This function frees callerid_state cid.
Definition: callerid.c:833
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
#define MAX_CALLERID_SIZE
Definition: callerid.h:50
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 ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()'s,...
Definition: callerid.c:1101
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
#define PUT_CLID_MARKMS
Definition: callerid.h:397
#define CID_NOMSGWAITING
Definition: callerid.h:57
#define CID_SIG_DTMF
Definition: callerid.h:62
#define CID_PRIVATE_NUMBER
Definition: callerid.h:53
struct callerid_state * callerid_new(int cid_signalling)
Create a callerID state machine.
Definition: callerid.c:130
#define CID_MSGWAITING
Definition: callerid.h:56
#define CID_SIG_V23
Definition: callerid.h:61
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
#define CID_MWI_TYPE_MDMF_FULL
Definition: callerid.h:83
void callerid_get_dtmf(char *cidstring, char *number, int *flags)
Get and parse DTMF-based callerid.
Definition: callerid.c:211
#define CID_START_RING
Definition: callerid.h:66
#define CID_START_POLARITY
Definition: callerid.h:67
#define CID_SIG_BELL
Definition: callerid.h:60
#define CID_QUALIFIER
Definition: callerid.h:58
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
#define CID_START_POLARITY_IN
Definition: callerid.h:68
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
Definition: callerid.c:1292
#define CID_START_DTMF_NOALERT
Definition: callerid.h:69
Internal Asterisk hangup causes.
#define AST_CAUSE_SWITCH_CONGESTION
Definition: causes.h:123
#define AST_CAUSE_CONGESTION
Definition: causes.h:153
#define AST_CAUSE_UNALLOCATED
Definition: causes.h:98
#define AST_CAUSE_INTERWORKING
Definition: causes.h:146
#define AST_CAUSE_PROTOCOL_ERROR
Definition: causes.h:145
#define AST_CAUSE_DESTINATION_OUT_OF_ORDER
Definition: causes.h:115
#define AST_CAUSE_NO_USER_RESPONSE
Definition: causes.h:108
#define AST_CAUSE_NORMAL_CIRCUIT_CONGESTION
Definition: causes.h:120
#define AST_CAUSE_NOTDEFINED
Definition: causes.h:155
#define AST_CAUSE_CALL_REJECTED
Definition: causes.h:111
#define AST_CAUSE_NETWORK_OUT_OF_ORDER
Definition: causes.h:121
#define AST_CAUSE_UNREGISTERED
Definition: causes.h:154
#define AST_CAUSE_BUSY
Definition: causes.h:149
#define AST_CAUSE_NO_ANSWER
Definition: causes.h:109
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:106
#define AST_CAUSE_USER_BUSY
Definition: causes.h:107
enum cc_state state
Definition: ccss.c:393
Call Completion Supplementary Services API.
#define ast_cc_config_params_init()
Allocate and initialize an ast_cc_config_params structure.
Definition: ccss.h:135
#define AST_CC_GENERIC_MONITOR_TYPE
Definition: ccss.h:455
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
void ast_cc_config_params_destroy(struct ast_cc_config_params *params)
Free memory from CCSS configuration params.
Definition: ccss.c:692
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
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
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
@ AST_CC_MONITOR_NEVER
Definition: ccss.h:76
@ AST_CC_MONITOR_ALWAYS
Definition: ccss.h:87
@ AST_CC_MONITOR_NATIVE
Definition: ccss.h:78
@ AST_CC_MONITOR_GENERIC
Definition: ccss.h:83
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
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
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_cc_is_config_param(const char *const name)
Is this a CCSS configuration parameter?
Definition: ccss.c:840
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
static sqlite3 * db
static PGresult * result
Definition: cel_pgsql.c:84
static struct ao2_container * pvts
Definition: chan_console.c:174
#define CALLPROGRESS_FAX_INCOMING
Definition: chan_dahdi.c:681
static int dahdi_create_channel_range(int start, int end)
Definition: chan_dahdi.c:11527
static int dahdi_confmute(struct dahdi_pvt *p, int muted)
Definition: chan_dahdi.c:5199
static ast_mutex_t ss_thread_lock
Definition: chan_dahdi.c:763
static int calc_energy(const unsigned char *buf, int len, struct ast_format *law)
Definition: chan_dahdi.c:11089
#define CALLWAITING_SUPPRESS_SAMPLES
Definition: chan_dahdi.c:801
static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
Definition: chan_dahdi.c:4755
static void release_doomed_pris(void)
Definition: chan_dahdi.c:1283
static struct dahdi_pvt * round_robin[64]
Definition: chan_dahdi.c:3690
#define HANGUP
Definition: chan_dahdi.c:16737
static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
Definition: chan_dahdi.c:2234
static int restore_gains(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5169
static void publish_channel_alarm_clear(int channel)
Definition: chan_dahdi.c:3765
static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
Definition: chan_dahdi.c:4766
static char * dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:15989
static void my_set_confirmanswer(void *pvt, int flag)
Definition: chan_dahdi.c:2190
#define CIDCW_EXPIRE_SAMPLES
Definition: chan_dahdi.c:802
static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
Definition: chan_dahdi.c:9249
static int my_callwait(void *pvt)
Definition: chan_dahdi.c:1664
static int restore_conference(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5262
static void publish_span_alarm_clear(int span)
Definition: chan_dahdi.c:3783
static ast_mutex_t iflock
Protect the interface list (of dahdi_pvt's)
Definition: chan_dahdi.c:746
static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Definition: chan_dahdi.c:9352
static void notify_message(char *mailbox, int thereornot)
Send MWI state change.
Definition: chan_dahdi.c:3553
static struct dahdi_pvt * mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
Definition: chan_dahdi.c:12493
static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
Definition: chan_dahdi.c:4717
static int unalloc_sub(struct dahdi_pvt *p, int x)
Definition: chan_dahdi.c:4464
static int my_check_confirmanswer(void *pvt)
Definition: chan_dahdi.c:2196
static const char *const events[]
Definition: chan_dahdi.c:4597
static int reset_conf(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4829
static int my_is_dialing(void *pvt, enum analog_sub sub)
Definition: chan_dahdi.c:2958
static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
Definition: chan_dahdi.c:2929
static struct ast_manager_event_blob * dahdichannel_to_ami(struct stasis_message *msg)
Definition: chan_dahdi.c:1910
static void my_cancel_cidspill(void *pvt)
Definition: chan_dahdi.c:2213
static int numbufs
Definition: chan_dahdi.c:731
static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
Definition: chan_dahdi.c:4785
static int my_set_echocanceller(void *pvt, int enable)
Definition: chan_dahdi.c:2753
static int dahdi_wink(struct dahdi_pvt *p, int index)
Definition: chan_dahdi.c:9796
static char mwimonitornotify[PATH_MAX]
Definition: chan_dahdi.c:721
static char * alarm2str(int alm)
Definition: chan_dahdi.c:4632
static void my_hangup_polarityswitch(void *pvt)
Definition: chan_dahdi.c:2826
static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
Definition: chan_dahdi.c:13439
static int dahdi_ring_phone(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7464
static char * dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:16348
#define CALLWAITING_REPEAT_SAMPLES
Definition: chan_dahdi.c:800
static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
Definition: chan_dahdi.c:3724
#define DEFAULT_RINGT
Definition: chan_dahdi.c:804
#define CALLPROGRESS_FAX_OUTGOING
Definition: chan_dahdi.c:680
static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout)
Definition: chan_dahdi.c:5393
static int my_stop_cid_detect(void *pvt)
Definition: chan_dahdi.c:1413
static int my_get_sub_fd(void *pvt, enum analog_sub sub)
Definition: chan_dahdi.c:2050
static void my_set_needringing(void *pvt, int value)
Definition: chan_dahdi.c:2789
static char * dahdi_destroy_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:15720
static struct ast_jb_conf default_jbconf
Definition: chan_dahdi.c:618
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
static struct dahdi_pvt * find_channel_from_str(const char *channel)
Definition: chan_dahdi.c:16778
static int __unload_module(void)
Definition: chan_dahdi.c:18108
static void dahdi_softhangup_all(void)
Definition: chan_dahdi.c:15813
static void dahdi_train_ec(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4953
static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno)
Definition: chan_dahdi.c:18238
static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
Definition: chan_dahdi.c:9271
static enum analog_event dahdievent_to_analogevent(int event)
Definition: chan_dahdi.c:2606
static int dahdi_digit_begin(struct ast_channel *ast, char digit)
Definition: chan_dahdi.c:4497
static void my_unlock_private(void *pvt)
Definition: chan_dahdi.c:1897
#define HEADER_MS
#define TRANSFER
Definition: chan_dahdi.c:16736
static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
Definition: chan_dahdi.c:7424
static void my_set_dialing(void *pvt, int is_dialing)
Definition: chan_dahdi.c:2083
static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
Definition: chan_dahdi.c:1817
static struct dahdi_pvt * fxo_pvt(struct ast_channel *chan)
Return DAHDI pivot if channel is FXO signalled.
Definition: chan_dahdi.c:2842
static int mwisend_rpas
Definition: chan_dahdi.c:723
static void publish_dnd_state(int channel, const char *status)
Definition: chan_dahdi.c:9814
static int my_on_hook(void *pvt)
Definition: chan_dahdi.c:2974
static int attempt_transfer(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7508
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
static void my_set_pulsedial(void *pvt, int flag)
Definition: chan_dahdi.c:2228
static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
Definition: chan_dahdi.c:4559
static char * dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:16438
static int dahdi_wait_event(int fd)
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition: chan_dahdi.c:782
static void publish_channel_alarm(int channel, const char *alarm_txt)
Definition: chan_dahdi.c:7708
static int canmatch_featurecode(const char *pickupexten, const char *exten)
Definition: chan_dahdi.c:9862
static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
Definition: chan_dahdi.c:3749
static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
Definition: chan_dahdi.c:5150
struct analog_callback analog_callbacks
Definition: chan_dahdi.c:3616
static void dahdi_destroy_channel_range(int start, int end)
Definition: chan_dahdi.c:11445
static char * dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:16070
static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
Definition: chan_dahdi.c:2571
static void my_set_alarm(void *pvt, int in_alarm)
Definition: chan_dahdi.c:2076
static int num_restart_pending
Definition: chan_dahdi.c:766
static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
Definition: chan_dahdi.c:1760
static int my_get_event(void *pvt)
Definition: chan_dahdi.c:2710
static int available(struct dahdi_pvt **pvt, int is_specific_channel)
Definition: chan_dahdi.c:13472
static int dahdi_devicestate(const char *data)
Definition: chan_dahdi.c:14084
static int user_has_defined_cadences
Definition: chan_dahdi.c:686
static int dahdi_callwait(struct ast_channel *ast)
Definition: chan_dahdi.c:5359
static void wakeup_sub(struct dahdi_pvt *p, int a)
Definition: chan_dahdi.c:3740
static void my_set_callwaiting(void *pvt, int callwaiting_enable)
Definition: chan_dahdi.c:2206
static int distinctiveringaftercid
Definition: chan_dahdi.c:729
static int my_is_off_hook(void *pvt)
Definition: chan_dahdi.c:2724
char * name
Definition: chan_dahdi.c:4621
#define END_SILENCE_LEN
static int mwi_send_init(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:11260
static int dahdi_open(char *fn)
Definition: chan_dahdi.c:4346
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
static int my_check_waitingfordt(void *pvt)
Definition: chan_dahdi.c:2179
static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
Definition: chan_dahdi.c:19956
static void publish_span_alarm(int span, const char *alarm_txt)
Definition: chan_dahdi.c:7694
static void my_set_outgoing(void *pvt, int is_outgoing)
Definition: chan_dahdi.c:2090
static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
Definition: chan_dahdi.c:16739
static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
Definition: chan_dahdi.c:2017
static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:5827
static int dahdi_hangup(struct ast_channel *ast)
Definition: chan_dahdi.c:6250
static void * analog_ss_thread(void *data)
Definition: chan_dahdi.c:9889
static int dahdi_sendtext(struct ast_channel *c, const char *text)
Definition: chan_dahdi.c:20388
static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
Definition: chan_dahdi.c:1968
static void my_swap_subchannels(void *pvt, enum analog_sub a, struct ast_channel *ast_a, enum analog_sub b, struct ast_channel *ast_b)
Definition: chan_dahdi.c:2379
#define PROC_DAHDI_OPT_NOCHAN
Definition: chan_dahdi.c:18432
static void parse_busy_pattern(struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
Definition: chan_dahdi.c:18436
static int analogsub_to_dahdisub(enum analog_sub analogsub)
Definition: chan_dahdi.c:1253
static void my_get_and_handle_alarms(void *pvt)
Definition: chan_dahdi.c:2027
static void my_lock_private(void *pvt)
Definition: chan_dahdi.c:1891
static int dahdi_answer(struct ast_channel *ast)
Definition: chan_dahdi.c:6699
static const char tdesc[]
Definition: chan_dahdi.c:648
static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
Definition: chan_dahdi.c:5018
static int dahdi_restart(void)
Definition: chan_dahdi.c:15841
static int action_transfer(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16828
static int bump_gains(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5155
static void * do_monitor(void *data)
Definition: chan_dahdi.c:11859
static int save_conference(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5236
static char * dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:16595
static void handle_clear_alarms(struct dahdi_pvt *p)
Definition: chan_dahdi.c:3796
static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
Definition: chan_dahdi.c:6794
static char * dahdi_sig2str(int sig)
Definition: chan_dahdi.c:4651
static int dahdi_set_hook(int fd, int hs)
Definition: chan_dahdi.c:5182
static int my_stop_callwait(void *pvt)
Definition: chan_dahdi.c:1650
static struct ast_channel * dahdi_new_callid_clean(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid, int callid_created)
Definition: chan_dahdi.c:9521
static int check_for_conference(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7541
static struct dahdi_ring_cadence AS_RP_cadence
Definition: chan_dahdi.c:709
static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
Definition: chan_dahdi.c:1526
#define NUM_SPANS
Definition: chan_dahdi.c:674
void dahdi_ec_enable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4898
#define AST_LAW(p)
Definition: chan_dahdi.c:642
static int dahdi_setlinear(int dfd, int linear)
Definition: chan_dahdi.c:4421
static int restart_monitor(void)
Definition: chan_dahdi.c:12168
static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
Definition: chan_dahdi.c:3568
static int my_confmute(void *pvt, int mute)
Definition: chan_dahdi.c:2222
#define READ_SIZE
Definition: chan_dahdi.c:794
static void * mwi_thread(void *data)
Definition: chan_dahdi.c:11103
#define CALLPROGRESS_FAX
Definition: chan_dahdi.c:682
static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
Definition: chan_dahdi.c:1698
static int sigtype_to_signalling(int sigtype)
Definition: chan_dahdi.c:12474
static void my_decrease_ss_count(void)
Definition: chan_dahdi.c:2255
static char * handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:16273
static int has_voicemail(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5293
static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:5600
void dahdi_conf_update(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4843
static int alloc_sub(struct dahdi_pvt *p, int x)
Definition: chan_dahdi.c:4427
static void my_start_polarityswitch(void *pvt)
Definition: chan_dahdi.c:2806
static int digit_to_dtmfindex(char digit)
Definition: chan_dahdi.c:4481
static int setup_dahdi(int reload)
Definition: chan_dahdi.c:20250
STASIS_MESSAGE_TYPE_DEFN_LOCAL(dahdichannel_type,.to_ami=dahdichannel_to_ami,)
static char * dahdi_set_mwi(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:16652
static int action_dahdidndon(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16790
static int report_alarms
Definition: chan_dahdi.c:738
#define GET_CHANNEL(p)
Definition: chan_dahdi.c:1180
static int mwilevel
Definition: chan_dahdi.c:733
static struct dahdi_pvt * iflist
Definition: chan_dahdi.c:922
#define NEED_MFDETECT(p)
Signaling types that need to use MF detection should be placed in this macro.
Definition: chan_dahdi.c:646
static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
Definition: chan_dahdi.c:6843
static int set_actual_txgain(int fd, float gain, float drc, int law)
Definition: chan_dahdi.c:5116
static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
Definition: chan_dahdi.c:7231
static int my_wait_event(void *pvt)
Definition: chan_dahdi.c:2703
static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
Definition: chan_dahdi.c:9777
static struct ast_channel * my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
Definition: chan_dahdi.c:2423
static int analog_tone_to_dahditone(enum analog_tone tone)
Definition: chan_dahdi.c:1233
static struct ast_str * create_channel_name(struct dahdi_pvt *i)
Definition: chan_dahdi.c:9476
static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
Definition: chan_dahdi.c:1429
#define TRAILER_MS
static int set_actual_rxgain(int fd, float gain, float drc, int law)
Definition: chan_dahdi.c:5133
static int my_start(void *pvt)
Definition: chan_dahdi.c:2921
static ast_mutex_t restart_lock
Definition: chan_dahdi.c:764
static struct ast_frame * dahdi_handle_event(struct ast_channel *ast)
Definition: chan_dahdi.c:7749
static char defaultcic[64]
Definition: chan_dahdi.c:717
int alarm
Definition: chan_dahdi.c:4620
static const char config[]
Definition: chan_dahdi.c:669
static int action_dahdishowchannels(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16906
void dahdi_dtmf_detect_enable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:6777
static struct dahdi_pvt * find_next_iface_in_span(struct dahdi_pvt *cur)
Definition: chan_dahdi.c:5816
static ast_cond_t ss_thread_complete
Definition: chan_dahdi.c:762
static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
Definition: chan_dahdi.c:18299
static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:5552
static struct ast_frame * dahdi_exception(struct ast_channel *ast)
Definition: chan_dahdi.c:8773
static void my_answer_polarityswitch(void *pvt)
Definition: chan_dahdi.c:2815
static struct ast_channel * dahdi_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
Definition: chan_dahdi.c:13903
#define SMDI_MD_WAIT_TIMEOUT
Definition: chan_dahdi.c:603
static int my_have_progressdetect(void *pvt)
Definition: chan_dahdi.c:3590
static char * dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:16517
static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
Definition: chan_dahdi.c:7062
#define CANPROGRESSDETECT(p)
Definition: chan_dahdi.c:715
static char * dahdi_create_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:15764
static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
Definition: chan_dahdi.c:5068
static int my_train_echocanceller(void *pvt)
Definition: chan_dahdi.c:2949
static const char * event2str(int event)
Definition: chan_dahdi.c:4642
#define CALLPROGRESS_PROGRESS
Definition: chan_dahdi.c:679
static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
Definition: chan_dahdi.c:4399
static void my_set_polarity(void *pvt, int value)
Definition: chan_dahdi.c:2795
void dahdi_ec_disable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4970
static struct ast_frame * __dahdi_exception(struct ast_channel *ast)
Definition: chan_dahdi.c:8651
static void handle_alarms(struct dahdi_pvt *p, int alms)
Definition: chan_dahdi.c:7727
static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
Definition: chan_dahdi.c:7594
static struct dahdi_chan_conf dahdi_chan_conf_default(void)
Definition: chan_dahdi.c:990
static struct dahdi_pvt * duplicate_pseudo(struct dahdi_pvt *src)
Definition: chan_dahdi.c:13678
static void swap_subs(struct dahdi_pvt *p, int a, int b)
Definition: chan_dahdi.c:4318
#define ISTRUNK(p)
Definition: chan_dahdi.c:711
static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
Definition: chan_dahdi.c:2005
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
static struct ast_channel * dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid)
Definition: chan_dahdi.c:9530
static int drc_sample(int sample, float drc)
Definition: chan_dahdi.c:4998
static int dahdi_get_event(int fd)
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition: chan_dahdi.c:773
static int ringt_base
Configured ring timeout base.
Definition: chan_dahdi.c:811
void dahdi_master_slave_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
Definition: chan_dahdi.c:7344
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
#define ASCII_BYTES_PER_CHAR
static void my_all_subchannels_hungup(void *pvt)
Definition: chan_dahdi.c:2263
static int my_ring(void *pvt)
Definition: chan_dahdi.c:2767
static int my_start_cid_detect(void *pvt, int cid_signalling)
Definition: chan_dahdi.c:1396
static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
Definition: chan_dahdi.c:7202
static struct dahdi_pvt * ifend
Definition: chan_dahdi.c:923
static char * dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:16405
static int my_complete_conference_update(void *pvt, int needconference)
Definition: chan_dahdi.c:2323
static struct @114 alarms[]
#define DEFAULT_DIALTONE_DETECT_TIMEOUT
Definition: chan_dahdi.c:805
static int mwi_send_process_buffer(struct dahdi_pvt *pvt, int num_read)
Definition: chan_dahdi.c:11313
#define HEADER_LEN
static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
Definition: chan_dahdi.c:2057
static void my_increase_ss_count(void)
Definition: chan_dahdi.c:2248
#define REPORT_CHANNEL_ALARMS
Definition: chan_dahdi.c:736
static int has_pseudo
Definition: chan_dahdi.c:688
static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
Definition: chan_dahdi.c:2596
static int my_wink(void *pvt, enum analog_sub sub)
Definition: chan_dahdi.c:1801
static struct ast_channel_tech dahdi_tech
Definition: chan_dahdi.c:1157
static struct ast_jb_conf global_jbconf
Definition: chan_dahdi.c:626
static int my_conf_add(void *pvt, enum analog_sub sub)
Definition: chan_dahdi.c:2313
static int my_dsp_reset_and_flush_digits(void *pvt)
Definition: chan_dahdi.c:1751
void dahdi_dtmf_detect_disable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:6763
#define PROC_DAHDI_OPT_NOWARN
Definition: chan_dahdi.c:18434
#define MIN_MS_SINCE_FLASH
Definition: chan_dahdi.c:803
static int my_has_voicemail(void *pvt)
Definition: chan_dahdi.c:2589
static char progzone[10]
Definition: chan_dahdi.c:726
static int load_module(void)
Load the module.
Definition: chan_dahdi.c:20279
#define sig2str
Definition: chan_dahdi.c:4715
static struct ast_frame * dahdi_read(struct ast_channel *ast)
Definition: chan_dahdi.c:8788
#define FORMAT
static const char * my_get_orig_dialstring(void *pvt)
Definition: chan_dahdi.c:2241
static int action_dahdirestart(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:15979
static struct ast_custom_function polarity_function
Definition: chan_dahdi.c:2915
static int get_alarms(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7567
static struct dahdi_pvt * determine_starting_point(const char *data, struct dahdi_starting_point *param)
Definition: chan_dahdi.c:13742
#define gen_pvt_field_callback(type, field)
Definition: chan_dahdi.c:3603
static int polarity_read(struct ast_channel *chan, const char *cmd, char *data, char *buffer, size_t buflen)
Definition: chan_dahdi.c:2874
static int send_cwcidspill(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5277
static int my_conf_del(void *pvt, enum analog_sub sub)
Definition: chan_dahdi.c:2303
#define FORMAT2
static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX]
Definition: chan_dahdi.c:690
static int action_dahdidndoff(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16809
static int unload_module(void)
Definition: chan_dahdi.c:18222
static int reload(void)
Definition: chan_dahdi.c:20509
static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
Definition: chan_dahdi.c:18471
static struct ast_cli_entry dahdi_cli[]
Definition: chan_dahdi.c:16721
#define POLARITY_IDLE
Definition: chan_dahdi.c:913
#define DEFAULT_CIDRINGS
Typically, how many rings before we should send Caller*ID.
Definition: chan_dahdi.c:640
static int num_cadence
Definition: chan_dahdi.c:685
static enum analog_sigtype dahdisig_to_analogsig(int sig)
Definition: chan_dahdi.c:1182
static void dahdi_close(int fd)
Definition: chan_dahdi.c:4393
static char defaultozz[64]
Definition: chan_dahdi.c:718
void dahdi_master_slave_link(struct dahdi_pvt *slave, struct dahdi_pvt *master)
Definition: chan_dahdi.c:7400
static int dtmfcid_level
Definition: chan_dahdi.c:734
#define CHAN_PSEUDO
Definition: chan_dahdi.c:677
static int my_off_hook(void *pvt)
Definition: chan_dahdi.c:2783
const char *const subnames[]
Definition: chan_dahdi.c:916
static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
Definition: chan_dahdi.c:2580
static int usedistinctiveringdetection
Definition: chan_dahdi.c:728
static int polarity_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Definition: chan_dahdi.c:2888
static char * dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:15956
static struct dahdi_pvt * find_channel(int channel)
Definition: chan_dahdi.c:16755
static void * my_get_sigpvt_bridged_channel(struct ast_channel *chan)
Definition: chan_dahdi.c:2036
static int send_callerid(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5323
static int set_hwgain(int fd, float gain, int tx_direction)
Definition: chan_dahdi.c:4988
static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
Definition: chan_dahdi.c:2139
static void build_alarm_info(char *restrict alarmstr, struct dahdi_spaninfo *spaninfo)
Definition: chan_dahdi.c:16309
static int my_check_for_conference(void *pvt)
Definition: chan_dahdi.c:2373
static int mwi_send_process_event(struct dahdi_pvt *pvt, int event)
Definition: chan_dahdi.c:11401
static int my_flash(void *pvt)
Definition: chan_dahdi.c:2774
#define POLARITY_REV
Definition: chan_dahdi.c:914
static int ss_thread_count
Definition: chan_dahdi.c:765
static const char *const lbostr[]
Definition: chan_dahdi.c:605
int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
Definition: chan_dahdi.c:3692
#define REPORT_SPAN_ALARMS
Definition: chan_dahdi.c:737
static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
Definition: chan_dahdi.c:19934
static void my_deadlock_avoidance_private(void *pvt)
Definition: chan_dahdi.c:1903
static struct dahdi_pvt * handle_init_event(struct dahdi_pvt *i, int event)
Definition: chan_dahdi.c:11595
static void destroy_channel(struct dahdi_pvt *cur, int now)
Definition: chan_dahdi.c:5907
static void my_set_ringtimeout(void *pvt, int ringt)
Definition: chan_dahdi.c:2133
static void monitor_pfds_clean(void *arg)
Definition: chan_dahdi.c:11854
static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16874
static int ifcount
Definition: chan_dahdi.c:749
#define NUM_CADENCE_MAX
Definition: chan_dahdi.c:684
static int dahdi_dial_str(struct dahdi_pvt *pvt, int operation, const char *dial_str)
Definition: chan_dahdi.c:1350
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
static int action_transferhangup(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16851
#define CANBUSYDETECT(p)
Definition: chan_dahdi.c:714
static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
Definition: chan_dahdi.c:6228
static void destroy_all_channels(void)
Definition: chan_dahdi.c:5925
static int action_dahdishowstatus(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16994
DAHDI internal API definitions.
#define SIG_FEATB
Definition: chan_dahdi.h:781
#define SIG_FGC_CAMA
Definition: chan_dahdi.h:784
#define SIG_SFWINK
Definition: chan_dahdi.h:793
#define SIG_EMWINK
Definition: chan_dahdi.h:778
#define SIG_MFCR2
Definition: chan_dahdi.h:808
#define SIG_FXSLS
Definition: chan_dahdi.h:786
#define MAX_SLAVES
Definition: chan_dahdi.h:95
static int dahdi_sig_pri_lib_handles(int signaling)
Definition: chan_dahdi.h:825
#define SIG_SF_FEATB
Definition: chan_dahdi.h:796
#define SIG_FXSKS
Definition: chan_dahdi.h:788
#define SIG_FXOGS
Definition: chan_dahdi.h:790
#define SUB_REAL
Definition: chan_dahdi.h:57
#define SIG_SF_FEATDMF
Definition: chan_dahdi.h:795
static int dahdi_analog_lib_handles(int signalling, int radio, int oprmode)
Definition: chan_dahdi.h:841
#define SUB_THREEWAY
Definition: chan_dahdi.h:59
#define SUB_CALLWAIT
Definition: chan_dahdi.h:58
#define SIG_PRI_LIB_HANDLE_CASES
Definition: chan_dahdi.h:811
#define SIG_FXOKS
Definition: chan_dahdi.h:791
#define SIG_FGC_CAMAMF
Definition: chan_dahdi.h:785
#define SIG_FXSGS
Definition: chan_dahdi.h:787
#define SIG_FEATDMF
Definition: chan_dahdi.h:780
#define SIG_EM_E1
Definition: chan_dahdi.h:797
#define SIG_SF_FEATD
Definition: chan_dahdi.h:794
#define SIG_SS7
Definition: chan_dahdi.h:805
#define SIG_BRI
Definition: chan_dahdi.h:801
@ DAHDI_IFLIST_NONE
Definition: chan_dahdi.h:117
@ DAHDI_IFLIST_MAIN
Definition: chan_dahdi.h:118
#define SIG_FEATD
Definition: chan_dahdi.h:779
#define SIG_BRI_PTMP
Definition: chan_dahdi.h:802
#define SIG_FEATDMF_TA
Definition: chan_dahdi.h:783
@ MWI_SEND_SA
Definition: chan_dahdi.h:102
@ MWI_SEND_PAUSE
Definition: chan_dahdi.h:104
@ MWI_SEND_SA_WAIT
Definition: chan_dahdi.h:103
@ MWI_SEND_DONE
Definition: chan_dahdi.h:107
@ MWI_SEND_SPILL
Definition: chan_dahdi.h:105
@ MWI_SEND_CLEANUP
Definition: chan_dahdi.h:106
#define SIG_FXOLS
Definition: chan_dahdi.h:789
#define SIG_E911
Definition: chan_dahdi.h:782
#define SIG_PRI
Definition: chan_dahdi.h:800
#define SIG_EM
Definition: chan_dahdi.h:777
#define SIG_SF
Definition: chan_dahdi.h:792
#define dahdi_get_index(ast, p, nullok)
Definition: chan_dahdi.h:882
static struct ast_timer * timer
Definition: chan_iax2.c:364
static const char type[]
Definition: chan_ooh323.c:109
General Asterisk PBX channel definitions.
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3175
const char * ast_channel_name(const struct ast_channel *chan)
static int ast_fdisset(struct pollfd *pfds, int fd, int maximum, int *start)
Helper function for migrating select to poll.
Definition: channel.h:2827
void ast_channel_rings_set(struct ast_channel *chan, int value)
void ast_channel_named_pickupgroups_set(struct ast_channel *chan, struct ast_namedgroups *value)
void ast_party_name_init(struct ast_party_name *init)
Initialize the given name structure.
Definition: channel.c:1591
void * ast_channel_tech_pvt(const struct ast_channel *chan)
struct ast_format * ast_channel_rawreadformat(struct ast_channel *chan)
void ast_party_number_init(struct ast_party_number *init)
Initialize the given number structure.
Definition: channel.c:1644
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
#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_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 ast_party_id_presentation(const struct ast_party_id *id)
Determine the overall presentation value for the given party.
Definition: channel.c:1821
#define CHECK_BLOCKING(c)
Set the blocking indication on the channel.
Definition: channel.h:2871
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
#define ast_channel_lock(chan)
Definition: channel.h:2922
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:570
unsigned short ast_channel_transfercapability(const struct ast_channel *chan)
struct ast_namedgroups * ast_ref_namedgroups(struct ast_namedgroups *groups)
Definition: channel.c:7738
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3162
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
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
unsigned long long ast_group_t
Definition: channel.h:213
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
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
const char * ast_channel_uniqueid(const struct ast_channel *chan)
const char * ast_channel_accountcode(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
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_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4257
#define ast_channel_trylock(chan)
Definition: channel.h:2924
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
@ AST_ADSI_UNAVAILABLE
Definition: channel.h:871
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
void ast_party_name_free(struct ast_party_name *doomed)
Destroy the party name contents.
Definition: channel.c:1638
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
int ast_channel_fd(const struct ast_channel *chan, int which)
void ast_channel_internal_fd_set(struct ast_channel *chan, int which, int value)
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition: channel.c:1166
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
void ast_party_caller_free(struct ast_party_caller *doomed)
Destroy the caller party contents.
Definition: channel.c:2015
int ast_active_channels(void)
returns number of active/allocated channels
Definition: channel.c:499
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
void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value)
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
int ast_channel_hangupcause(const struct ast_channel *chan)
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
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
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2471
void ast_channel_named_callgroups_set(struct ast_channel *chan, struct ast_namedgroups *value)
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
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1216
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
Queue a hold frame.
Definition: channel.c:1191
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
#define AST_CHANNEL_NAME
Definition: channel.h:171
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
void ast_channel_softhangup_internal_flag_add(struct ast_channel *chan, int value)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
@ AST_SOFTHANGUP_EXPLICIT
Definition: channel.h:1148
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1121
@ AST_SOFTHANGUP_APPUNLOAD
Definition: channel.h:1143
void ast_party_number_free(struct ast_party_number *doomed)
Destroy the party number contents.
Definition: channel.c:1691
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
void ast_channel_amaflags_set(struct ast_channel *chan, enum ama_flags value)
const char * ast_channel_language(const struct ast_channel *chan)
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
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2426
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2458
enum ama_flags ast_channel_string2amaflag(const char *flag)
Convert a string to a detail record AMA flag.
Definition: channel.c:4360
@ AST_FLAG_DISABLE_DEVSTATE_CACHE
Definition: channel.h:1029
@ AST_FLAG_END_DTMF_ONLY
Definition: channel.h:1007
@ AST_FLAG_BLOCKING
Definition: channel.h:985
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
struct ast_namedgroups * ast_unref_namedgroups(struct ast_namedgroups *groups)
Definition: channel.c:7732
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
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2969
void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value)
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)
ast_group_t ast_get_group(const char *s)
Definition: channel.c:7618
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1574
const char * ast_channel_exten(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
Definition: channel.h:2923
#define AST_MAX_EXTENSION
Definition: channel.h:134
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_RING
Definition: channelstate.h:40
@ AST_STATE_DIALING_OFFHOOK
Definition: channelstate.h:44
@ AST_STATE_RINGING
Definition: channelstate.h:41
@ AST_STATE_PRERING
Definition: channelstate.h:45
@ AST_STATE_DOWN
Definition: channelstate.h:36
@ AST_STATE_OFFHOOK
Definition: channelstate.h:38
@ AST_STATE_BUSY
Definition: channelstate.h:43
@ AST_STATE_DIALING
Definition: channelstate.h:39
@ AST_STATE_UP
Definition: channelstate.h:42
@ AST_STATE_RESERVED
Definition: channelstate.h:37
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7386
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define RESULT_SUCCESS
Definition: cli.h:40
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
#define RESULT_FAILURE
Definition: cli.h:42
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static struct channel_usage channels
#define container_of(ptr, type, member)
Definition: codec_dahdi.c:277
short word
short int16_t
Definition: db.h:59
Device state management.
@ AST_DEVSTATE_NOT_CACHABLE
Definition: devicestate.h:69
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
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
ast_device_state
Device States.
Definition: devicestate.h:52
@ AST_DEVICE_INUSE
Definition: devicestate.h:55
@ AST_DEVICE_UNKNOWN
Definition: devicestate.h:53
@ AST_DEVICE_BUSY
Definition: devicestate.h:56
@ AST_DEVICE_NOT_INUSE
Definition: devicestate.h:54
@ AST_DEVICE_UNAVAILABLE
Definition: devicestate.h:58
Convenient Signal Processing routines.
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1783
int ast_dsp_get_tcount(struct ast_dsp *dsp)
Get tcount (Threshold counter)
Definition: dsp.c:1916
threshold
Definition: dsp.h:71
#define DSP_FEATURE_WAITDIALTONE
Definition: dsp.h:44
#define DSP_FEATURE_BUSY_DETECT
Definition: dsp.h:27
#define DSP_TONE_STATE_DIALTONE
Definition: dsp.h:54
void ast_dsp_digitreset(struct ast_dsp *dsp)
Reset DTMF detector.
Definition: dsp.c:1810
#define DSP_DIGITMODE_MF
Definition: dsp.h:32
#define DSP_DIGITMODE_MUTEMAX
Definition: dsp.h:36
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
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
#define DSP_FEATURE_DIGIT_DETECT
Definition: dsp.h:28
#define DSP_FEATURE_FAX_DETECT
Definition: dsp.h:29
#define DSP_FEATURE_CALL_PROGRESS
Definition: dsp.h:43
int ast_dsp_set_digitmode(struct ast_dsp *dsp, int digitmode)
Set digit mode.
Definition: dsp.c:1857
#define DSP_DIGITMODE_MUTECONF
Definition: dsp.h:35
int ast_dsp_get_tstate(struct ast_dsp *dsp)
Get tstate (Tone State)
Definition: dsp.c:1911
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
#define DSP_TONE_STATE_RINGING
Definition: dsp.h:53
void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
Set number of required cadences for busy.
Definition: dsp.c:1793
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1768
#define DSP_DIGITMODE_DTMF
Definition: dsp.h:31
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1758
#define DSP_DIGITMODE_RELAXDTMF
Definition: dsp.h:37
int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
Set zone for doing progress detection.
Definition: dsp.c:1892
char * bs
Definition: eagi_proxy.c:73
char * end
Definition: eagi_proxy.c:73
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2206
char * address
Definition: f2c.h:59
#define abs(x)
Definition: f2c.h:195
long int flag
Definition: f2c.h:83
#define max(a, b)
Definition: f2c.h:198
Call Parking and Pickup API Includes code and algorithms from the Zapata library.
Generic File Format Support. Should be included by clients of the file handling routines....
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1293
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
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
@ AST_FORMAT_CMP_EQUAL
Definition: format.h:36
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
Media Format Cache API.
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
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
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3389
void ast_manager_publish_event(const char *type, int class_type, struct ast_json *obj)
Publish an event to AMI.
Definition: manager.c:2063
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
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3421
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:3050
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3475
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3310
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:8057
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
const char * ext
Definition: http.c:150
#define AST_APP_ARG(name)
Define an application argument.
#define ast_app_separate_args(a, b, c, d)
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"....
Definition: main/app.c:582
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:829
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
char * strsep(char **str, const char *delims)
char * strcasestr(const char *, const char *)
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3326
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3274
#define ast_variable_new(name, value, filename)
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
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
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:783
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
@ CONFIG_FLAG_FILEUNCHANGED
struct ast_features_pickup_config * ast_get_chan_features_pickup_config(struct ast_channel *chan)
Get the pickup configuration options for a channel.
#define AST_FRAME_DTMF
#define AST_OPTION_RELAXDTMF
#define AST_OPTION_TONE_VERIFY
#define AST_OPTION_RXGAIN
#define AST_OPTION_DIGIT_DETECT
#define AST_OPTION_OPRMODE
#define ast_frfree(fr)
#define AST_OPTION_CC_AGENT_TYPE
#define AST_OPTION_TDD
#define AST_OPTION_FAX_DETECT
#define AST_OPTION_TXGAIN
#define AST_OPTION_ECHOCAN
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
@ AST_FRAME_NULL
@ AST_FRAME_IMAGE
@ AST_FRAME_DTMF_END
@ AST_FRAME_DTMF_BEGIN
@ AST_FRAME_VOICE
@ AST_FRAME_CONTROL
@ AST_FRAME_TEXT
@ AST_CONTROL_RING
@ AST_CONTROL_SRCUPDATE
@ AST_CONTROL_PROGRESS
@ AST_CONTROL_OFFHOOK
@ AST_CONTROL_RADIO_UNKEY
@ AST_CONTROL_BUSY
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_PROCEEDING
@ AST_CONTROL_CONGESTION
@ AST_CONTROL_ANSWER
@ AST_CONTROL_RINGING
@ AST_CONTROL_HANGUP
@ AST_CONTROL_RADIO_KEY
@ AST_CONTROL_HOLD
@ AST_CONTROL_FLASH
@ AST_CONTROL_INCOMPLETE
@ AST_CONTROL_PVT_CAUSE_CODE
#define AST_OPTION_AUDIO_MODE
struct ast_frame ast_null_frame
Definition: main/frame.c:79
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 DEBUG_ATLEAST(level)
#define ast_debug(level,...)
Log a DEBUG message.
unsigned int ast_callid
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 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
#define LOG_ERROR
#define ast_verb(level,...)
#define LOG_NOTICE
#define LOG_WARNING
#define ast_verbose_callid(callid,...)
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_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:283
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
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
Definition: json.c:332
AST_JSON_INT_T ast_json_int_t
Primarily used to cast when packing to an "I" type.
Definition: json.h:87
#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
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
Definition: linkedlists.h:429
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_HEAD_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD.
Definition: linkedlists.h:234
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:410
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_MOVE_CURRENT(newhead, field)
Move the current list entry to another list.
Definition: linkedlists.h:582
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:856
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
Asterisk locking-related definitions:
#define DLA_LOCK(lock)
Definition: lock.h:492
#define DLA_UNLOCK(lock)
Definition: lock.h:490
#define ast_cond_destroy(cond)
Definition: lock.h:202
#define ast_cond_wait(cond, mutex)
Definition: lock.h:205
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define ast_cond_init(cond, attr)
Definition: lock.h:201
#define ast_mutex_init(pmutex)
Definition: lock.h:186
#define CHANNEL_DEADLOCK_AVOIDANCE(chan)
Definition: lock.h:474
#define DEADLOCK_AVOIDANCE(lock)
Definition: lock.h:479
#define AST_PTHREADT_STOP
Definition: lock.h:67
#define ast_mutex_unlock(a)
Definition: lock.h:190
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
#define ast_mutex_trylock(a)
Definition: lock.h:191
pthread_cond_t ast_cond_t
Definition: lock.h:178
#define ast_mutex_destroy(a)
Definition: lock.h:188
#define ast_mutex_lock(a)
Definition: lock.h:189
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:520
#define ast_cond_signal(cond)
Definition: lock.h:203
int errno
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
#define EVENT_FLAG_SYSTEM
Definition: manager.h:75
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:191
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:10564
#define EVENT_FLAG_CALL
Definition: manager.h:76
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition: module.h:331
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:483
#define ast_module_ref(mod)
Hold a reference to the module.
Definition: module.h:457
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:557
@ AST_MODPRI_CHANNEL_DRIVER
Definition: module.h:341
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:640
Music on hold handling.
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
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7776
Asterisk MWI API.
struct stasis_message_type * ast_mwi_state_type(void)
Get the Stasis Message Bus API message type for MWI messages.
void * ast_mwi_unsubscribe(struct ast_mwi_subscriber *sub)
Unsubscribe from the stasis topic and MWI.
Definition: mwi.c:254
struct stasis_cache * ast_mwi_state_cache(void)
Backend cache for ast_mwi_topic_cached().
Definition: mwi.c:94
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
#define ast_publish_mwi_state(mailbox, context, new_msgs, old_msgs)
Publish a MWI state update via stasis.
Definition: mwi.h:378
Call Parking API.
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
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 ast_parking_provider_registered(void)
Check whether a parking provider is registered.
Definition: parking.c:241
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_LOG_DIR
Definition: options.c:159
Core PBX routines and definitions.
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:4755
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
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
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.
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
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
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4708
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
Definition: pbx.c:6879
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
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
Call Pickup API.
int ast_pickup_call(struct ast_channel *chan)
Pickup a call.
Definition: pickup.c:199
struct stasis_forward * sub
Definition: res_corosync.c:240
static void to_ami(struct ast_sip_subscription *sub, struct ast_str **buf)
static int debug
Global debug status.
Definition: res_xmpp.c:441
#define NULL
Definition: resample.c:96
Say numbers and dates (maybe words one day too)
int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
Definition: sig_analog.c:1277
int analog_available(struct analog_pvt *p)
Definition: sig_analog.c:793
struct ast_frame * analog_exception(struct analog_pvt *p, struct ast_channel *ast)
Definition: sig_analog.c:3673
int analog_dnd(struct analog_pvt *p, int flag)
Definition: sig_analog.c:4165
int analog_config_complete(struct analog_pvt *p)
Definition: sig_analog.c:4109
void analog_handle_dtmf(struct analog_pvt *p, struct ast_channel *ast, enum analog_sub idx, struct ast_frame **dest)
Definition: sig_analog.c:1593
int analog_call(struct analog_pvt *p, struct ast_channel *ast, const char *rdest, int timeout)
Definition: sig_analog.c:990
void analog_delete(struct analog_pvt *doomed)
Delete the analog private structure.
Definition: sig_analog.c:4104
struct analog_pvt * analog_new(enum analog_sigtype signallingtype, void *private_data)
Definition: sig_analog.c:4076
int analog_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, void *newp)
Definition: sig_analog.c:4127
enum analog_sigtype sigtype
Definition: sig_analog.c:69
struct ast_channel * analog_request(struct analog_pvt *p, int *callwait, const struct ast_channel *requestor)
Definition: sig_analog.c:770
void * analog_handle_init_event(struct analog_pvt *i, int event)
Definition: sig_analog.c:3793
int analog_answer(struct analog_pvt *p, struct ast_channel *ast)
Definition: sig_analog.c:1490
int analog_ss_thread_start(struct analog_pvt *p, struct ast_channel *chan)
Definition: sig_analog.c:2752
Interface header for analog signaling module.
#define ANALOG_MAX_CID
Definition: sig_analog.h:33
analog_dsp_digitmode
Definition: sig_analog.h:114
@ ANALOG_DIGITMODE_DTMF
Definition: sig_analog.h:115
@ ANALOG_DIGITMODE_MF
Definition: sig_analog.h:116
#define ANALOG_INTER_DIGIT_TIMEOUT
Default time (ms) to detect following digits.
Definition: sig_analog.h:40
#define ANALOG_MATCH_DIGIT_TIMEOUT
Default time (ms) to wait, in case of ambiguous match.
Definition: sig_analog.h:42
@ ANALOG_DIALMODE_DTMF
Definition: sig_analog.h:122
@ ANALOG_DIALMODE_PULSE
Definition: sig_analog.h:121
@ ANALOG_DIALMODE_NONE
Definition: sig_analog.h:123
@ ANALOG_DIALMODE_BOTH
Definition: sig_analog.h:120
#define RING_PATTERNS
Definition: sig_analog.h:35
analog_event
Definition: sig_analog.h:79
@ ANALOG_EVENT_NONE
Definition: sig_analog.h:80
@ ANALOG_EVENT_HOOKCOMPLETE
Definition: sig_analog.h:89
@ ANALOG_EVENT_DTMFDOWN
Definition: sig_analog.h:104
@ ANALOG_EVENT_RINGEROFF
Definition: sig_analog.h:88
@ ANALOG_EVENT_PULSE_START
Definition: sig_analog.h:90
@ ANALOG_EVENT_DTMFCID
Definition: sig_analog.h:102
@ ANALOG_EVENT_TX_CED_DETECTED
Definition: sig_analog.h:97
@ ANALOG_EVENT_NEONMWI_ACTIVE
Definition: sig_analog.h:95
@ ANALOG_EVENT_RINGBEGIN
Definition: sig_analog.h:92
@ ANALOG_EVENT_ONHOOK
Definition: sig_analog.h:81
@ ANALOG_EVENT_EC_DISABLED
Definition: sig_analog.h:93
@ ANALOG_EVENT_WINKFLASH
Definition: sig_analog.h:83
@ ANALOG_EVENT_ERROR
Definition: sig_analog.h:101
@ ANALOG_EVENT_PULSEDIGIT
Definition: sig_analog.h:103
@ ANALOG_EVENT_RINGERON
Definition: sig_analog.h:87
@ ANALOG_EVENT_RX_CED_DETECTED
Definition: sig_analog.h:98
@ ANALOG_EVENT_ALARM
Definition: sig_analog.h:84
@ ANALOG_EVENT_DIALCOMPLETE
Definition: sig_analog.h:86
@ ANALOG_EVENT_EC_NLP_ENABLED
Definition: sig_analog.h:100
@ ANALOG_EVENT_POLARITY
Definition: sig_analog.h:91
@ ANALOG_EVENT_NEONMWI_INACTIVE
Definition: sig_analog.h:96
@ ANALOG_EVENT_DTMFUP
Definition: sig_analog.h:105
@ ANALOG_EVENT_EC_NLP_DISABLED
Definition: sig_analog.h:99
@ ANALOG_EVENT_RINGOFFHOOK
Definition: sig_analog.h:82
@ ANALOG_EVENT_REMOVED
Definition: sig_analog.h:94
@ ANALOG_EVENT_NOALARM
Definition: sig_analog.h:85
@ ANALOG_DIAL_OP_REPLACE
Definition: sig_analog.h:134
analog_sub
Definition: sig_analog.h:108
@ ANALOG_SUB_THREEWAY
Definition: sig_analog.h:111
@ ANALOG_SUB_REAL
Definition: sig_analog.h:109
@ ANALOG_SUB_CALLWAIT
Definition: sig_analog.h:110
#define ANALOG_FIRST_DIGIT_TIMEOUT
Default time (ms) to detect first digit.
Definition: sig_analog.h:38
analog_sigtype
Definition: sig_analog.h:45
@ ANALOG_SIG_FEATD
Definition: sig_analog.h:56
@ ANALOG_SIG_FEATDMF_TA
Definition: sig_analog.h:66
@ ANALOG_SIG_FGC_CAMAMF
Definition: sig_analog.h:60
@ ANALOG_SIG_FXOLS
Definition: sig_analog.h:47
@ ANALOG_SIG_FEATDMF
Definition: sig_analog.h:57
@ ANALOG_SIG_EM_E1
Definition: sig_analog.h:55
@ ANALOG_SIG_EMWINK
Definition: sig_analog.h:53
@ ANALOG_SIG_FXOKS
Definition: sig_analog.h:48
@ ANALOG_SIG_SF
Definition: sig_analog.h:63
@ ANALOG_SIG_FGC_CAMA
Definition: sig_analog.h:59
@ ANALOG_SIG_FXSLS
Definition: sig_analog.h:50
@ ANALOG_SIG_EM
Definition: sig_analog.h:54
@ ANALOG_SIG_FXOGS
Definition: sig_analog.h:49
@ ANALOG_SIG_NONE
Definition: sig_analog.h:46
@ ANALOG_SIG_FXSGS
Definition: sig_analog.h:52
@ ANALOG_SIG_SF_FEATDMF
Definition: sig_analog.h:65
@ ANALOG_SIG_SFWINK
Definition: sig_analog.h:62
@ ANALOG_SIG_FEATB
Definition: sig_analog.h:61
@ ANALOG_SIG_SF_FEATD
Definition: sig_analog.h:64
@ ANALOG_SIG_FXSKS
Definition: sig_analog.h:51
analog_tone
Definition: sig_analog.h:70
@ ANALOG_TONE_CONGESTION
Definition: sig_analog.h:73
@ ANALOG_TONE_INFO
Definition: sig_analog.h:76
@ ANALOG_TONE_DIALTONE
Definition: sig_analog.h:74
@ ANALOG_TONE_DIALRECALL
Definition: sig_analog.h:75
@ ANALOG_TONE_STUTTER
Definition: sig_analog.h:72
@ ANALOG_TONE_RINGTONE
Definition: sig_analog.h:71
@ ANALOG_CID_START_RING
Definition: sig_analog.h:129
@ ANALOG_CID_START_DTMF_NOALERT
Definition: sig_analog.h:130
@ ANALOG_CID_START_POLARITY
Definition: sig_analog.h:127
@ ANALOG_CID_START_POLARITY_IN
Definition: sig_analog.h:128
Interface header for PRI signaling module.
int sig_pri_is_chan_available(struct sig_pri_chan *pvt)
void sig_pri_unload(void)
sig_pri_law
Definition: sig_pri.h:67
@ SIG_PRI_DEFLAW
Definition: sig_pri.h:68
@ SIG_PRI_ULAW
Definition: sig_pri.h:69
@ SIG_PRI_ALAW
Definition: sig_pri.h:70
#define SIG_PRI_DEBUG_NORMAL
Definition: sig_pri.h:41
@ SIG_PRI_COLP_UPDATE
Definition: sig_pri.h:441
@ SIG_PRI_COLP_CONNECT
Definition: sig_pri.h:439
@ SIG_PRI_COLP_BLOCK
Definition: sig_pri.h:437
int pri_send_callrerouting_facility_exec(struct sig_pri_chan *p, enum ast_channel_state chanstate, const char *destination, const char *original, const char *reason)
int sig_pri_ami_show_spans(struct mansession *s, const char *show_cmd, struct sig_pri_span *pri, const int *dchannels, const char *action_id)
int sig_pri_cc_agent_status_req(struct ast_cc_agent *agent)
struct sig_pri_callback sig_pri_callbacks
int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condition, const void *data, size_t datalen)
void sig_pri_extract_called_num_subaddr(struct sig_pri_chan *p, const char *rdest, char *called, size_t called_buff_size)
#define SIG_PRI_NUM_DCHANS
Definition: sig_pri.h:239
int sig_pri_cc_agent_start_offer_timer(struct ast_cc_agent *agent)
int sig_pri_hangup(struct sig_pri_chan *p, struct ast_channel *ast)
int sig_pri_cc_monitor_unsuspend(struct ast_cc_monitor *monitor)
int sig_pri_available(struct sig_pri_chan **pvt, int is_specific_channel)
int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, const char *rdest, int timeout, int layer1)
#define DAHDI_OVERLAPDIAL_OUTGOING
Definition: sig_pri.h:252
int sig_pri_is_alarm_ignored(struct sig_pri_span *pri)
int sig_pri_cc_monitor_req_cc(struct ast_cc_monitor *monitor, int *available_timer_id)
int sig_pri_start_pri(struct sig_pri_span *pri)
int sig_pri_cc_monitor_cancel_available_timer(struct ast_cc_monitor *monitor, int *sched_id)
void sig_pri_cli_show_channels(int fd, struct sig_pri_span *pri)
void sig_pri_cc_agent_req_rsp(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
int sig_pri_cc_monitor_suspend(struct ast_cc_monitor *monitor)
@ SIG_PRI_RESET_IDLE
The channel is not being RESTARTed.
Definition: sig_pri.h:154
#define DAHDI_OVERLAPDIAL_BOTH
Definition: sig_pri.h:254
void sig_pri_stop_pri(struct sig_pri_span *pri)
void sig_pri_cc_agent_destructor(struct ast_cc_agent *agent)
void sig_pri_cli_show_spans(int fd, int span, struct sig_pri_span *pri)
void sig_pri_init_pri(struct sig_pri_span *pri)
#define SIG_PRI_AOC_GRANT_D
Definition: sig_pri.h:54
#define DAHDI_OVERLAPDIAL_NONE
Definition: sig_pri.h:251
int sig_pri_cc_agent_start_monitoring(struct ast_cc_agent *agent)
#define DAHDI_CHAN_MAPPING_LOGICAL
Definition: sig_pri.h:248
int sig_pri_cc_agent_init(struct ast_cc_agent *agent, struct sig_pri_chan *pvt_chan)
void sig_pri_chan_alarm_notify(struct sig_pri_chan *p, int noalarm)
int sig_pri_load(const char *cc_type_name)
@ SIG_PRI_CALL_LEVEL_PROCEEDING
Definition: sig_pri.h:143
@ SIG_PRI_MOH_SIGNALING_MOH
Definition: sig_pri.h:75
@ SIG_PRI_MOH_SIGNALING_NOTIFY
Definition: sig_pri.h:77
int sig_pri_cc_agent_callee_available(struct ast_cc_agent *agent)
#define DAHDI_OVERLAPDIAL_INCOMING
Definition: sig_pri.h:253
struct ast_channel * sig_pri_request(struct sig_pri_chan *p, enum sig_pri_law law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, int transfercapability)
#define SIG_PRI_AOC_GRANT_E
Definition: sig_pri.h:55
void sig_pri_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, struct sig_pri_chan *pchan)
void sig_pri_cc_monitor_destructor(void *monitor_pvt)
void sig_pri_dial_complete(struct sig_pri_chan *pvt, struct ast_channel *ast)
struct sig_pri_chan * sig_pri_chan_new(void *pvt_data, struct sig_pri_span *pri, int logicalspan, int channo, int trunkgroup)
void pri_event_noalarm(struct sig_pri_span *pri, int index, int before_start_pri)
void sig_pri_cli_show_span(int fd, int *dchannels, struct sig_pri_span *pri)
void sig_pri_chan_delete(struct sig_pri_chan *doomed)
int sig_pri_answer(struct sig_pri_chan *p, struct ast_channel *ast)
#define SIG_PRI_AOC_GRANT_S
Definition: sig_pri.h:53
sig_pri_tone
Definition: sig_pri.h:57
@ SIG_PRI_TONE_RINGTONE
Definition: sig_pri.h:58
@ SIG_PRI_TONE_INFO
Definition: sig_pri.h:63
@ SIG_PRI_TONE_DIALTONE
Definition: sig_pri.h:61
@ SIG_PRI_TONE_BUSY
Definition: sig_pri.h:64
@ SIG_PRI_TONE_STUTTER
Definition: sig_pri.h:59
@ SIG_PRI_TONE_CONGESTION
Definition: sig_pri.h:60
@ SIG_PRI_TONE_DIALRECALL
Definition: sig_pri.h:62
void pri_event_alarm(struct sig_pri_span *pri, int index, int before_start_pri)
int sig_pri_cc_agent_stop_offer_timer(struct ast_cc_agent *agent)
void sig_pri_cli_show_channels_header(int fd)
void sig_pri_set_alarm(struct sig_pri_chan *p, int in_alarm)
int sig_pri_cc_agent_party_b_free(struct ast_cc_agent *agent)
int sig_pri_cc_monitor_status_rsp(struct ast_cc_monitor *monitor, enum ast_device_state devstate)
#define DAHDI_CHAN_MAPPING_PHYSICAL
Definition: sig_pri.h:247
int sig_pri_cc_agent_stop_ringing(struct ast_cc_agent *agent)
int sig_pri_digit_begin(struct sig_pri_chan *pvt, struct ast_channel *ast, char digit)
int pri_send_keypad_facility_exec(struct sig_pri_chan *p, const char *digits)
Interface header for SS7 signaling module.
void sig_ss7_cb_call_null(struct ss7 *ss7, struct isup_call *c, int lock)
void sig_ss7_link_noalarm(struct sig_ss7_linkset *linkset, int which)
void sig_ss7_cli_show_channels_header(int fd)
struct ast_channel * sig_ss7_request(struct sig_ss7_chan *p, enum sig_ss7_law law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, int transfercapability)
void sig_ss7_init_linkset(struct sig_ss7_linkset *ss7)
void sig_ss7_link_alarm(struct sig_ss7_linkset *linkset, int which)
#define LINKSET_FLAG_EXPLICITACM
Definition: sig_ss7.h:68
#define LINKSET_FLAG_AUTOACM
Definition: sig_ss7.h:72
int sig_ss7_reset_group(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc, int range)
int sig_ss7_available(struct sig_ss7_chan *p)
void sig_ss7_cb_notinservice(struct ss7 *ss7, int cic, unsigned int dpc)
int sig_ss7_reset_cic(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc)
int sig_ss7_call(struct sig_ss7_chan *p, struct ast_channel *ast, const char *rdest)
void * ss7_linkset(void *data)
int sig_ss7_indicate(struct sig_ss7_chan *p, struct ast_channel *chan, int condition, const void *data, size_t datalen)
#define SS7_BLOCKED_MAINTENANCE
Definition: sig_ss7.h:74
int sig_ss7_group_blocking(struct sig_ss7_linkset *linkset, int do_block, int startcic, int endcic, unsigned char state[], int type)
int sig_ss7_find_cic(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc)
#define SIG_SS7_DEBUG
Definition: sig_ss7.h:43
struct sig_ss7_callback sig_ss7_callbacks
void sig_ss7_set_alarm(struct sig_ss7_chan *p, int in_alarm)
sig_ss7_tone
Definition: sig_ss7.h:78
@ SIG_SS7_TONE_DIALRECALL
Definition: sig_ss7.h:83
@ SIG_SS7_TONE_INFO
Definition: sig_ss7.h:84
@ SIG_SS7_TONE_STUTTER
Definition: sig_ss7.h:80
@ SIG_SS7_TONE_RINGTONE
Definition: sig_ss7.h:79
@ SIG_SS7_TONE_CONGESTION
Definition: sig_ss7.h:81
@ SIG_SS7_TONE_DIALTONE
Definition: sig_ss7.h:82
@ SIG_SS7_TONE_BUSY
Definition: sig_ss7.h:85
struct sig_ss7_chan * sig_ss7_chan_new(void *pvt_data, struct sig_ss7_linkset *ss7)
void sig_ss7_cli_show_channels(int fd, struct sig_ss7_linkset *linkset)
int sig_ss7_cic_blocking(struct sig_ss7_linkset *linkset, int do_block, int cic)
#define LINKSET_FLAG_DEFAULTECHOCONTROL
Definition: sig_ss7.h:71
sig_ss7_law
Definition: sig_ss7.h:88
@ SIG_SS7_DEFLAW
Definition: sig_ss7.h:89
@ SIG_SS7_ULAW
Definition: sig_ss7.h:90
@ SIG_SS7_ALAW
Definition: sig_ss7.h:91
#define LINKSET_FLAG_USEECHOCONTROL
Definition: sig_ss7.h:70
void sig_ss7_chan_delete(struct sig_ss7_chan *doomed)
#define LINKSET_FLAG_INITIALHWBLO
Definition: sig_ss7.h:69
int sig_ss7_cb_hangup(struct ss7 *ss7, int cic, unsigned int dpc, int cause, int do_hangup)
#define SS7_NAI_DYNAMIC
Definition: sig_ss7.h:66
int sig_ss7_add_sigchan(struct sig_ss7_linkset *linkset, int which, int ss7type, int transport, int inalarm, int networkindicator, int pointcode, int adjpointcode, int cur_slc)
int sig_ss7_hangup(struct sig_ss7_chan *p, struct ast_channel *ast)
void sig_ss7_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, struct sig_ss7_chan *pchan)
#define SS7_BLOCKED_HARDWARE
Definition: sig_ss7.h:75
#define SIG_SS7_NUM_DCHANS
Definition: sig_ss7.h:56
int sig_ss7_answer(struct sig_ss7_chan *p, struct ast_channel *ast)
int sig_ss7_find_cic_range(struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc)
SMDI support for Asterisk.
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
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
#define SMDI_MAX_FILENAME_LEN
Definition: smdi.h:42
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1515
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
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1493
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
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 * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#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
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
#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 force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
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
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
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
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
int(*const play_tone)(void *pvt, enum analog_sub sub, enum analog_tone tone)
Definition: sig_analog.h:182
unsigned int immediate
Definition: sig_analog.h:298
unsigned int immediatering
Definition: sig_analog.h:299
unsigned int permcallwaiting
Definition: sig_analog.h:300
unsigned int canpark
Definition: sig_analog.h:295
unsigned int dahditrcallerid
Definition: sig_analog.h:296
int polarityonanswerdelay
Definition: sig_analog.h:324
char cid_num[AST_MAX_EXTENSION]
Definition: sig_analog.h:328
int redirecting_reason
Definition: sig_analog.h:356
unsigned int permhidecallerid
Definition: sig_analog.h:301
unsigned int callwaitingcallerid
Definition: sig_analog.h:309
unsigned int ani_wink_time
Definition: sig_analog.h:289
enum analog_sigtype outsigmod
Definition: sig_analog.h:320
unsigned int usedistinctiveringdetection
Definition: sig_analog.h:308
unsigned int answeronpolarityswitch
Definition: sig_analog.h:291
unsigned int threewaycalling
Definition: sig_analog.h:303
unsigned int pulse
Definition: sig_analog.h:302
int echotraining
Definition: sig_analog.h:322
int msgstate
-1 = unknown, 0 = no messages, 1 = new messages available
Definition: sig_analog.h:284
int onhooktime
Definition: sig_analog.h:281
unsigned int hanguponpolarityswitch
Definition: sig_analog.h:297
enum analog_cid_start cid_start
Definition: sig_analog.h:326
unsigned int callreturn
Definition: sig_analog.h:293
struct ast_channel * owner
Definition: sig_analog.h:277
unsigned int use_smdi
TRUE if SMDI (Simplified Message Desk Interface) is enabled.
Definition: sig_analog.h:313
unsigned int call_qualifier
Definition: sig_analog.h:349
unsigned int ani_timeout
Definition: sig_analog.h:288
int ringt_base
Definition: sig_analog.h:376
int fxsoffhookstate
Definition: sig_analog.h:282
unsigned int ani_info_digits
Definition: sig_analog.h:287
enum analog_dialmode dialmode
Definition: sig_analog.h:321
unsigned int cancallforward
Definition: sig_analog.h:294
struct analog_subchannel subs[3]
Definition: sig_analog.h:279
int cid_signalling
Definition: sig_analog.h:323
unsigned int transfer
Definition: sig_analog.h:305
unsigned int transfertobusy
Definition: sig_analog.h:306
unsigned int inalarm
Definition: sig_analog.h:341
char cid_name[AST_MAX_EXTENSION]
Definition: sig_analog.h:329
int stripmsd
Definition: sig_analog.h:325
unsigned int calledsubscriberheld
Definition: sig_analog.h:292
char mohsuggest[MAX_MUSICCLASS]
Definition: sig_analog.h:327
unsigned int use_callerid
Definition: sig_analog.h:307
struct ast_channel * ss_astchan
Definition: sig_analog.h:372
struct ast_smdi_interface * smdi_iface
The SMDI interface to get SMDI messages from.
Definition: sig_analog.h:315
struct ast_party_caller caller
Definition: sig_analog.h:355
struct ast_channel * owner
Definition: sig_analog.h:264
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:604
Structure that contains information regarding a channel in a bridge.
struct ast_channel * chan
const char * type
Type of agent the callbacks belong to.
Definition: ccss.h:857
Callbacks defined by CC monitors.
Definition: ccss.h:542
const char * type
Type of monitor the callbacks belong to.
Definition: ccss.h:549
Blob of data associated with a channel.
struct ast_channel_snapshot * snapshot
struct ast_json * blob
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition: channel.h:628
struct ast_format_cap * capabilities
Definition: channel.h:632
const char *const type
Definition: channel.h:629
Main Channel structure associated with a channel.
char exten[AST_MAX_EXTENSION]
const char * data
char x
Definition: extconf.c:81
struct ast_party_redirecting redirecting
Redirecting/Diversion information.
const ast_string_field name
struct ast_flags flags
descriptor for a cli entry.
Definition: cli.h:171
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
char chan_name[AST_CHANNEL_NAME]
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
const char * name
Definition: pbx.h:119
int pattern[4]
Definition: dsp.h:68
Configuration relating to call pickup.
Structure used to handle boolean flags.
Definition: utils.h:199
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Definition of a media format.
Definition: format.c:43
struct ast_codec * codec
Pointer to the codec in use for this format.
Definition: format.c:47
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
union ast_frame::@226 data
struct timeval delivery
enum ast_frame_type frametype
unsigned int flags
const char * src
General jitterbuffer configuration.
Definition: abstract_jb.h:70
unsigned int flags
Combination of the AST_JB_ENABLED, AST_JB_FORCED and AST_JB_LOG flags.
Definition: abstract_jb.h:72
Abstract JSON element (object, array, string, int, ...).
Struct containing info for an AMI event to send out.
Definition: manager.h:502
struct ast_module * self
Definition: module.h:356
The structure that contains MWI state.
Definition: mwi.h:455
int new_msgs
Definition: mwi.h:459
Caller Party information.
Definition: channel.h:418
struct ast_party_id id
Caller party ID.
Definition: channel.h:420
int ani2
Automatic Number Identification 2 (Info Digits)
Definition: channel.h:433
struct ast_party_id ani
Automatic Number Identification (ANI)
Definition: channel.h:427
struct ast_party_id id
Connected party ID.
Definition: channel.h:458
struct ast_party_dialed::@208 number
Dialed/Called number.
char * str
Subscriber phone number (Malloced)
Definition: channel.h:386
struct ast_party_subaddress subaddress
Subscriber subaddress.
Definition: channel.h:344
char * tag
User-set "tag".
Definition: channel.h:354
struct ast_party_name name
Subscriber name.
Definition: channel.h:340
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:342
int presentation
Q.931 encoded presentation-indicator encoded field.
Definition: channel.h:277
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:279
char * str
Subscriber name (Malloced)
Definition: channel.h:264
int presentation
Q.931 presentation-indicator and screening-indicator encoded fields.
Definition: channel.h:295
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:297
char * str
Subscriber phone number (Malloced)
Definition: channel.h:291
int plan
Q.931 Type-Of-Number and Numbering-Plan encoded fields.
Definition: channel.h:293
int code
enum AST_REDIRECTING_REASON value for redirection
Definition: channel.h:510
struct ast_party_redirecting_reason reason
Reason for the redirection.
Definition: channel.h:542
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:527
unsigned char valid
TRUE if the subaddress information is valid/present.
Definition: channel.h:328
char * str
Malloced subaddress string.
Definition: channel.h:313
An SMDI message desk message.
Definition: smdi.h:65
char calling_st[SMDI_MAX_STATION_NUM_LEN+1]
Definition: smdi.h:70
char fwd_st[SMDI_MAX_STATION_NUM_LEN+1]
Definition: smdi.h:69
Support for dynamic strings.
Definition: strings.h:623
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
char number[64]
Definition: callerid.c:54
Definition: astman.c:88
All configuration options for http media cache.
Channel configuration from chan_dahdi.conf . This struct is used for parsing the [channels] section o...
Definition: chan_dahdi.c:952
char smdi_port[SMDI_MAX_FILENAME_LEN]
The serial port to listen for SMDI data on.
Definition: chan_dahdi.c:974
int ignore_failed_channels
Definition: chan_dahdi.c:968
struct dahdi_params timing
Definition: chan_dahdi.c:965
int wanted_channels_end
Don't create channels above this number (infinity by default)
Definition: chan_dahdi.c:986
struct dahdi_pvt chan
Definition: chan_dahdi.c:953
int wanted_channels_start
Don't create channels below this number.
Definition: chan_dahdi.c:980
struct ringContextData ringContext[3]
Definition: chan_dahdi.h:71
struct distRingData ringnum[3]
Definition: chan_dahdi.h:70
unsigned int echocanon
TRUE if echo cancellation is turned on.
Definition: chan_dahdi.h:272
char dialdest[256]
Delayed dialing for E911. Overlap digits for ISDN.
Definition: chan_dahdi.h:713
unsigned int immediate
TRUE if the channel should be answered immediately without attempting to gather any digits.
Definition: chan_dahdi.h:316
unsigned int immediatering
TRUE if audible ringback should be provided when immediate = yes.
Definition: chan_dahdi.h:322
unsigned int threewaysilenthold
TRUE if a three way dial tone should time out to silence.
Definition: chan_dahdi.h:373
enum DAHDI_IFLIST which_iflist
Definition: chan_dahdi.h:168
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
float cid_rxgain
Amount of gain to increase during caller id.
Definition: chan_dahdi.h:158
float txdrc
Definition: chan_dahdi.h:164
struct dahdi_distRings drings
Distinctive Ring data.
Definition: chan_dahdi.h:485
struct ast_variable * vars
Channel variable list with associated values to set when a channel is created.
Definition: chan_dahdi.h:584
char cid_subaddr[AST_MAX_EXTENSION]
Caller ID subaddress from an incoming call.
Definition: chan_dahdi.h:537
unsigned int canpark
TRUE if support for call parking is enabled.
Definition: chan_dahdi.h:243
unsigned int bufferoverrideinuse
Definition: chan_dahdi.h:278
int law
Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW.
Definition: chan_dahdi.h:556
int bufsize
Definition: chan_dahdi.h:138
unsigned int hwtxgain_enabled
TRUE if hardware Tx gain set by Asterisk.
Definition: chan_dahdi.h:469
unsigned int dnd
TRUE if Do-Not-Disturb is enabled, present only for non sig_analog.
Definition: chan_dahdi.h:262
int faxbuf_policy
Definition: chan_dahdi.h:142
unsigned int ignoredtmf
TRUE if DTMF detection is disabled.
Definition: chan_dahdi.h:310
struct dahdi_dialoperation dop
DAHDI dial operation command struct for ioctl() call.
Definition: chan_dahdi.h:696
struct timeval dtmfcid_delay
Definition: chan_dahdi.h:591
unsigned int dahditrcallerid
TRUE if we should use the callerid from incoming call on dahdi transfer.
Definition: chan_dahdi.h:408
struct dahdi_pvt * next
Definition: chan_dahdi.h:169
unsigned int doreoriginate
Internal flag for if we should actually process a reorigination.
Definition: chan_dahdi.h:293
unsigned char * cidspill
Analog caller ID waveform sample buffer.
Definition: chan_dahdi.h:597
struct tdd_state * tdd
Definition: chan_dahdi.h:702
int waitfordialtonetemp
Transient variable. Same as waitfordialtone, but temporarily set for a specific call,...
Definition: chan_dahdi.h:660
int cidlen
Length of the cidspill buffer containing samples.
Definition: chan_dahdi.h:601
int polarityonanswerdelay
Minimal time period (ms) between the answer polarity switch and hangup polarity switch.
Definition: chan_dahdi.h:727
int busycount
Number of times to see "busy" tone before hanging up.
Definition: chan_dahdi.h:641
char cid_num[AST_MAX_EXTENSION]
Caller ID number from an incoming call.
Definition: chan_dahdi.h:526
int ringt
Ring timeout timer??
Definition: chan_dahdi.h:603
struct ast_mwi_subscriber * mwi_event_sub
Opaque event subscription parameters for message waiting indication support.
Definition: chan_dahdi.h:711
ast_group_t group
Bitmapped groups this belongs to.
Definition: chan_dahdi.h:552
int sendcalleridafter
Send caller ID on FXS after this many rings. Set to 1 for US.
Definition: chan_dahdi.h:734
struct dahdi_pvt * oprpeer
Definition: chan_dahdi.h:152
unsigned int permhidecallerid
TRUE if the outgoing caller ID is blocked/restricted/hidden.
Definition: chan_dahdi.h:339
unsigned int mwisendactive
TRUE if a MWI message sending thread is active.
Definition: chan_dahdi.h:433
char * origcid_name
Definition: chan_dahdi.h:539
struct mwisend_info mwisend_data
Definition: chan_dahdi.h:480
int cid_suppress_expire
Definition: chan_dahdi.h:595
struct timeval flashtime
Definition: chan_dahdi.h:692
int oprmode
Definition: chan_dahdi.h:151
int interdigit_timeout
Time (ms) to detect following digits (in an analog phone)
Definition: chan_dahdi.h:685
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
struct dahdi_pvt * master
Definition: chan_dahdi.h:135
unsigned int confirmanswer
TRUE if to wait for a DTMF digit to confirm answer.
Definition: chan_dahdi.h:245
unsigned int restartpending
Definition: chan_dahdi.h:357
unsigned int mwimonitoractive
TRUE if an MWI monitor thread is currently active.
Definition: chan_dahdi.h:431
unsigned int outgoing
TRUE if we originated the call leg.
Definition: chan_dahdi.h:328
unsigned int faxdetect_timeout
The number of seconds into call to disable fax detection. (0 = disabled)
Definition: chan_dahdi.h:675
int whichwink
Definition: chan_dahdi.h:697
float rxdrc
Definition: chan_dahdi.h:165
unsigned int callwaitingcallerid
TRUE if send caller ID for Call Waiting.
Definition: chan_dahdi.h:231
char * origcid_num
Definition: chan_dahdi.h:538
unsigned int manages_span_alarms
TRUE if the channel alarms will be managed also as Span ones.
Definition: chan_dahdi.h:465
unsigned int ani_wink_time
INTEGER, length of time to wait before sending ANI wink in ms.
Definition: chan_dahdi.h:200
int waitfordialtone
Number of milliseconds to wait for dialtone.
Definition: chan_dahdi.h:656
unsigned int locallyblocked
Bitmask for the channel being locally blocked.
Definition: chan_dahdi.h:451
unsigned int adsi
TRUE if ADSI (Analog Display Services Interface) available.
Definition: chan_dahdi.h:178
int outsigmod
Definition: chan_dahdi.h:150
unsigned int usedistinctiveringdetection
TRUE if distinctive rings are to be detected.
Definition: chan_dahdi.h:403
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
unsigned int threewaycalling
TRUE if three way calling is enabled.
Definition: chan_dahdi.h:368
struct dahdi_subchannel subs[3]
Definition: chan_dahdi.h:131
int distinctivering
Definition: chan_dahdi.h:719
struct dahdi_confinfo saveconf
Definition: chan_dahdi.h:132
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
int dtmfrelax
Definition: chan_dahdi.h:720
unsigned int pulse
TRUE if we will pulse dial.
Definition: chan_dahdi.h:354
int dialtone_scanning_time_elapsed
Definition: chan_dahdi.h:670
unsigned int priexclusive
TRUE if PRI B channels are always exclusively selected.
Definition: chan_dahdi.h:349
char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Voice mailbox location.
Definition: chan_dahdi.h:709
float hwrxgain
Hardware Rx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:154
int echotraining
Echo training time. 0 = disabled.
Definition: chan_dahdi.h:634
int tonezone
Definition: chan_dahdi.h:167
char callwait_num[AST_MAX_EXTENSION]
Call waiting number.
Definition: chan_dahdi.h:541
float hwtxgain
Hardware Tx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:156
int waitfordialtoneduration
Transient variable. Stored off waitfordialtone duration at runtime.
Definition: chan_dahdi.h:664
int dsp_features
DSP feature flags: DSP_FEATURE_xxx.
Definition: chan_dahdi.h:738
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
char exten[AST_MAX_EXTENSION]
Extension to use in the dialplan.
Definition: chan_dahdi.h:502
int callprogress
Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
Definition: chan_dahdi.h:651
int callwaitcas
TRUE if Call Waiting (CW) CPE Alert Signal (CAS) is being sent.
Definition: chan_dahdi.h:622
time_t guardtime
Definition: chan_dahdi.h:587
struct timeval polaritydelaytv
Start delay time if polarityonanswerdelay is nonzero.
Definition: chan_dahdi.h:729
unsigned int hanguponpolarityswitch
TRUE if the call will be considered "hung up" on a polarity reversal.
Definition: chan_dahdi.h:285
char dnid[AST_MAX_EXTENSION]
Dialed Number Identifier.
Definition: chan_dahdi.h:547
char dialstring[AST_CHANNEL_NAME]
Definition: chan_dahdi.h:772
char call_forward[AST_MAX_EXTENSION]
Accumulated call forwarding number.
Definition: chan_dahdi.h:704
char description[32]
A description for the channel configuration.
Definition: chan_dahdi.h:496
unsigned int firstradio
TRUE if over a radio and dahdi_read() has been called.
Definition: chan_dahdi.h:280
unsigned int remotelyblocked
Bitmask for the channel being remotely blocked. 1 maintenance, 2 blocked in hardware.
Definition: chan_dahdi.h:460
struct dahdi_pvt::@115 echocancel
Echo cancel parameters.
unsigned int hidecallerid
TRUE if the outgoing caller ID is blocked/hidden.
Definition: chan_dahdi.h:302
unsigned int echobreak
XXX BOOLEAN Purpose???
Definition: chan_dahdi.h:264
struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS]
Definition: chan_dahdi.h:628
int faxbuf_no
Definition: chan_dahdi.h:141
unsigned int callreturn
TRUE if call return is enabled. (*69, if your dialplan doesn't catch this first)
Definition: chan_dahdi.h:219
struct ast_namedgroups * named_pickupgroups
Named pickup groups this belongs to.
Definition: chan_dahdi.h:579
struct ast_channel * owner
Definition: chan_dahdi.h:127
char rdnis[AST_MAX_EXTENSION]
Redirecting Directory Number Information Service (RDNIS) number.
Definition: chan_dahdi.h:545
unsigned int faxhandled
TRUE if a fax tone has already been handled.
Definition: chan_dahdi.h:274
unsigned int use_smdi
TRUE if SMDI (Simplified Message Desk Interface) is enabled.
Definition: chan_dahdi.h:479
struct callerid_state * cs
Definition: chan_dahdi.h:126
int cid_ani2
Automatic Number Identification code from PRI.
Definition: chan_dahdi.h:524
struct ast_namedgroups * named_callgroups
Named call groups this belongs to.
Definition: chan_dahdi.h:574
int callwaitrings
Number of call waiting rings.
Definition: chan_dahdi.h:624
unsigned int mwimonitor_neon
TRUE if the FXO port monitors for neon type MWI indications from the other end.
Definition: chan_dahdi.h:418
unsigned int dialednone
TRUE if analog type line dialed no digits in Dial()
Definition: chan_dahdi.h:253
unsigned int hwrxgain_enabled
TRUE if hardware Rx gain set by Asterisk.
Definition: chan_dahdi.h:467
int law_default
Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW.
Definition: chan_dahdi.h:554
int fake_event
Holding place for event injected from outside normal operation.
Definition: chan_dahdi.h:722
unsigned int didtdd
Definition: chan_dahdi.h:251
char echorest[20]
Filled with 'w'. XXX Purpose??
Definition: chan_dahdi.h:636
struct dahdi_pvt * slaves[MAX_SLAVES]
Definition: chan_dahdi.h:134
void * sig_pvt
Definition: chan_dahdi.h:764
int confno
Definition: chan_dahdi.h:557
unsigned int ani_timeout
INTEGER, length of ANI failure timeout in ms.
Definition: chan_dahdi.h:195
int dtmfcid_holdoff_state
Definition: chan_dahdi.h:590
unsigned int mwioverride_active
TRUE if a manual MWI override is active for a channel.
Definition: chan_dahdi.h:435
unsigned int mwimonitor_fsk
TRUE if the FXO port monitors for fsk type MWI indications from the other end.
Definition: chan_dahdi.h:423
int ringt_base
Ring timeout base.
Definition: chan_dahdi.h:608
int cid_start
Definition: chan_dahdi.h:589
unsigned int destroy
TRUE if the channel is to be destroyed on hangup. (Used by pseudo channels.)
Definition: chan_dahdi.h:250
unsigned int restrictcid
TRUE if caller ID is restricted.
Definition: chan_dahdi.h:363
char defcontext[AST_MAX_CONTEXT]
Default distinctive ring context.
Definition: chan_dahdi.h:500
unsigned int priindication_oob
TRUE if PRI congestion/busy indications are sent out-of-band.
Definition: chan_dahdi.h:344
unsigned int ani_info_digits
INTEGER, number of ANI INFO digits on a CAMA trunk. older switches use 1 INFO digit,...
Definition: chan_dahdi.h:190
unsigned int busydetect
TRUE if busy detection is enabled. (Listens for the beep-beep busy pattern.)
Definition: chan_dahdi.h:206
unsigned int hidecalleridname
TRUE if hide just the name not the number for legacy PBX use.
Definition: chan_dahdi.h:308
struct timeval waitingfordt
Definition: chan_dahdi.h:691
struct ast_dsp * dsp
Opaque DSP configuration structure.
Definition: chan_dahdi.h:694
struct dahdi_pvt * prev
Definition: chan_dahdi.h:170
ast_group_t pickupgroup
Bitmapped pickup groups this belongs to.
Definition: chan_dahdi.h:569
int callingpres
Definition: chan_dahdi.h:592
int dialmode
Definition: chan_dahdi.h:149
unsigned int reoriginate
TRUE if FXS (FXO-signalled) channel should reoriginate for user to make a new call.
Definition: chan_dahdi.h:289
int buf_policy
Definition: chan_dahdi.h:140
int cidpos
Position in the cidspill buffer to send out next.
Definition: chan_dahdi.h:599
char context[AST_MAX_CONTEXT]
The configured context for incoming calls.
Definition: chan_dahdi.h:491
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
int radio
Nonzero if the signaling type is sent over a radio.
Definition: chan_dahdi.h:148
char parkinglot[AST_MAX_EXTENSION]
Definition: chan_dahdi.h:518
int cidcwexpire
Definition: chan_dahdi.h:594
unsigned int hardwaredtmf
TRUE if DTMF detection needs to be done by hardware.
Definition: chan_dahdi.h:295
int callwaitingrepeat
Definition: chan_dahdi.h:593
char begindigit
DTMF digit in progress. 0 when no digit in progress.
Definition: chan_dahdi.h:761
struct ast_cc_config_params * cc_params
Definition: chan_dahdi.h:765
unsigned int mate
TRUE if TDD in MATE mode.
Definition: chan_dahdi.h:326
float txgain
Software Tx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:162
int firstdigit_timeout
Time (ms) to detect first digit (in an analog phone)
Definition: chan_dahdi.h:680
int amaflags
Definition: chan_dahdi.h:701
struct dahdi_echocanparams head
Definition: chan_dahdi.h:627
unsigned int echocanbridged
TRUE if echo cancellation enabled when bridged.
Definition: chan_dahdi.h:270
int cid_signalling
Definition: chan_dahdi.h:588
char finaldial[64]
Second part of SIG_FEATDMF_TA wink operation.
Definition: chan_dahdi.h:699
unsigned int transfer
TRUE if call transfer is enabled.
Definition: chan_dahdi.h:382
unsigned int transfertobusy
TRUE if allowed to flash-transfer to busy channels.
Definition: chan_dahdi.h:413
int buf_no
Definition: chan_dahdi.h:139
unsigned int inalarm
TRUE if in an alarm condition.
Definition: chan_dahdi.h:324
char cid_name[AST_MAX_EXTENSION]
Caller ID name from an incoming call.
Definition: chan_dahdi.h:535
ast_mutex_t lock
Definition: chan_dahdi.h:125
unsigned int inservice
TRUE if channel is out of reset and ready.
Definition: chan_dahdi.h:442
char language[MAX_LANGUAGE]
Language configured for calls.
Definition: chan_dahdi.h:507
unsigned int digital
TRUE if the transfer capability of the call is digital.
Definition: chan_dahdi.h:260
int channel
Definition: chan_dahdi.h:585
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_dahdi.h:700
unsigned int mwioverride_disposition
Manual MWI disposition (on/off)
Definition: chan_dahdi.h:437
struct ast_dsp_busy_pattern busy_cadence
Busy cadence pattern description.
Definition: chan_dahdi.h:646
int stripmsd
Number of most significant digits/characters to strip from the dialed number.
Definition: chan_dahdi.h:615
unsigned int pulsedial
TRUE if a pulsed digit was detected. (Pulse dial phone detected)
Definition: chan_dahdi.h:356
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
int muting
TRUE if confrence is muted.
Definition: chan_dahdi.h:763
char cid_tag[AST_MAX_EXTENSION]
Caller ID tag from incoming call.
Definition: chan_dahdi.h:531
int matchdigit_timeout
Time (ms) to wait, in case of ambiguous match (in an analog phone)
Definition: chan_dahdi.h:690
char mohsuggest[MAX_MUSICCLASS]
Suggested music-on-hold class for peer channel to use for calls.
Definition: chan_dahdi.h:517
unsigned int use_callerid
TRUE if caller ID is used on this channel.
Definition: chan_dahdi.h:390
float rxgain
Software Rx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:160
int polarity
Current line interface polarity. POLARITY_IDLE, POLARITY_REV.
Definition: chan_dahdi.h:736
ast_group_t callgroup
Bitmapped call groups this belongs to.
Definition: chan_dahdi.h:564
unsigned int dialing
TRUE if in the process of dialing digits or sending something.
Definition: chan_dahdi.h:258
unsigned int usefaxbuffers
Definition: chan_dahdi.h:276
char callwait_name[AST_MAX_EXTENSION]
Call waiting name.
Definition: chan_dahdi.h:543
char mohinterpret[MAX_MUSICCLASS]
The configured music-on-hold class to use for calls.
Definition: chan_dahdi.h:512
int dialtone_detect
Number of frames to watch for dialtone in incoming calls.
Definition: chan_dahdi.h:669
struct ast_smdi_interface * smdi_iface
The SMDI interface to get SMDI messages from.
Definition: chan_dahdi.h:482
int inconference
Definition: chan_dahdi.h:136
int cid_ton
Caller ID Q.931 TON/NPI field values. Set by PRI. Zero otherwise.
Definition: chan_dahdi.h:533
ast_group_t groupmatch
Definition: chan_dahdi.c:13726
unsigned int needanswer
Definition: chan_dahdi.h:86
unsigned int needringing
Definition: chan_dahdi.h:83
unsigned int linear
Definition: chan_dahdi.h:90
unsigned int needhold
Definition: chan_dahdi.h:88
unsigned int needunhold
Definition: chan_dahdi.h:89
struct ast_frame f
Definition: chan_dahdi.h:82
unsigned int inthreeway
Definition: chan_dahdi.h:91
struct ast_channel * owner
Definition: chan_dahdi.h:79
struct dahdi_confinfo curconf
Definition: chan_dahdi.h:92
unsigned int needflash
Definition: chan_dahdi.h:87
unsigned int needbusy
Definition: chan_dahdi.h:84
short buffer[AST_FRIENDLY_OFFSET/2+READ_SIZE]
Definition: chan_dahdi.h:81
unsigned int needcongestion
Definition: chan_dahdi.h:85
int ring[3]
Definition: chan_dahdi.h:63
Definition: search.h:40
Definition: astman.c:222
Definition: logger.c:172
In case you didn't read that giant block of text above the mansession_session struct,...
Definition: manager.c:1785
struct dahdi_pvt * pvt
Definition: chan_dahdi.c:11084
unsigned char buf[READ_SIZE]
Definition: chan_dahdi.c:11085
mwisend_states mwisend_current
Definition: chan_dahdi.h:112
struct timeval pause
Definition: chan_dahdi.h:111
Number structure.
Definition: app_followme.c:154
struct ast_channel * peer
char contextData[AST_MAX_CONTEXT]
Definition: chan_dahdi.h:67
void(*const handle_dchan_exception)(struct sig_pri_span *pri, int index)
Definition: sig_pri.h:202
unsigned int immediate
Definition: sig_pri.h:282
struct sig_pri_span * pri
Definition: sig_pri.h:355
void * chan_pvt
Definition: sig_pri.h:374
enum sig_pri_reset_state resetting
Channel reset/restart state.
Definition: sig_pri.h:361
unsigned int allocated
TRUE when this channel is allocated.
Definition: sig_pri.h:339
unsigned int use_callingpres
Definition: sig_pri.h:286
unsigned int priexclusive
Definition: sig_pri.h:283
unsigned int hidecallerid
Definition: sig_pri.h:280
unsigned int priindication_oob
Definition: sig_pri.h:284
unsigned int hidecalleridname
Definition: sig_pri.h:281
char context[AST_MAX_CONTEXT]
Definition: sig_pri.h:287
unsigned int inalarm
Definition: sig_pri.h:324
int channel
Definition: sig_pri.h:290
unsigned int no_b_channel
TRUE if this interface has no B channel. (call hold and call waiting)
Definition: sig_pri.h:343
int stripmsd
Definition: sig_pri.h:289
unsigned int use_callerid
Definition: sig_pri.h:285
char mohinterpret[MAX_MUSICCLASS]
Definition: sig_pri.h:288
q931_call * call
Definition: sig_pri.h:356
struct sig_pri_chan * pvts[SIG_PRI_MAX_CHANNELS]
Definition: sig_pri.h:614
struct pri * pri
Definition: sig_pri.h:602
int nodetype
Definition: sig_pri.h:555
int numchans
Definition: sig_pri.h:613
char idleext[AST_MAX_EXTENSION]
Definition: sig_pri.h:550
int switchtype
Definition: sig_pri.h:556
int minunused
Definition: sig_pri.h:553
int fds[SIG_PRI_NUM_DCHANS]
Definition: sig_pri.h:457
int minidle
Definition: sig_pri.h:554
int trunkgroup
Definition: sig_pri.h:558
pthread_t master
Definition: sig_pri.h:615
int dialplan
Definition: sig_pri.h:504
int congestion_devstate
Congestion device state of the span.
Definition: sig_pri.h:627
void * no_b_chan_end
Definition: sig_pri.h:612
void * no_b_chan_iflist
Definition: sig_pri.h:607
ast_mutex_t lock
Definition: sig_pri.h:616
char idledial[AST_MAX_EXTENSION]
Definition: sig_pri.h:552
void(*const lock_private)(void *pvt)
Definition: sig_ss7.h:157
unsigned int immediate
Definition: sig_ss7.h:221
void * chan_pvt
Definition: sig_ss7.h:190
unsigned int locallyblocked
Bitmask for the channel being locally blocked.
Definition: sig_ss7.h:228
unsigned int dpc
Definition: sig_ss7.h:202
unsigned int use_callingpres
TRUE if we will use the calling presentation setting from the Asterisk channel for outgoing calls.
Definition: sig_ss7.h:220
struct isup_call * ss7call
Opaque libss7 call control structure.
Definition: sig_ss7.h:195
unsigned int remotelyblocked
Bitmask for the channel being remotely blocked.
Definition: sig_ss7.h:235
unsigned int hidecallerid
TRUE if the outgoing caller ID is blocked/hidden.
Definition: sig_ss7.h:213
struct ast_channel * owner
Definition: sig_ss7.h:192
char context[AST_MAX_CONTEXT]
Definition: sig_ss7.h:237
unsigned int inalarm
TRUE if channel is associated with a link that is down.
Definition: sig_ss7.h:288
unsigned int inservice
TRUE if channel is in service.
Definition: sig_ss7.h:290
int channel
Definition: sig_ss7.h:200
int stripmsd
Number of most significant digits/characters to strip from the dialed number.
Definition: sig_ss7.h:209
unsigned int use_callerid
TRUE if caller ID is used on this channel.
Definition: sig_ss7.h:215
char mohinterpret[MAX_MUSICCLASS]
Definition: sig_ss7.h:238
int fds[SIG_SS7_NUM_DCHANS]
Definition: sig_ss7.h:323
pthread_t master
Definition: sig_ss7.h:319
struct ss7 * ss7
Definition: sig_ss7.h:321
ast_mutex_t lock
Definition: sig_ss7.h:320
struct sig_ss7_chan * pvts[SIG_SS7_MAX_CHANNELS]
Definition: sig_ss7.h:322
struct sla_ringing_trunk * next
Definition: app_sla.c:308
Definition: ast_expr2.c:325
int value
Definition: syslog.c:37
TTY/TDD Generation support.
#define TDD_BYTES_PER_CHAR
Definition: tdd.h:27
int tdd_generate(struct tdd_state *tdd, unsigned char *buf, const char *string)
Definition: tdd.c:296
struct tdd_state * tdd_new(void)
Definition: tdd.c:103
void tdd_free(struct tdd_state *tdd)
Definition: tdd.c:218
int ast_tdd_gen_ecdisa(unsigned char *outbuf, int len)
Definition: tdd.c:148
int tdd_feed(struct tdd_state *tdd, unsigned char *ubuf, int samples)
Definition: tdd.c:161
Handy terminal functions for vt* terms.
#define COLOR_MAGENTA
Definition: term.h:60
#define COLOR_BLACK
Definition: term.h:50
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
#define COLOR_GREEN
Definition: term.h:54
const char * args
static struct test_options options
static struct test_val b
static struct test_val a
static struct test_val c
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:2281
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
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:235
General Asterisk channel transcoding definitions.
#define IS_DIGITAL(cap)
Definition: transcap.h:45
#define AST_TRANS_CAP_DIGITAL
Definition: transcap.h:36
u-Law to Signed linear conversion
#define AST_MULAW(a)
Definition: ulaw.h:85
#define AST_LIN2MU(a)
Definition: ulaw.h:49
FILE * out
Definition: utils/frame.c:33
Utility functions.
#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
#define ast_assert(a)
Definition: utils.h:739
#define ast_pthread_create(a, b, c, d)
Definition: utils.h:584
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:592
#define ast_clear_flag(p, flag)
Definition: utils.h:77
long int ast_random(void)
Definition: utils.c:2312
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:588
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define ARRAY_LEN(a)
Definition: utils.h:666