]> git.ipfire.org Git - thirdparty/asterisk.git/blob - channels/chan_dahdi.c
chan_dahdi: Allow MWI to be manually toggled on channels.
[thirdparty/asterisk.git] / channels / chan_dahdi.c
1 /*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 1999 - 2008, Digium, Inc.
5 *
6 * Mark Spencer <markster@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19 /*! \file
20 *
21 * \brief DAHDI for Pseudo TDM
22 *
23 * \author Mark Spencer <markster@digium.com>
24 *
25 * Connects to the DAHDI telephony library as well as
26 * libpri. Libpri is optional and needed only if you are
27 * going to use ISDN connections.
28 *
29 * You need to install libraries before you attempt to compile
30 * and install the DAHDI channel.
31 *
32 * \ingroup channel_drivers
33 *
34 * \todo Deprecate the "musiconhold" configuration option post 1.4
35 */
36
37 /*! \li \ref chan_dahdi.c uses the configuration file \ref chan_dahdi.conf
38 * \addtogroup configuration_file
39 */
40
41 /*! \page chan_dahdi.conf chan_dahdi.conf
42 * \verbinclude chan_dahdi.conf.sample
43 */
44
45 /*** MODULEINFO
46 <depend>dahdi</depend>
47 <depend>tonezone</depend>
48 <use type="module">res_smdi</use>
49 <use type="external">pri</use>
50 <use type="external">ss7</use>
51 <use type="external">openr2</use>
52 <support_level>core</support_level>
53 ***/
54
55 #include "asterisk.h"
56
57 #if defined(__NetBSD__) || defined(__FreeBSD__)
58 #include <pthread.h>
59 #else
60 #include <sys/sysmacros.h>
61 #endif
62 #include <signal.h>
63 #include <sys/stat.h>
64 #include <math.h>
65
66 #include "sig_analog.h"
67 /* Analog signaling is currently still present in chan_dahdi for use with
68 * radio. Sig_analog does not currently handle any radio operations. If
69 * radio only uses analog signaling, then the radio handling logic could
70 * be placed in sig_analog and the duplicated code could be removed.
71 */
72
73 #if defined(HAVE_PRI)
74 #include "sig_pri.h"
75 #ifndef PRI_RESTART
76 #error "Upgrade your libpri"
77 #endif
78 #endif /* defined(HAVE_PRI) */
79
80 #if defined(HAVE_SS7)
81 #include "sig_ss7.h"
82 #if !defined(LIBSS7_ABI_COMPATIBILITY)
83 #error "Upgrade your libss7"
84 #elif LIBSS7_ABI_COMPATIBILITY != 2
85 #error "Your installed libss7 is not compatible"
86 #endif
87 #endif /* defined(HAVE_SS7) */
88
89 #if defined(HAVE_OPENR2)
90 /* put this here until sig_mfcr2 comes along */
91 #define SIG_MFCR2_MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
92 #endif /* defined(HAVE_OPENR2) */
93
94 #include "asterisk/lock.h"
95 #include "asterisk/channel.h"
96 #include "asterisk/config.h"
97 #include "asterisk/module.h"
98 #include "asterisk/pbx.h"
99 #include "asterisk/file.h"
100 #include "asterisk/ulaw.h"
101 #include "asterisk/alaw.h"
102 #include "asterisk/callerid.h"
103 #include "asterisk/adsi.h"
104 #include "asterisk/cli.h"
105 #include "asterisk/pickup.h"
106 #include "asterisk/features.h"
107 #include "asterisk/musiconhold.h"
108 #include "asterisk/say.h"
109 #include "asterisk/tdd.h"
110 #include "asterisk/mwi.h"
111 #include "asterisk/dsp.h"
112 #include "asterisk/astdb.h"
113 #include "asterisk/manager.h"
114 #include "asterisk/causes.h"
115 #include "asterisk/term.h"
116 #include "asterisk/utils.h"
117 #include "asterisk/transcap.h"
118 #include "asterisk/stringfields.h"
119 #include "asterisk/abstract_jb.h"
120 #include "asterisk/smdi.h"
121 #include "asterisk/devicestate.h"
122 #include "asterisk/paths.h"
123 #include "asterisk/ccss.h"
124 #include "asterisk/features_config.h"
125 #include "asterisk/bridge.h"
126 #include "asterisk/stasis_channels.h"
127 #include "asterisk/parking.h"
128 #include "asterisk/format_cache.h"
129 #include "chan_dahdi.h"
130 #include "dahdi/bridge_native_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 </enumlist>
280 </info>
281 <info name="Dial_Resource" language="en_US" tech="DAHDI">
282 <para>DAHDI allows several modifiers to be specified as part of the resource.</para>
283 <para>The general syntax is :</para>
284 <para><literal>Dial(DAHDI/pseudo[/extension])</literal></para>
285 <para><literal>Dial(DAHDI/&lt;channel#&gt;[c|r&lt;cadence#&gt;|d][/extension])</literal></para>
286 <para><literal>Dial(DAHDI/(g|G|r|R)&lt;group#(0-63)&gt;[c|r&lt;cadence#&gt;|d][/extension])</literal></para>
287 <para>The following modifiers may be used before the channel number:</para>
288 <enumlist>
289 <enum name="g">
290 <para>Search forward, dialing on first available channel in group (lowest to highest).</para>
291 </enum>
292 <enum name="G">
293 <para>Search backward, dialing on first available channel in group (highest to lowest).</para>
294 </enum>
295 <enum name="r">
296 <para>Round robin search forward, picking up from where last left off (lowest to highest).</para>
297 </enum>
298 <enum name="R">
299 <para>Round robin search backward, picking up from where last left off (highest to lowest).</para>
300 </enum>
301 </enumlist>
302 <para>The following modifiers may be used after the channel number:</para>
303 <enumlist>
304 <enum name="c">
305 <para>Wait for DTMF digit <literal>#</literal> before providing answer supervision.</para>
306 <para>This can be useful on outbound calls via FXO ports, as otherwise
307 they would indicate answer immediately.</para>
308 </enum>
309 <enum name="d">
310 <para>Force bearer capability for ISDN/SS7 call to digital.</para>
311 </enum>
312 <enum name="i">
313 <para>ISDN span channel restriction.</para>
314 <para>Used by CC to ensure that the CC recall goes out the same span.
315 Also to make ISDN channel names dialable when the sequence number
316 is stripped off. (Used by DTMF attended transfer feature.)</para>
317 </enum>
318 <enum name="r">
319 <para>Specifies the distinctive ring cadence number to use immediately after
320 specifying this option. There are 4 default built-in cadences, and up to 24
321 total cadences may be configured.</para>
322 </enum>
323 </enumlist>
324 <example title="Dial 555-1212 on first available channel in group 1, searching from highest to lowest">
325 same => n,Dial(DAHDI/g1/5551212)
326 </example>
327 <example title="Ringing FXS channel 4 with ring cadence 2">
328 same => n,Dial(DAHDI/4r2)
329 </example>
330 <example title="Dial 555-1212 on channel 3 and require answer confirmation">
331 same => n,Dial(DAHDI/3c/5551212)
332 </example>
333 </info>
334 <manager name="DAHDITransfer" language="en_US">
335 <synopsis>
336 Transfer DAHDI Channel.
337 </synopsis>
338 <syntax>
339 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
340 <parameter name="DAHDIChannel" required="true">
341 <para>DAHDI channel number to transfer.</para>
342 </parameter>
343 </syntax>
344 <description>
345 <para>Simulate a flash hook event by the user connected to the channel.</para>
346 <note><para>Valid only for analog channels.</para></note>
347 </description>
348 </manager>
349 <manager name="DAHDIHangup" language="en_US">
350 <synopsis>
351 Hangup 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 hangup.</para>
357 </parameter>
358 </syntax>
359 <description>
360 <para>Simulate an on-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="DAHDIDialOffhook" language="en_US">
365 <synopsis>
366 Dial over DAHDI channel while offhook.
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 dial digits.</para>
372 </parameter>
373 <parameter name="Number" required="true">
374 <para>Digits to dial.</para>
375 </parameter>
376 </syntax>
377 <description>
378 <para>Generate DTMF control frames to the bridged peer.</para>
379 </description>
380 </manager>
381 <manager name="DAHDIDNDon" language="en_US">
382 <synopsis>
383 Toggle DAHDI channel Do Not Disturb status ON.
384 </synopsis>
385 <syntax>
386 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
387 <parameter name="DAHDIChannel" required="true">
388 <para>DAHDI channel number to set DND on.</para>
389 </parameter>
390 </syntax>
391 <description>
392 <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> on".</para>
393 <note><para>Feature only supported by analog channels.</para></note>
394 </description>
395 </manager>
396 <manager name="DAHDIDNDoff" language="en_US">
397 <synopsis>
398 Toggle DAHDI channel Do Not Disturb status OFF.
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 off.</para>
404 </parameter>
405 </syntax>
406 <description>
407 <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> off".</para>
408 <note><para>Feature only supported by analog channels.</para></note>
409 </description>
410 </manager>
411 <manager name="DAHDIShowChannels" language="en_US">
412 <synopsis>
413 Show status of DAHDI channels.
414 </synopsis>
415 <syntax>
416 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
417 <parameter name="DAHDIChannel">
418 <para>Specify the specific channel number to show. Show all channels if zero or not present.</para>
419 </parameter>
420 </syntax>
421 <description>
422 <para>Similar to the CLI command "dahdi show channels".</para>
423 </description>
424 </manager>
425 <manager name="DAHDIRestart" language="en_US">
426 <synopsis>
427 Fully Restart DAHDI channels (terminates calls).
428 </synopsis>
429 <syntax>
430 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
431 </syntax>
432 <description>
433 <para>Equivalent to the CLI command "dahdi restart".</para>
434 </description>
435 </manager>
436 <manager name="PRIShowSpans" language="en_US">
437 <synopsis>
438 Show status of PRI spans.
439 </synopsis>
440 <syntax>
441 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
442 <parameter name="Span">
443 <para>Specify the specific span to show. Show all spans if zero or not present.</para>
444 </parameter>
445 </syntax>
446 <description>
447 <para>Similar to the CLI command "pri show spans".</para>
448 </description>
449 </manager>
450 <manager name="PRIDebugSet" language="en_US">
451 <synopsis>
452 Set PRI debug levels for a span
453 </synopsis>
454 <syntax>
455 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
456 <parameter name="Span" required="true">
457 <para>Which span to affect.</para>
458 </parameter>
459 <parameter name="Level" required="true">
460 <para>What debug level to set. May be a numerical value or a text value from the list below</para>
461 <enumlist>
462 <enum name="off" />
463 <enum name="on" />
464 <enum name="hex" />
465 <enum name="intense" />
466 </enumlist>
467 </parameter>
468 </syntax>
469 <description>
470 <para>Equivalent to the CLI command "pri set debug &lt;level&gt; span &lt;span&gt;".</para>
471 </description>
472 </manager>
473 <manager name="PRIDebugFileSet" language="en_US">
474 <synopsis>
475 Set the file used for PRI debug message output
476 </synopsis>
477 <syntax>
478 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
479 <parameter name="File" required="true">
480 <para>Path of file to write debug output.</para>
481 </parameter>
482 </syntax>
483 <description>
484 <para>Equivalent to the CLI command "pri set debug file &lt;output-file&gt;"</para>
485 </description>
486 </manager>
487 <manager name="PRIDebugFileUnset" language="en_US">
488 <synopsis>
489 Disables file output for PRI debug messages
490 </synopsis>
491 <syntax>
492 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
493 </syntax>
494 </manager>
495 <managerEvent language="en_US" name="AlarmClear">
496 <managerEventInstance class="EVENT_FLAG_SYSTEM">
497 <synopsis>Raised when an alarm is cleared on a DAHDI channel.</synopsis>
498 <syntax>
499 <parameter name="DAHDIChannel">
500 <para>The DAHDI channel on which the alarm was cleared.</para>
501 <note><para>This is not an Asterisk channel identifier.</para></note>
502 </parameter>
503 </syntax>
504 </managerEventInstance>
505 </managerEvent>
506 <managerEvent language="en_US" name="SpanAlarmClear">
507 <managerEventInstance class="EVENT_FLAG_SYSTEM">
508 <synopsis>Raised when an alarm is cleared on a DAHDI span.</synopsis>
509 <syntax>
510 <parameter name="Span">
511 <para>The span on which the alarm was cleared.</para>
512 </parameter>
513 </syntax>
514 </managerEventInstance>
515 </managerEvent>
516 <managerEvent language="en_US" name="DNDState">
517 <managerEventInstance class="EVENT_FLAG_SYSTEM">
518 <synopsis>Raised when the Do Not Disturb state is changed on a DAHDI channel.</synopsis>
519 <syntax>
520 <parameter name="DAHDIChannel">
521 <para>The DAHDI channel on which DND status changed.</para>
522 <note><para>This is not an Asterisk channel identifier.</para></note>
523 </parameter>
524 <parameter name="Status">
525 <enumlist>
526 <enum name="enabled"/>
527 <enum name="disabled"/>
528 </enumlist>
529 </parameter>
530 </syntax>
531 </managerEventInstance>
532 </managerEvent>
533 <managerEvent language="en_US" name="Alarm">
534 <managerEventInstance class="EVENT_FLAG_SYSTEM">
535 <synopsis>Raised when an alarm is set on a DAHDI channel.</synopsis>
536 <syntax>
537 <parameter name="DAHDIChannel">
538 <para>The channel on which the alarm occurred.</para>
539 <note><para>This is not an Asterisk channel identifier.</para></note>
540 </parameter>
541 <parameter name="Alarm">
542 <para>A textual description of the alarm that occurred.</para>
543 </parameter>
544 </syntax>
545 </managerEventInstance>
546 </managerEvent>
547 <managerEvent language="en_US" name="SpanAlarm">
548 <managerEventInstance class="EVENT_FLAG_SYSTEM">
549 <synopsis>Raised when an alarm is set on a DAHDI span.</synopsis>
550 <syntax>
551 <parameter name="Span">
552 <para>The span on which the alarm occurred.</para>
553 </parameter>
554 <parameter name="Alarm">
555 <para>A textual description of the alarm that occurred.</para>
556 </parameter>
557 </syntax>
558 </managerEventInstance>
559 </managerEvent>
560 <managerEvent language="en_US" name="DAHDIChannel">
561 <managerEventInstance class="EVENT_FLAG_CALL">
562 <synopsis>Raised when a DAHDI channel is created or an underlying technology is associated with a DAHDI channel.</synopsis>
563 <syntax>
564 <channel_snapshot/>
565 <parameter name="DAHDIGroup">
566 <para>The DAHDI logical group associated with this channel.</para>
567 </parameter>
568 <parameter name="DAHDISpan">
569 <para>The DAHDI span associated with this channel.</para>
570 </parameter>
571 <parameter name="DAHDIChannel">
572 <para>The DAHDI channel associated with this channel.</para>
573 </parameter>
574 </syntax>
575 </managerEventInstance>
576 </managerEvent>
577 ***/
578
579 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
580
581 static const char * const lbostr[] = {
582 "0 db (CSU)/0-133 feet (DSX-1)",
583 "133-266 feet (DSX-1)",
584 "266-399 feet (DSX-1)",
585 "399-533 feet (DSX-1)",
586 "533-655 feet (DSX-1)",
587 "-7.5db (CSU)",
588 "-15db (CSU)",
589 "-22.5db (CSU)"
590 };
591
592 /*! Global jitterbuffer configuration - by default, jb is disabled
593 * \note Values shown here match the defaults shown in chan_dahdi.conf.sample */
594 static struct ast_jb_conf default_jbconf =
595 {
596 .flags = 0,
597 .max_size = 200,
598 .resync_threshold = 1000,
599 .impl = "fixed",
600 .target_extra = 40,
601 };
602 static struct ast_jb_conf global_jbconf;
603
604 /*!
605 * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
606 * the user hangs up to reset the state machine so ring works properly.
607 * This is used to be able to support kewlstart by putting the zhone in
608 * groundstart mode since their forward disconnect supervision is entirely
609 * broken even though their documentation says it isn't and their support
610 * is entirely unwilling to provide any assistance with their channel banks
611 * even though their web site says they support their products for life.
612 */
613 /* #define ZHONE_HACK */
614
615 /*! \brief Typically, how many rings before we should send Caller*ID */
616 #define DEFAULT_CIDRINGS 1
617
618 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? ast_format_alaw : ast_format_ulaw)
619
620
621 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
622 #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))
623
624 static const char tdesc[] = "DAHDI Telephony"
625 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
626 " w/"
627 #if defined(HAVE_PRI)
628 "PRI"
629 #endif /* defined(HAVE_PRI) */
630 #if defined(HAVE_SS7)
631 #if defined(HAVE_PRI)
632 " & "
633 #endif /* defined(HAVE_PRI) */
634 "SS7"
635 #endif /* defined(HAVE_SS7) */
636 #if defined(HAVE_OPENR2)
637 #if defined(HAVE_PRI) || defined(HAVE_SS7)
638 " & "
639 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
640 "MFC/R2"
641 #endif /* defined(HAVE_OPENR2) */
642 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2) */
643 ;
644
645 static const char config[] = "chan_dahdi.conf";
646
647 #ifdef LOTS_OF_SPANS
648 #define NUM_SPANS DAHDI_MAX_SPANS
649 #else
650 #define NUM_SPANS 32
651 #endif
652
653 #define CHAN_PSEUDO -2
654
655 #define CALLPROGRESS_PROGRESS 1
656 #define CALLPROGRESS_FAX_OUTGOING 2
657 #define CALLPROGRESS_FAX_INCOMING 4
658 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
659
660 #define NUM_CADENCE_MAX 25
661 static int num_cadence = 4;
662 static int user_has_defined_cadences = 0;
663
664 static int has_pseudo;
665
666 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
667 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
668 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
669 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
670 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
671 };
672
673 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
674 * is 1, the second pause is 2 and so on.
675 */
676
677 static int cidrings[NUM_CADENCE_MAX] = {
678 2, /*!< Right after first long ring */
679 4, /*!< Right after long part */
680 3, /*!< After third chirp */
681 2, /*!< Second spell */
682 };
683
684 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
685 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
686
687 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
688 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
689
690 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
691 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
692
693 static char defaultcic[64] = "";
694 static char defaultozz[64] = "";
695
696 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
697 static char mwimonitornotify[PATH_MAX] = "";
698 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
699 static int mwisend_rpas = 0;
700 #endif
701
702 static char progzone[10] = "";
703
704 static int usedistinctiveringdetection = 0;
705 static int distinctiveringaftercid = 0;
706
707 static int numbufs = 4;
708
709 static int mwilevel = 512;
710 static int dtmfcid_level = 256;
711
712 #define REPORT_CHANNEL_ALARMS 1
713 #define REPORT_SPAN_ALARMS 2
714 static int report_alarms = REPORT_CHANNEL_ALARMS;
715
716 #ifdef HAVE_PRI
717 static int pridebugfd = -1;
718 static char pridebugfilename[1024] = "";
719 #endif
720
721 /*! \brief Protect the interface list (of dahdi_pvt's) */
722 AST_MUTEX_DEFINE_STATIC(iflock);
723
724
725 static int ifcount = 0;
726
727 #ifdef HAVE_PRI
728 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
729 #endif
730
731 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
732 when it's doing something critical. */
733 AST_MUTEX_DEFINE_STATIC(monlock);
734
735 /*! \brief This is the thread for the monitor which checks for input on the channels
736 which are not currently in use. */
737 static pthread_t monitor_thread = AST_PTHREADT_NULL;
738 static ast_cond_t ss_thread_complete;
739 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
740 AST_MUTEX_DEFINE_STATIC(restart_lock);
741 static int ss_thread_count = 0;
742 static int num_restart_pending = 0;
743
744 static int restart_monitor(void);
745
746 static int dahdi_sendtext(struct ast_channel *c, const char *text);
747
748 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
749 static inline int dahdi_get_event(int fd)
750 {
751 int j;
752 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
753 return -1;
754 return j;
755 }
756
757 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
758 static inline int dahdi_wait_event(int fd)
759 {
760 int i, j = 0;
761 i = DAHDI_IOMUX_SIGEVENT;
762 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
763 return -1;
764 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
765 return -1;
766 return j;
767 }
768
769 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
770 #define READ_SIZE 160
771
772 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
773 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
774
775 #define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE) /*!< 300 ms */
776 #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
777 #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE) /*!< 100 ms */
778 #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE) /*!< 500 ms */
779 #define MIN_MS_SINCE_FLASH ((2000) ) /*!< 2000 ms */
780 #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE) /*!< 8,000 ms */
781 #define DEFAULT_DIALTONE_DETECT_TIMEOUT ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
782
783 /*!
784 * \brief Configured ring timeout base.
785 * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
786 */
787 static int ringt_base = DEFAULT_RINGT;
788
789 #if defined(HAVE_SS7)
790
791 struct dahdi_ss7 {
792 struct sig_ss7_linkset ss7;
793 };
794
795 static struct dahdi_ss7 linksets[NUM_SPANS];
796
797 static int cur_ss7type = -1;
798 static int cur_slc = -1;
799 static int cur_linkset = -1;
800 static int cur_pointcode = -1;
801 static int cur_cicbeginswith = -1;
802 static int cur_adjpointcode = -1;
803 static int cur_networkindicator = -1;
804 static int cur_defaultdpc = -1;
805 #endif /* defined(HAVE_SS7) */
806
807 #ifdef HAVE_OPENR2
808 struct dahdi_mfcr2_conf {
809 openr2_variant_t variant;
810 int mfback_timeout;
811 int metering_pulse_timeout;
812 int max_ani;
813 int max_dnis;
814 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
815 int dtmf_time_on;
816 int dtmf_time_off;
817 #endif
818 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
819 int dtmf_end_timeout;
820 #endif
821 signed int get_ani_first:2;
822 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
823 signed int skip_category_request:2;
824 #endif
825 unsigned int call_files:1;
826 unsigned int allow_collect_calls:1;
827 unsigned int charge_calls:1;
828 unsigned int accept_on_offer:1;
829 unsigned int forced_release:1;
830 unsigned int double_answer:1;
831 signed int immediate_accept:2;
832 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
833 signed int dtmf_dialing:2;
834 signed int dtmf_detection:2;
835 #endif
836 char logdir[OR2_MAX_PATH];
837 char r2proto_file[OR2_MAX_PATH];
838 openr2_log_level_t loglevel;
839 openr2_calling_party_category_t category;
840 };
841
842 /* MFC-R2 pseudo-link structure */
843 struct dahdi_mfcr2 {
844 int index; /*!< Unique index for CLI */
845 pthread_t r2master; /*!< Thread of master */
846 openr2_context_t *protocol_context; /*!< OpenR2 context handle */
847 struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS]; /*!< Member channel pvt structs */
848 int numchans; /*!< Number of channels in this R2 block */
849 int live_chans; /*!< Number of unremoved channels in this R2 block */
850 int nodev; /*!< Link disconnected? */
851 struct dahdi_mfcr2_conf conf; /*!< Configuration used to setup this pseudo-link */
852 };
853
854 struct r2link_entry {
855 struct dahdi_mfcr2 mfcr2;
856 AST_LIST_ENTRY(r2link_entry) list;
857 };
858 static AST_LIST_HEAD_STATIC(r2links, r2link_entry);
859 static struct r2links nodev_r2links = AST_LIST_HEAD_INIT_VALUE;
860
861
862 /* how many r2links have been malloc'd */
863 static int r2links_count = 0;
864
865 #endif /* HAVE_OPENR2 */
866
867 #ifdef HAVE_PRI
868
869 struct dahdi_pri {
870 int dchannels[SIG_PRI_NUM_DCHANS]; /*!< What channel are the dchannels on */
871 int mastertrunkgroup; /*!< What trunk group is our master */
872 int prilogicalspan; /*!< Logical span number within trunk group */
873 struct sig_pri_span pri;
874 };
875
876 static struct dahdi_pri pris[NUM_SPANS];
877
878 #if defined(HAVE_PRI_CCSS)
879 /*! DAHDI PRI CCSS agent and monitor type name. */
880 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
881 #endif /* defined(HAVE_PRI_CCSS) */
882
883 #else
884 /*! Shut up the compiler */
885 struct dahdi_pri;
886 #endif
887
888 /* Polarity states */
889 #define POLARITY_IDLE 0
890 #define POLARITY_REV 1
891
892 const char * const subnames[] = {
893 "Real",
894 "Callwait",
895 "Threeway"
896 };
897
898 static struct dahdi_pvt *iflist = NULL; /*!< Main interface list start */
899 static struct dahdi_pvt *ifend = NULL; /*!< Main interface list end */
900
901 #if defined(HAVE_PRI)
902 struct doomed_pri {
903 struct sig_pri_span *pri;
904 AST_LIST_ENTRY(doomed_pri) list;
905 };
906 static AST_LIST_HEAD_STATIC(doomed_pris, doomed_pri);
907
908 static void pri_destroy_span(struct sig_pri_span *pri);
909
910 static struct dahdi_parms_pseudo {
911 int buf_no; /*!< Number of buffers */
912 int buf_policy; /*!< Buffer policy */
913 int faxbuf_no; /*!< Number of Fax buffers */
914 int faxbuf_policy; /*!< Fax buffer policy */
915 } dahdi_pseudo_parms;
916 #endif /* defined(HAVE_PRI) */
917
918 /*! \brief Channel configuration from chan_dahdi.conf .
919 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
920 * Generally there is a field here for every possible configuration item.
921 *
922 * The state of fields is saved along the parsing and whenever a 'channel'
923 * statement is reached, the current dahdi_chan_conf is used to configure the
924 * channel (struct dahdi_pvt)
925 *
926 * \see dahdi_chan_init for the default values.
927 */
928 struct dahdi_chan_conf {
929 struct dahdi_pvt chan;
930 #ifdef HAVE_PRI
931 struct dahdi_pri pri;
932 #endif
933
934 #if defined(HAVE_SS7)
935 struct dahdi_ss7 ss7;
936 #endif /* defined(HAVE_SS7) */
937
938 #ifdef HAVE_OPENR2
939 struct dahdi_mfcr2_conf mfcr2;
940 #endif
941 struct dahdi_params timing;
942 int is_sig_auto; /*!< Use channel signalling from DAHDI? */
943 /*! Continue configuration even if a channel is not there. */
944 int ignore_failed_channels;
945
946 /*!
947 * \brief The serial port to listen for SMDI data on
948 * \note Set from the "smdiport" string read in from chan_dahdi.conf
949 */
950 char smdi_port[SMDI_MAX_FILENAME_LEN];
951
952 /*!
953 * \brief Don't create channels below this number
954 * \note by default is 0 (no limit)
955 */
956 int wanted_channels_start;
957
958 /*!
959 * \brief Don't create channels above this number (infinity by default)
960 * \note by default is 0 (special value that means "no limit").
961 */
962 int wanted_channels_end;
963 };
964
965 /*! returns a new dahdi_chan_conf with default values (by-value) */
966 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
967 {
968 /* recall that if a field is not included here it is initialized
969 * to 0 or equivalent
970 */
971 struct dahdi_chan_conf conf = {
972 #ifdef HAVE_PRI
973 .pri.pri = {
974 .nsf = PRI_NSF_NONE,
975 .switchtype = PRI_SWITCH_NI2,
976 .dialplan = PRI_UNKNOWN + 1,
977 .localdialplan = PRI_NATIONAL_ISDN + 1,
978 .nodetype = PRI_CPE,
979 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
980
981 #if defined(HAVE_PRI_CCSS)
982 .cc_ptmp_recall_mode = 1,/* specificRecall */
983 .cc_qsig_signaling_link_req = 1,/* retain */
984 .cc_qsig_signaling_link_rsp = 1,/* retain */
985 #endif /* defined(HAVE_PRI_CCSS) */
986
987 .minunused = 2,
988 .idleext = "",
989 .idledial = "",
990 .internationalprefix = "",
991 .nationalprefix = "",
992 .localprefix = "",
993 .privateprefix = "",
994 .unknownprefix = "",
995 .colp_send = SIG_PRI_COLP_UPDATE,
996 .resetinterval = -1,
997 },
998 #endif
999 #if defined(HAVE_SS7)
1000 .ss7.ss7 = {
1001 .called_nai = SS7_NAI_NATIONAL,
1002 .calling_nai = SS7_NAI_NATIONAL,
1003 .internationalprefix = "",
1004 .nationalprefix = "",
1005 .subscriberprefix = "",
1006 .unknownprefix = "",
1007 .networkroutedprefix = ""
1008 },
1009 #endif /* defined(HAVE_SS7) */
1010 #ifdef HAVE_OPENR2
1011 .mfcr2 = {
1012 .variant = OR2_VAR_ITU,
1013 .mfback_timeout = -1,
1014 .metering_pulse_timeout = -1,
1015 .max_ani = 10,
1016 .max_dnis = 4,
1017 .get_ani_first = -1,
1018 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
1019 .skip_category_request = -1,
1020 #endif
1021 .call_files = 0,
1022 .allow_collect_calls = 0,
1023 .charge_calls = 1,
1024 .accept_on_offer = 1,
1025 .forced_release = 0,
1026 .double_answer = 0,
1027 .immediate_accept = -1,
1028 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
1029 .dtmf_dialing = -1,
1030 .dtmf_detection = -1,
1031 .dtmf_time_on = OR2_DEFAULT_DTMF_ON,
1032 .dtmf_time_off = OR2_DEFAULT_DTMF_OFF,
1033 #endif
1034 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
1035 .dtmf_end_timeout = -1,
1036 #endif
1037 .logdir = "",
1038 .r2proto_file = "",
1039 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
1040 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
1041 },
1042 #endif
1043 .chan = {
1044 .context = "default",
1045 .immediatering = 1,
1046 .cid_num = "",
1047 .cid_name = "",
1048 .cid_tag = "",
1049 .mohinterpret = "default",
1050 .mohsuggest = "",
1051 .parkinglot = "",
1052 .transfertobusy = 1,
1053 .dialmode = 0,
1054
1055 .ani_info_digits = 2,
1056 .ani_wink_time = 1000,
1057 .ani_timeout = 10000,
1058
1059 .cid_signalling = CID_SIG_BELL,
1060 .cid_start = CID_START_RING,
1061 .dahditrcallerid = 0,
1062 .use_callerid = 1,
1063 .sig = -1,
1064 .outsigmod = -1,
1065
1066 .cid_rxgain = +5.0,
1067
1068 .tonezone = -1,
1069
1070 .echocancel.head.tap_length = 1,
1071
1072 .busycount = 3,
1073
1074 .accountcode = "",
1075
1076 .mailbox = "",
1077
1078 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
1079 .mwisend_fsk = 1,
1080 #endif
1081 .polarityonanswerdelay = 600,
1082
1083 .sendcalleridafter = DEFAULT_CIDRINGS,
1084
1085 .buf_policy = DAHDI_POLICY_IMMEDIATE,
1086 .buf_no = numbufs,
1087 .usefaxbuffers = 0,
1088 .cc_params = ast_cc_config_params_init(),
1089 .firstdigit_timeout = ANALOG_FIRST_DIGIT_TIMEOUT,
1090 .interdigit_timeout = ANALOG_INTER_DIGIT_TIMEOUT,
1091 .matchdigit_timeout = ANALOG_MATCH_DIGIT_TIMEOUT,
1092 },
1093 .timing = {
1094 .prewinktime = -1,
1095 .preflashtime = -1,
1096 .winktime = -1,
1097 .flashtime = -1,
1098 .starttime = -1,
1099 .rxwinktime = -1,
1100 .rxflashtime = -1,
1101 .debouncetime = -1
1102 },
1103 .is_sig_auto = 1,
1104 .ignore_failed_channels = 1,
1105 .smdi_port = "/dev/ttyS0",
1106 };
1107
1108 return conf;
1109 }
1110
1111
1112 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap,
1113 const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor,
1114 const char *data, int *cause);
1115 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
1116 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
1117 static int dahdi_sendtext(struct ast_channel *c, const char *text);
1118 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout);
1119 static int dahdi_hangup(struct ast_channel *ast);
1120 static int dahdi_answer(struct ast_channel *ast);
1121 static struct ast_frame *dahdi_read(struct ast_channel *ast);
1122 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
1123 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
1124 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
1125 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
1126 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
1127 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
1128 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
1129 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
1130 static int dahdi_devicestate(const char *data);
1131 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
1132
1133 static struct ast_channel_tech dahdi_tech = {
1134 .type = "DAHDI",
1135 .description = tdesc,
1136 .requester = dahdi_request,
1137 .send_digit_begin = dahdi_digit_begin,
1138 .send_digit_end = dahdi_digit_end,
1139 .send_text = dahdi_sendtext,
1140 .call = dahdi_call,
1141 .hangup = dahdi_hangup,
1142 .answer = dahdi_answer,
1143 .read = dahdi_read,
1144 .write = dahdi_write,
1145 .exception = dahdi_exception,
1146 .indicate = dahdi_indicate,
1147 .fixup = dahdi_fixup,
1148 .setoption = dahdi_setoption,
1149 .queryoption = dahdi_queryoption,
1150 .func_channel_read = dahdi_func_read,
1151 .func_channel_write = dahdi_func_write,
1152 .devicestate = dahdi_devicestate,
1153 .cc_callback = dahdi_cc_callback,
1154 };
1155
1156 #define GET_CHANNEL(p) ((p)->channel)
1157
1158 static enum analog_sigtype dahdisig_to_analogsig(int sig)
1159 {
1160 switch (sig) {
1161 case SIG_FXOLS:
1162 return ANALOG_SIG_FXOLS;
1163 case SIG_FXOGS:
1164 return ANALOG_SIG_FXOGS;
1165 case SIG_FXOKS:
1166 return ANALOG_SIG_FXOKS;
1167 case SIG_FXSLS:
1168 return ANALOG_SIG_FXSLS;
1169 case SIG_FXSGS:
1170 return ANALOG_SIG_FXSGS;
1171 case SIG_FXSKS:
1172 return ANALOG_SIG_FXSKS;
1173 case SIG_EMWINK:
1174 return ANALOG_SIG_EMWINK;
1175 case SIG_EM:
1176 return ANALOG_SIG_EM;
1177 case SIG_EM_E1:
1178 return ANALOG_SIG_EM_E1;
1179 case SIG_FEATD:
1180 return ANALOG_SIG_FEATD;
1181 case SIG_FEATDMF:
1182 return ANALOG_SIG_FEATDMF;
1183 case SIG_E911:
1184 return SIG_E911;
1185 case SIG_FGC_CAMA:
1186 return ANALOG_SIG_FGC_CAMA;
1187 case SIG_FGC_CAMAMF:
1188 return ANALOG_SIG_FGC_CAMAMF;
1189 case SIG_FEATB:
1190 return ANALOG_SIG_FEATB;
1191 case SIG_SFWINK:
1192 return ANALOG_SIG_SFWINK;
1193 case SIG_SF:
1194 return ANALOG_SIG_SF;
1195 case SIG_SF_FEATD:
1196 return ANALOG_SIG_SF_FEATD;
1197 case SIG_SF_FEATDMF:
1198 return ANALOG_SIG_SF_FEATDMF;
1199 case SIG_FEATDMF_TA:
1200 return ANALOG_SIG_FEATDMF_TA;
1201 case SIG_SF_FEATB:
1202 return ANALOG_SIG_FEATB;
1203 default:
1204 return -1;
1205 }
1206 }
1207
1208
1209 static int analog_tone_to_dahditone(enum analog_tone tone)
1210 {
1211 switch (tone) {
1212 case ANALOG_TONE_RINGTONE:
1213 return DAHDI_TONE_RINGTONE;
1214 case ANALOG_TONE_STUTTER:
1215 return DAHDI_TONE_STUTTER;
1216 case ANALOG_TONE_CONGESTION:
1217 return DAHDI_TONE_CONGESTION;
1218 case ANALOG_TONE_DIALTONE:
1219 return DAHDI_TONE_DIALTONE;
1220 case ANALOG_TONE_DIALRECALL:
1221 return DAHDI_TONE_DIALRECALL;
1222 case ANALOG_TONE_INFO:
1223 return DAHDI_TONE_INFO;
1224 default:
1225 return -1;
1226 }
1227 }
1228
1229 static int analogsub_to_dahdisub(enum analog_sub analogsub)
1230 {
1231 int index;
1232
1233 switch (analogsub) {
1234 case ANALOG_SUB_REAL:
1235 index = SUB_REAL;
1236 break;
1237 case ANALOG_SUB_CALLWAIT:
1238 index = SUB_CALLWAIT;
1239 break;
1240 case ANALOG_SUB_THREEWAY:
1241 index = SUB_THREEWAY;
1242 break;
1243 default:
1244 ast_log(LOG_ERROR, "Unidentified sub!\n");
1245 index = SUB_REAL;
1246 }
1247
1248 return index;
1249 }
1250
1251 /*!
1252 * \internal
1253 * \brief release all members on the doomed pris list
1254 * \since 13.0
1255 *
1256 * Called priodically by the monitor threads to release spans marked for
1257 * removal.
1258 */
1259 static void release_doomed_pris(void)
1260 {
1261 #ifdef HAVE_PRI
1262 struct doomed_pri *entry;
1263
1264 AST_LIST_LOCK(&doomed_pris);
1265 while ((entry = AST_LIST_REMOVE_HEAD(&doomed_pris, list))) {
1266 /* The span destruction must be done with this lock not held */
1267 AST_LIST_UNLOCK(&doomed_pris);
1268 ast_debug(4, "Destroying span %d from doomed queue.\n",
1269 entry->pri->span);
1270 pri_destroy_span(entry->pri);
1271 ast_free(entry);
1272 AST_LIST_LOCK(&doomed_pris);
1273 }
1274 AST_LIST_UNLOCK(&doomed_pris);
1275 #endif
1276 }
1277
1278 #ifdef HAVE_PRI
1279 /*!
1280 * \brief Queue a span for destruction
1281 * \since 13.0
1282 *
1283 * \param pri the span to destroy
1284 *
1285 * Add a span to the list of spans to be destroyed later on
1286 * by the monitor thread. Allows destroying a span while holding its
1287 * lock.
1288 */
1289 static void pri_queue_for_destruction(struct sig_pri_span *pri)
1290 {
1291 struct doomed_pri *entry;
1292
1293 AST_LIST_LOCK(&doomed_pris);
1294 AST_LIST_TRAVERSE(&doomed_pris, entry, list) {
1295 if (entry->pri == pri) {
1296 AST_LIST_UNLOCK(&doomed_pris);
1297 return;
1298 }
1299 }
1300 entry = ast_calloc(sizeof(struct doomed_pri), 1);
1301 if (!entry) {
1302 /* Nothing useful to do here. Panic? */
1303 ast_log(LOG_WARNING, "Failed allocating memory for a doomed_pri.\n");
1304 AST_LIST_UNLOCK(&doomed_pris);
1305 return;
1306 }
1307 entry->pri = pri;
1308 ast_debug(4, "Queue span %d for destruction.\n", pri->span);
1309 AST_LIST_INSERT_TAIL(&doomed_pris, entry, list);
1310 AST_LIST_UNLOCK(&doomed_pris);
1311 }
1312 #endif
1313
1314 /*!
1315 * \internal
1316 * \brief Send a dial string to DAHDI.
1317 * \since 12.0.0
1318 *
1319 * \param pvt DAHDI private pointer
1320 * \param operation DAHDI dial operation to do to string
1321 * \param dial_str Dial string to send
1322 *
1323 * \retval 0 on success.
1324 * \retval non-zero on error.
1325 */
1326 static int dahdi_dial_str(struct dahdi_pvt *pvt, int operation, const char *dial_str)
1327 {
1328 int res;
1329 int offset;
1330 const char *pos;
1331 struct dahdi_dialoperation zo = {
1332 .op = operation,
1333 };
1334
1335 /* Convert the W's to ww. */
1336 pos = dial_str;
1337 for (offset = 0; offset < sizeof(zo.dialstr) - 1; ++offset) {
1338 if (!*pos) {
1339 break;
1340 }
1341 if (*pos == 'W') {
1342 /* Convert 'W' to "ww" */
1343 ++pos;
1344 if (offset >= sizeof(zo.dialstr) - 3) {
1345 /* No room to expand */
1346 break;
1347 }
1348 zo.dialstr[offset] = 'w';
1349 ++offset;
1350 zo.dialstr[offset] = 'w';
1351 continue;
1352 }
1353 zo.dialstr[offset] = *pos++;
1354 }
1355 /* The zo initialization has already terminated the dialstr. */
1356
1357 ast_debug(1, "Channel %d: Dial str '%s' expanded to '%s' sent to DAHDI_DIAL.\n",
1358 pvt->channel, dial_str, zo.dialstr);
1359 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
1360 if (res) {
1361 ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
1362 pvt->channel, dial_str, strerror(errno));
1363 }
1364
1365 return res;
1366 }
1367
1368 static enum analog_event dahdievent_to_analogevent(int event);
1369 static int bump_gains(struct dahdi_pvt *p);
1370 static int dahdi_setlinear(int dfd, int linear);
1371
1372 static int my_start_cid_detect(void *pvt, int cid_signalling)
1373 {
1374 struct dahdi_pvt *p = pvt;
1375 int index = SUB_REAL;
1376 p->cs = callerid_new(cid_signalling);
1377 if (!p->cs) {
1378 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
1379 return -1;
1380 }
1381 bump_gains(p);
1382 dahdi_setlinear(p->subs[index].dfd, 0);
1383
1384 return 0;
1385 }
1386
1387 static int restore_gains(struct dahdi_pvt *p);
1388
1389 static int my_stop_cid_detect(void *pvt)
1390 {
1391 struct dahdi_pvt *p = pvt;
1392 int index = SUB_REAL;
1393
1394 if (p->cs) {
1395 callerid_free(p->cs);
1396 }
1397
1398 /* Restore linear mode after Caller*ID processing */
1399 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
1400 restore_gains(p);
1401
1402 return 0;
1403 }
1404
1405 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
1406 {
1407 struct dahdi_pvt *p = pvt;
1408 struct analog_pvt *analog_p = p->sig_pvt;
1409 struct pollfd poller;
1410 char *name, *num;
1411 int index = SUB_REAL;
1412 int res;
1413 unsigned char buf[256];
1414 int flags;
1415
1416 poller.fd = p->subs[SUB_REAL].dfd;
1417 poller.events = POLLPRI | POLLIN;
1418 poller.revents = 0;
1419
1420 res = poll(&poller, 1, timeout);
1421
1422 if (poller.revents & POLLPRI) {
1423 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
1424 return 1;
1425 }
1426
1427 if (poller.revents & POLLIN) {
1428 /*** NOTES ***/
1429 /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
1430 * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
1431 * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
1432 * a failure and die, and returning 2 means no event was received. */
1433 res = read(p->subs[index].dfd, buf, sizeof(buf));
1434 if (res < 0) {
1435 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
1436 return -1;
1437 }
1438
1439 if (analog_p->ringt > 0) {
1440 if (!(--analog_p->ringt)) {
1441 /* only return if we timeout from a ring event */
1442 return -1;
1443 }
1444 }
1445
1446 if (p->cid_signalling == CID_SIG_V23_JP) {
1447 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
1448 } else {
1449 res = callerid_feed(p->cs, buf, res, AST_LAW(p));
1450 }
1451 if (res < 0) {
1452 /*
1453 * The previous diagnostic message output likely
1454 * explains why it failed.
1455 */
1456 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
1457 return -1;
1458 }
1459
1460 if (res == 1) {
1461 callerid_get(p->cs, &name, &num, &flags);
1462 if (name)
1463 ast_copy_string(namebuf, name, ANALOG_MAX_CID);
1464 if (num)
1465 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
1466
1467 if (flags & (CID_PRIVATE_NUMBER | CID_UNKNOWN_NUMBER)) {
1468 /* If we got a presentation, we must set it on the channel */
1469 struct ast_channel *chan = analog_p->ss_astchan;
1470 struct ast_party_caller caller;
1471
1472 ast_party_caller_set_init(&caller, ast_channel_caller(chan));
1473 caller.id.name.presentation = caller.id.number.presentation = (flags & CID_PRIVATE_NUMBER) ?
1474 AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED : AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_UNSCREENED;
1475 ast_party_caller_set(ast_channel_caller(chan), &caller, NULL);
1476 ast_party_caller_free(&caller);
1477 }
1478
1479 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
1480 return 0;
1481 }
1482 }
1483
1484 *ev = ANALOG_EVENT_NONE;
1485 return 2;
1486 }
1487
1488 static const char *event2str(int event);
1489
1490 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
1491 {
1492 unsigned char buf[256];
1493 int distMatches;
1494 int curRingData[RING_PATTERNS];
1495 int receivedRingT;
1496 int counter1;
1497 int counter;
1498 int i;
1499 int res;
1500 int checkaftercid = 0;
1501 const char *matched_context;
1502 struct dahdi_pvt *p = pvt;
1503 struct analog_pvt *analog_p = p->sig_pvt;
1504
1505 if (ringdata == NULL) {
1506 ringdata = curRingData;
1507 } else {
1508 checkaftercid = 1;
1509 }
1510
1511 /* We must have a ring by now so lets try to listen for distinctive ringing */
1512 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
1513 /* Clear the current ring data array so we don't have old data in it. */
1514 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
1515 ringdata[receivedRingT] = 0;
1516 receivedRingT = 0;
1517
1518 if (checkaftercid && distinctiveringaftercid) {
1519 ast_verb(3, "Detecting post-CID distinctive ring\n");
1520 }
1521
1522 for (;;) {
1523 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
1524 res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i);
1525 if (res) {
1526 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
1527 ast_hangup(chan);
1528 return 1;
1529 }
1530 if (i & DAHDI_IOMUX_SIGEVENT) {
1531 res = dahdi_get_event(p->subs[idx].dfd);
1532 ast_debug(3, "Got event %d (%s)...\n", res, event2str(res));
1533 if (res == DAHDI_EVENT_NOALARM) {
1534 p->inalarm = 0;
1535 analog_p->inalarm = 0;
1536 } else if (res == DAHDI_EVENT_RINGOFFHOOK) {
1537 /* Let us detect distinctive ring */
1538 ringdata[receivedRingT] = analog_p->ringt;
1539
1540 if (analog_p->ringt < analog_p->ringt_base / 2) {
1541 break;
1542 }
1543 /* Increment the ringT counter so we can match it against
1544 values in chan_dahdi.conf for distinctive ring */
1545 if (++receivedRingT == RING_PATTERNS) {
1546 break;
1547 }
1548 }
1549 } else if (i & DAHDI_IOMUX_READ) {
1550 res = read(p->subs[idx].dfd, buf, sizeof(buf));
1551 if (res < 0) {
1552 if (errno != ELAST) {
1553 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
1554 ast_hangup(chan);
1555 return 1;
1556 }
1557 break;
1558 }
1559 if (analog_p->ringt > 0) {
1560 if (!(--analog_p->ringt)) {
1561 break;
1562 }
1563 }
1564 }
1565 }
1566 }
1567
1568 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
1569 ast_verb(3, "Detected ring pattern: %d,%d,%d\n", ringdata[0], ringdata[1], ringdata[2]);
1570 matched_context = p->defcontext;
1571 for (counter = 0; counter < 3; counter++) {
1572 int range = p->drings.ringnum[counter].range;
1573
1574 distMatches = 0;
1575 ast_verb(3, "Checking %d,%d,%d with +/- %d range\n",
1576 p->drings.ringnum[counter].ring[0],
1577 p->drings.ringnum[counter].ring[1],
1578 p->drings.ringnum[counter].ring[2],
1579 range);
1580 for (counter1 = 0; counter1 < 3; counter1++) {
1581 int ring = p->drings.ringnum[counter].ring[counter1];
1582
1583 if (ring == -1) {
1584 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
1585 ringdata[counter1]);
1586 distMatches++;
1587 } else if (ring - range <= ringdata[counter1] && ringdata[counter1] <= ring + range) {
1588 ast_verb(3, "Ring pattern %d is in range: %d to %d\n",
1589 ringdata[counter1], ring - range, ring + range);
1590 distMatches++;
1591 } else {
1592 /* The current dring pattern cannot match. */
1593 break;
1594 }
1595 }
1596
1597 if (distMatches == 3) {
1598 /* The ring matches, set the context to whatever is for distinctive ring.. */
1599 matched_context = S_OR(p->drings.ringContext[counter].contextData, p->defcontext);
1600 ast_verb(3, "Matched Distinctive Ring context %s\n", matched_context);
1601 break;
1602 }
1603 }
1604
1605 /* Set selected distinctive ring context if not already set. */
1606 if (strcmp(p->context, matched_context) != 0) {
1607 ast_copy_string(p->context, matched_context, sizeof(p->context));
1608 ast_channel_context_set(chan, matched_context);
1609 }
1610
1611 return 0;
1612 }
1613
1614 static int my_stop_callwait(void *pvt)
1615 {
1616 struct dahdi_pvt *p = pvt;
1617 p->callwaitingrepeat = 0;
1618 p->cidcwexpire = 0;
1619 p->cid_suppress_expire = 0;
1620
1621 return 0;
1622 }
1623
1624 static int send_callerid(struct dahdi_pvt *p);
1625 static int save_conference(struct dahdi_pvt *p);
1626 static int restore_conference(struct dahdi_pvt *p);
1627
1628 static int my_callwait(void *pvt)
1629 {
1630 struct dahdi_pvt *p = pvt;
1631
1632 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
1633 if (p->cidspill) {
1634 ast_log(LOG_WARNING, "Spill already exists?!?\n");
1635 ast_free(p->cidspill);
1636 }
1637
1638 /*
1639 * SAS: Subscriber Alert Signal, 440Hz for 300ms
1640 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
1641 */
1642 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
1643 return -1;
1644 save_conference(p);
1645 /* Silence */
1646 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
1647 if (!p->callwaitrings && p->callwaitingcallerid) {
1648 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
1649 p->callwaitcas = 1;
1650 p->cidlen = 2400 + 680 + READ_SIZE * 4;
1651 } else {
1652 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
1653 p->callwaitcas = 0;
1654 p->cidlen = 2400 + READ_SIZE * 4;
1655 }
1656 p->cidpos = 0;
1657 send_callerid(p);
1658
1659 return 0;
1660 }
1661
1662 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
1663 {
1664 struct dahdi_pvt *p = pvt;
1665 struct analog_pvt *analog_p = p->sig_pvt;
1666
1667 ast_debug(2, "Starting cid spill\n");
1668
1669 if (p->cidspill) {
1670 ast_log(LOG_WARNING, "cidspill already exists??\n");
1671 ast_free(p->cidspill);
1672 }
1673
1674 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
1675 int pres = ast_party_id_presentation(&caller->id);
1676 if (cwcid == 0) {
1677 /* Some CPE support additional parameters for on-hook Caller*ID,
1678 * such as redirecting reason and call qualifier, so send those
1679 * if available.
1680 * I don't know of any CPE that supports this for Call Waiting (unfortunately),
1681 * so don't send those for call waiting as that will just lengthen the CID spill
1682 * for no good reason.
1683 */
1684 p->cidlen = ast_callerid_full_generate(p->cidspill,
1685 caller->id.name.str,
1686 caller->id.number.str,
1687 NULL,
1688 analog_p->redirecting_reason,
1689 pres,
1690 analog_p->call_qualifier,
1691 CID_TYPE_MDMF,
1692 AST_LAW(p));
1693 } else {
1694 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
1695 caller->id.name.str, caller->id.number.str);
1696 p->callwaitcas = 0;
1697 p->cidcwexpire = 0;
1698 p->cidlen = ast_callerid_callwaiting_full_generate(p->cidspill,
1699 caller->id.name.str,
1700 caller->id.number.str,
1701 NULL,
1702 -1,
1703 pres,
1704 0,
1705 AST_LAW(p));
1706 p->cidlen += READ_SIZE * 4;
1707 }
1708 p->cidpos = 0;
1709 p->cid_suppress_expire = 0;
1710 send_callerid(p);
1711 }
1712 return 0;
1713 }
1714
1715 static int my_dsp_reset_and_flush_digits(void *pvt)
1716 {
1717 struct dahdi_pvt *p = pvt;
1718 if (p->dsp)
1719 ast_dsp_digitreset(p->dsp);
1720
1721 return 0;
1722 }
1723
1724 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
1725 {
1726 struct dahdi_pvt *p = pvt;
1727
1728 if (p->channel == CHAN_PSEUDO)
1729 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
1730
1731 if (mode == ANALOG_DIGITMODE_DTMF) {
1732 /* If we do hardware dtmf, no need for a DSP */
1733 if (p->hardwaredtmf) {
1734 if (p->dsp) {
1735 ast_dsp_free(p->dsp);
1736 p->dsp = NULL;
1737 }
1738 return 0;
1739 }
1740
1741 if (!p->dsp) {
1742 p->dsp = ast_dsp_new();
1743 if (!p->dsp) {
1744 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
1745 return -1;
1746 }
1747 }
1748
1749 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
1750 } else if (mode == ANALOG_DIGITMODE_MF) {
1751 if (!p->dsp) {
1752 p->dsp = ast_dsp_new();
1753 if (!p->dsp) {
1754 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
1755 return -1;
1756 }
1757 }
1758 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
1759 }
1760 return 0;
1761 }
1762
1763 static int dahdi_wink(struct dahdi_pvt *p, int index);
1764
1765 static int my_wink(void *pvt, enum analog_sub sub)
1766 {
1767 struct dahdi_pvt *p = pvt;
1768 int index = analogsub_to_dahdisub(sub);
1769 if (index != SUB_REAL) {
1770 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
1771 }
1772 return dahdi_wink(p, index);
1773 }
1774
1775 static void wakeup_sub(struct dahdi_pvt *p, int a);
1776
1777 static int reset_conf(struct dahdi_pvt *p);
1778
1779 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
1780
1781 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
1782 {
1783 struct ast_frame *f = *dest;
1784 struct dahdi_pvt *p = pvt;
1785 int idx = analogsub_to_dahdisub(analog_index);
1786
1787 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
1788 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
1789 (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
1790
1791 if (f->subclass.integer == 'f') {
1792 if (f->frametype == AST_FRAME_DTMF_END) {
1793 /* Fax tone -- Handle and return NULL */
1794 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
1795 /* If faxbuffers are configured, use them for the fax transmission */
1796 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
1797 struct dahdi_bufferinfo bi = {
1798 .txbufpolicy = p->faxbuf_policy,
1799 .bufsize = p->bufsize,
1800 .numbufs = p->faxbuf_no
1801 };
1802 int res;
1803
1804 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
1805 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
1806 } else {
1807 p->bufferoverrideinuse = 1;
1808 }
1809 }
1810 p->faxhandled = 1;
1811 if (p->dsp) {
1812 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
1813 ast_dsp_set_features(p->dsp, p->dsp_features);
1814 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
1815 }
1816 if (strcmp(ast_channel_exten(ast), "fax")) {
1817 const char *target_context = ast_channel_context(ast);
1818
1819 /*
1820 * We need to unlock 'ast' here because ast_exists_extension has the
1821 * potential to start autoservice on the channel. Such action is prone
1822 * to deadlock if the channel is locked.
1823 *
1824 * ast_async_goto() has its own restriction on not holding the
1825 * channel lock.
1826 */
1827 ast_mutex_unlock(&p->lock);
1828 ast_channel_unlock(ast);
1829 if (ast_exists_extension(ast, target_context, "fax", 1,
1830 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
1831 ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
1832 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
1833 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
1834 if (ast_async_goto(ast, target_context, "fax", 1))
1835 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
1836 } else {
1837 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
1838 }
1839 ast_channel_lock(ast);
1840 ast_mutex_lock(&p->lock);
1841 } else {
1842 ast_debug(1, "Already in a fax extension, not redirecting\n");
1843 }
1844 } else {
1845 ast_debug(1, "Fax already handled\n");
1846 }
1847 dahdi_confmute(p, 0);
1848 }
1849 p->subs[idx].f.frametype = AST_FRAME_NULL;
1850 p->subs[idx].f.subclass.integer = 0;
1851 *dest = &p->subs[idx].f;
1852 }
1853 }
1854
1855 static void my_lock_private(void *pvt)
1856 {
1857 struct dahdi_pvt *p = pvt;
1858 ast_mutex_lock(&p->lock);
1859 }
1860
1861 static void my_unlock_private(void *pvt)
1862 {
1863 struct dahdi_pvt *p = pvt;
1864 ast_mutex_unlock(&p->lock);
1865 }
1866
1867 static void my_deadlock_avoidance_private(void *pvt)
1868 {
1869 struct dahdi_pvt *p = pvt;
1870
1871 DEADLOCK_AVOIDANCE(&p->lock);
1872 }
1873
1874 static struct ast_manager_event_blob *dahdichannel_to_ami(struct stasis_message *msg)
1875 {
1876 RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
1877 struct ast_channel_blob *obj = stasis_message_data(msg);
1878 struct ast_json *group, *span, *channel;
1879
1880 channel_string = ast_manager_build_channel_state_string(obj->snapshot);
1881 if (!channel_string) {
1882 return NULL;
1883 }
1884
1885 group = ast_json_object_get(obj->blob, "group");
1886 span = ast_json_object_get(obj->blob, "span");
1887 channel = ast_json_object_get(obj->blob, "channel");
1888
1889 return ast_manager_event_blob_create(EVENT_FLAG_CALL, "DAHDIChannel",
1890 "%s"
1891 "DAHDIGroup: %llu\r\n"
1892 "DAHDISpan: %u\r\n"
1893 "DAHDIChannel: %s\r\n",
1894 ast_str_buffer(channel_string),
1895 (ast_group_t)ast_json_integer_get(group),
1896 (unsigned int)ast_json_integer_get(span),
1897 ast_json_string_get(channel));
1898 }
1899
1900 STASIS_MESSAGE_TYPE_DEFN_LOCAL(dahdichannel_type,
1901 .to_ami = dahdichannel_to_ami,
1902 );
1903
1904 /*! \brief Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages */
1905 static void publish_dahdichannel(struct ast_channel *chan, ast_group_t group, int span, const char *dahdi_channel)
1906 {
1907 RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
1908
1909 ast_assert(dahdi_channel != NULL);
1910
1911 blob = ast_json_pack("{s: I, s: i, s: s}",
1912 "group", (ast_json_int_t)group,
1913 "span", span,
1914 "channel", dahdi_channel);
1915 if (!blob) {
1916 return;
1917 }
1918
1919 ast_channel_lock(chan);
1920 ast_channel_publish_blob(chan, dahdichannel_type(), blob);
1921 ast_channel_unlock(chan);
1922 }
1923
1924 /*!
1925 * \internal
1926 * \brief Post an AMI DAHDI channel association event.
1927 * \since 1.8
1928 *
1929 * \param p DAHDI private pointer
1930 * \param chan Channel associated with the private pointer
1931 */
1932 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
1933 {
1934 char ch_name[23];
1935
1936 if (p->channel < CHAN_PSEUDO) {
1937 /* No B channel */
1938 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
1939 } else if (p->channel == CHAN_PSEUDO) {
1940 /* Pseudo channel */
1941 strcpy(ch_name, "pseudo");
1942 } else {
1943 /* Real channel */
1944 snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
1945 }
1946 publish_dahdichannel(chan, p->group, p->span, ch_name);
1947 }
1948
1949 #ifdef HAVE_PRI
1950 /*!
1951 * \internal
1952 * \brief Post an AMI DAHDI channel association event.
1953 * \since 1.8
1954 *
1955 * \param pvt DAHDI private pointer
1956 * \param chan Channel associated with the private pointer
1957 */
1958 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
1959 {
1960 struct dahdi_pvt *p = pvt;
1961
1962 dahdi_ami_channel_event(p, chan);
1963 }
1964 #endif
1965
1966 /* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
1967 * returns the last value of the linear setting
1968 */
1969 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
1970 {
1971 struct dahdi_pvt *p = pvt;
1972 int oldval;
1973 int idx = analogsub_to_dahdisub(sub);
1974
1975 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
1976 oldval = p->subs[idx].linear;
1977 p->subs[idx].linear = linear_mode ? 1 : 0;
1978 return oldval;
1979 }
1980
1981 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
1982 {
1983 struct dahdi_pvt *p = pvt;
1984 int idx = analogsub_to_dahdisub(sub);
1985
1986 p->subs[idx].inthreeway = inthreeway;
1987 }
1988
1989 static int get_alarms(struct dahdi_pvt *p);
1990 static void handle_alarms(struct dahdi_pvt *p, int alms);
1991 static void my_get_and_handle_alarms(void *pvt)
1992 {
1993 int res;
1994 struct dahdi_pvt *p = pvt;
1995
1996 res = get_alarms(p);
1997 handle_alarms(p, res);
1998 }
1999
2000 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
2001 {
2002 RAII_VAR(struct ast_channel *, bridged, ast_channel_bridge_peer(chan), ast_channel_cleanup);
2003
2004 if (bridged && ast_channel_tech(bridged) == &dahdi_tech) {
2005 struct dahdi_pvt *p = ast_channel_tech_pvt(bridged);
2006
2007 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
2008 return p->sig_pvt;
2009 }
2010 }
2011 return NULL;
2012 }
2013
2014 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
2015 {
2016 struct dahdi_pvt *p = pvt;
2017 int dahdi_sub = analogsub_to_dahdisub(sub);
2018 return p->subs[dahdi_sub].dfd;
2019 }
2020
2021 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
2022 {
2023 struct dahdi_pvt *p = pvt;
2024
2025 /* Choose proper cadence */
2026 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
2027 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
2028 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast_channel_name(ast), strerror(errno));
2029 *cid_rings = cidrings[p->distinctivering - 1];
2030 } else {
2031 if (p->distinctivering > 0) {
2032 ast_log(LOG_WARNING, "Cadence %d is not defined, falling back to default ring cadence\n", p->distinctivering);
2033 }
2034 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
2035 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast_channel_name(ast), strerror(errno));
2036 *cid_rings = p->sendcalleridafter;
2037 }
2038 }
2039
2040 static void my_set_alarm(void *pvt, int in_alarm)
2041 {
2042 struct dahdi_pvt *p = pvt;
2043
2044 p->inalarm = in_alarm;
2045 }
2046
2047 static void my_set_dialing(void *pvt, int is_dialing)
2048 {
2049 struct dahdi_pvt *p = pvt;
2050
2051 p->dialing = is_dialing;
2052 }
2053
2054 static void my_set_outgoing(void *pvt, int is_outgoing)
2055 {
2056 struct dahdi_pvt *p = pvt;
2057
2058 p->outgoing = is_outgoing;
2059 }
2060
2061 #if defined(HAVE_PRI) || defined(HAVE_SS7)
2062 static void my_set_digital(void *pvt, int is_digital)
2063 {
2064 struct dahdi_pvt *p = pvt;
2065
2066 p->digital = is_digital;
2067 }
2068 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
2069
2070 #if defined(HAVE_SS7)
2071 static void my_set_inservice(void *pvt, int is_inservice)
2072 {
2073 struct dahdi_pvt *p = pvt;
2074
2075 p->inservice = is_inservice;
2076 }
2077 #endif /* defined(HAVE_SS7) */
2078
2079 #if defined(HAVE_SS7)
2080 static void my_set_locallyblocked(void *pvt, int is_blocked)
2081 {
2082 struct dahdi_pvt *p = pvt;
2083
2084 p->locallyblocked = is_blocked;
2085 }
2086 #endif /* defined(HAVE_SS7) */
2087
2088 #if defined(HAVE_SS7)
2089 static void my_set_remotelyblocked(void *pvt, int is_blocked)
2090 {
2091 struct dahdi_pvt *p = pvt;
2092
2093 p->remotelyblocked = is_blocked;
2094 }
2095 #endif /* defined(HAVE_SS7) */
2096
2097 static void my_set_ringtimeout(void *pvt, int ringt)
2098 {
2099 struct dahdi_pvt *p = pvt;
2100 p->ringt = ringt;
2101 }
2102
2103 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
2104 {
2105 struct dahdi_pvt *p = pvt;
2106
2107 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
2108 ast_debug(1, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
2109 gettimeofday(&p->waitingfordt, NULL);
2110 ast_setstate(ast, AST_STATE_OFFHOOK);
2111 }
2112 }
2113
2114 static int my_check_waitingfordt(void *pvt)
2115 {
2116 struct dahdi_pvt *p = pvt;
2117
2118 if (p->waitingfordt.tv_sec) {
2119 return 1;
2120 }
2121
2122 return 0;
2123 }
2124
2125 static void my_set_confirmanswer(void *pvt, int flag)
2126 {
2127 struct dahdi_pvt *p = pvt;
2128 p->confirmanswer = flag;
2129 }
2130
2131 static int my_check_confirmanswer(void *pvt)
2132 {
2133 struct dahdi_pvt *p = pvt;
2134 if (p->confirmanswer) {
2135 return 1;
2136 }
2137
2138 return 0;
2139 }
2140
2141 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
2142 {
2143 struct dahdi_pvt *p = pvt;
2144
2145 p->callwaiting = callwaiting_enable;
2146 }
2147
2148 static void my_cancel_cidspill(void *pvt)
2149 {
2150 struct dahdi_pvt *p = pvt;
2151
2152 ast_free(p->cidspill);
2153 p->cidspill = NULL;
2154 restore_conference(p);
2155 }
2156
2157 static int my_confmute(void *pvt, int mute)
2158 {
2159 struct dahdi_pvt *p = pvt;
2160 return dahdi_confmute(p, mute);
2161 }
2162
2163 static void my_set_pulsedial(void *pvt, int flag)
2164 {
2165 struct dahdi_pvt *p = pvt;
2166 p->pulsedial = flag;
2167 }
2168
2169 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
2170 {
2171 struct dahdi_pvt *p = pvt;
2172
2173 p->owner = new_owner;
2174 }
2175
2176 static const char *my_get_orig_dialstring(void *pvt)
2177 {
2178 struct dahdi_pvt *p = pvt;
2179
2180 return p->dialstring;
2181 }
2182
2183 static void my_increase_ss_count(void)
2184 {
2185 ast_mutex_lock(&ss_thread_lock);
2186 ss_thread_count++;
2187 ast_mutex_unlock(&ss_thread_lock);
2188 }
2189
2190 static void my_decrease_ss_count(void)
2191 {
2192 ast_mutex_lock(&ss_thread_lock);
2193 ss_thread_count--;
2194 ast_cond_signal(&ss_thread_complete);
2195 ast_mutex_unlock(&ss_thread_lock);
2196 }
2197
2198 static void my_all_subchannels_hungup(void *pvt)
2199 {
2200 struct dahdi_pvt *p = pvt;
2201 int res, law;
2202
2203 p->faxhandled = 0;
2204 p->didtdd = 0;
2205
2206 if (p->dsp) {
2207 ast_dsp_free(p->dsp);
2208 p->dsp = NULL;
2209 }
2210
2211 p->law = p->law_default;
2212 law = p->law_default;
2213 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
2214 if (res < 0)
2215 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
2216
2217 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
2218
2219 #if 1
2220 {
2221 int i;
2222 p->owner = NULL;
2223 /* Cleanup owners here */
2224 for (i = 0; i < 3; i++) {
2225 p->subs[i].owner = NULL;
2226 }
2227 }
2228 #endif
2229
2230 reset_conf(p);
2231 if (num_restart_pending == 0) {
2232 restart_monitor();
2233 }
2234 }
2235
2236 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
2237
2238 static int my_conf_del(void *pvt, enum analog_sub sub)
2239 {
2240 struct dahdi_pvt *p = pvt;
2241 int x = analogsub_to_dahdisub(sub);
2242
2243 return conf_del(p, &p->subs[x], x);
2244 }
2245
2246 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
2247
2248 static int my_conf_add(void *pvt, enum analog_sub sub)
2249 {
2250 struct dahdi_pvt *p = pvt;
2251 int x = analogsub_to_dahdisub(sub);
2252
2253 return conf_add(p, &p->subs[x], x, 0);
2254 }
2255
2256 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
2257
2258 static int my_complete_conference_update(void *pvt, int needconference)
2259 {
2260 struct dahdi_pvt *p = pvt;
2261 int needconf = needconference;
2262 int x;
2263 int useslavenative;
2264 struct dahdi_pvt *slave = NULL;
2265
2266 useslavenative = isslavenative(p, &slave);
2267
2268 /* If we have a slave, add him to our conference now. or DAX
2269 if this is slave native */
2270 for (x = 0; x < MAX_SLAVES; x++) {
2271 if (p->slaves[x]) {
2272 if (useslavenative)
2273 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
2274 else {
2275 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
2276 needconf++;
2277 }
2278 }
2279 }
2280 /* If we're supposed to be in there, do so now */
2281 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
2282 if (useslavenative)
2283 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
2284 else {
2285 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
2286 needconf++;
2287 }
2288 }
2289 /* If we have a master, add ourselves to his conference */
2290 if (p->master) {
2291 if (isslavenative(p->master, NULL)) {
2292 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
2293 } else {
2294 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
2295 }
2296 }
2297 if (!needconf) {
2298 /* Nobody is left (or should be left) in our conference.
2299 Kill it. */
2300 p->confno = -1;
2301 }
2302
2303 return 0;
2304 }
2305
2306 static int check_for_conference(struct dahdi_pvt *p);
2307
2308 static int my_check_for_conference(void *pvt)
2309 {
2310 struct dahdi_pvt *p = pvt;
2311 return check_for_conference(p);
2312 }
2313
2314 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)
2315 {
2316 struct dahdi_pvt *p = pvt;
2317 int da, db;
2318 int tchan;
2319 int tinthreeway;
2320
2321 da = analogsub_to_dahdisub(a);
2322 db = analogsub_to_dahdisub(b);
2323
2324 tchan = p->subs[da].chan;
2325 p->subs[da].chan = p->subs[db].chan;
2326 p->subs[db].chan = tchan;
2327
2328 tinthreeway = p->subs[da].inthreeway;
2329 p->subs[da].inthreeway = p->subs[db].inthreeway;
2330 p->subs[db].inthreeway = tinthreeway;
2331
2332 p->subs[da].owner = ast_a;
2333 p->subs[db].owner = ast_b;
2334
2335 if (ast_a)
2336 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
2337 if (ast_b)
2338 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
2339
2340 wakeup_sub(p, a);
2341 wakeup_sub(p, b);
2342
2343 return;
2344 }
2345
2346 /*!
2347 * \internal
2348 * \brief performs duties of dahdi_new, but also removes and possibly unbinds (if callid_created is 1) before returning
2349 * \note this variant of dahdi should only be used in conjunction with ast_callid_threadstorage_auto()
2350 *
2351 * \param callid_created value returned from ast_callid_threadstorage_auto()
2352 * \param i, state, startpbx, idx, law, assignedids, requestor, callid
2353 */
2354 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);
2355
2356 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);
2357
2358 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
2359 {
2360 ast_callid callid = 0;
2361 int callid_created = ast_callid_threadstorage_auto(&callid);
2362 struct dahdi_pvt *p = pvt;
2363 int dsub = analogsub_to_dahdisub(sub);
2364
2365 return dahdi_new_callid_clean(p, state, startpbx, dsub, 0, NULL, requestor, callid, callid_created);
2366 }
2367
2368 #if defined(HAVE_PRI) || defined(HAVE_SS7)
2369 static int dahdi_setlaw(int dfd, int law)
2370 {
2371 int res;
2372 res = ioctl(dfd, DAHDI_SETLAW, &law);
2373 if (res)
2374 return res;
2375 return 0;
2376 }
2377 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
2378
2379 #if defined(HAVE_PRI)
2380 static struct ast_channel *my_new_pri_ast_channel(void *pvt, int state,
2381 enum sig_pri_law law, char *exten, const struct ast_assigned_ids *assignedids,
2382 const struct ast_channel *requestor)
2383 {
2384 struct dahdi_pvt *p = pvt;
2385 int audio;
2386 int newlaw = -1;
2387 ast_callid callid = 0;
2388 int callid_created = ast_callid_threadstorage_auto(&callid);
2389
2390 switch (p->sig) {
2391 case SIG_PRI_LIB_HANDLE_CASES:
2392 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
2393 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
2394 break;
2395 }
2396 /* Fall through */
2397 default:
2398 /* Set to audio mode at this point */
2399 audio = 1;
2400 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
2401 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
2402 p->channel, audio, strerror(errno));
2403 }
2404 break;
2405 }
2406
2407 if (law != SIG_PRI_DEFLAW) {
2408 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
2409 }
2410
2411 ast_copy_string(p->exten, exten, sizeof(p->exten));
2412
2413 switch (law) {
2414 case SIG_PRI_DEFLAW:
2415 newlaw = 0;
2416 break;
2417 case SIG_PRI_ALAW:
2418 newlaw = DAHDI_LAW_ALAW;
2419 break;
2420 case SIG_PRI_ULAW:
2421 newlaw = DAHDI_LAW_MULAW;
2422 break;
2423 }
2424
2425 return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, assignedids, requestor, callid, callid_created);
2426 }
2427 #endif /* defined(HAVE_PRI) */
2428
2429 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
2430
2431 #if defined(HAVE_PRI) || defined(HAVE_SS7)
2432 /*!
2433 * \internal
2434 * \brief Open the PRI/SS7 channel media path.
2435 * \since 1.8
2436 *
2437 * \param p Channel private control structure.
2438 */
2439 static void my_pri_ss7_open_media(void *p)
2440 {
2441 struct dahdi_pvt *pvt = p;
2442 int res;
2443 int dfd;
2444 int set_val;
2445
2446 dfd = pvt->subs[SUB_REAL].dfd;
2447
2448 /* Open the media path. */
2449 set_val = 1;
2450 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
2451 if (res < 0) {
2452 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
2453 pvt->channel, strerror(errno));
2454 }
2455
2456 /* Set correct companding law for this call. */
2457 res = dahdi_setlaw(dfd, pvt->law);
2458 if (res < 0) {
2459 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
2460 }
2461
2462 /* Set correct gain for this call. */
2463 if (pvt->digital) {
2464 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
2465 } else {
2466 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
2467 pvt->law);
2468 }
2469 if (res < 0) {
2470 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
2471 }
2472
2473 if (pvt->dsp_features && pvt->dsp) {
2474 ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
2475 }
2476 }
2477 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
2478
2479 #if defined(HAVE_PRI)
2480 /*!
2481 * \internal
2482 * \brief Ask DAHDI to dial the given dial string.
2483 * \since 1.8.11
2484 *
2485 * \param p Channel private control structure.
2486 * \param dial_string String to pass to DAHDI to dial.
2487 *
2488 * \note The channel private lock needs to be held when calling.
2489 */
2490 static void my_pri_dial_digits(void *p, const char *dial_string)
2491 {
2492 char dial_str[DAHDI_MAX_DTMF_BUF];
2493 struct dahdi_pvt *pvt = p;
2494 int res;
2495
2496 snprintf(dial_str, sizeof(dial_str), "T%s", dial_string);
2497 res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
2498 if (!res) {
2499 pvt->dialing = 1;
2500 }
2501 }
2502 #endif /* defined(HAVE_PRI) */
2503
2504 static int unalloc_sub(struct dahdi_pvt *p, int x);
2505
2506 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
2507 {
2508 struct dahdi_pvt *p = pvt;
2509
2510 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
2511 }
2512
2513 static int alloc_sub(struct dahdi_pvt *p, int x);
2514
2515 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
2516 {
2517 struct dahdi_pvt *p = pvt;
2518
2519 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
2520 }
2521
2522 static int has_voicemail(struct dahdi_pvt *p);
2523
2524 static int my_has_voicemail(void *pvt)
2525 {
2526 struct dahdi_pvt *p = pvt;
2527
2528 return has_voicemail(p);
2529 }
2530
2531 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
2532 {
2533 struct dahdi_pvt *p = pvt;
2534 int index;
2535
2536 index = analogsub_to_dahdisub(sub);
2537
2538 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
2539 }
2540
2541 static enum analog_event dahdievent_to_analogevent(int event)
2542 {
2543 enum analog_event res;
2544
2545 switch (event) {
2546 case DAHDI_EVENT_ONHOOK:
2547 res = ANALOG_EVENT_ONHOOK;
2548 break;
2549 case DAHDI_EVENT_RINGOFFHOOK:
2550 res = ANALOG_EVENT_RINGOFFHOOK;
2551 break;
2552 case DAHDI_EVENT_WINKFLASH:
2553 res = ANALOG_EVENT_WINKFLASH;
2554 break;
2555 case DAHDI_EVENT_ALARM:
2556 res = ANALOG_EVENT_ALARM;
2557 break;
2558 case DAHDI_EVENT_NOALARM:
2559 res = ANALOG_EVENT_NOALARM;
2560 break;
2561 case DAHDI_EVENT_DIALCOMPLETE:
2562 res = ANALOG_EVENT_DIALCOMPLETE;
2563 break;
2564 case DAHDI_EVENT_RINGERON:
2565 res = ANALOG_EVENT_RINGERON;
2566 break;
2567 case DAHDI_EVENT_RINGEROFF:
2568 res = ANALOG_EVENT_RINGEROFF;
2569 break;
2570 case DAHDI_EVENT_HOOKCOMPLETE:
2571 res = ANALOG_EVENT_HOOKCOMPLETE;
2572 break;
2573 case DAHDI_EVENT_PULSE_START:
2574 res = ANALOG_EVENT_PULSE_START;
2575 break;
2576 case DAHDI_EVENT_POLARITY:
2577 res = ANALOG_EVENT_POLARITY;
2578 break;
2579 case DAHDI_EVENT_RINGBEGIN:
2580 res = ANALOG_EVENT_RINGBEGIN;
2581 break;
2582 case DAHDI_EVENT_EC_DISABLED:
2583 res = ANALOG_EVENT_EC_DISABLED;
2584 break;
2585 case DAHDI_EVENT_REMOVED:
2586 res = ANALOG_EVENT_REMOVED;
2587 break;
2588 case DAHDI_EVENT_NEONMWI_ACTIVE:
2589 res = ANALOG_EVENT_NEONMWI_ACTIVE;
2590 break;
2591 case DAHDI_EVENT_NEONMWI_INACTIVE:
2592 res = ANALOG_EVENT_NEONMWI_INACTIVE;
2593 break;
2594 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
2595 case DAHDI_EVENT_TX_CED_DETECTED:
2596 res = ANALOG_EVENT_TX_CED_DETECTED;
2597 break;
2598 case DAHDI_EVENT_RX_CED_DETECTED:
2599 res = ANALOG_EVENT_RX_CED_DETECTED;
2600 break;
2601 case DAHDI_EVENT_EC_NLP_DISABLED:
2602 res = ANALOG_EVENT_EC_NLP_DISABLED;
2603 break;
2604 case DAHDI_EVENT_EC_NLP_ENABLED:
2605 res = ANALOG_EVENT_EC_NLP_ENABLED;
2606 break;
2607 #endif
2608 case DAHDI_EVENT_PULSEDIGIT:
2609 res = ANALOG_EVENT_PULSEDIGIT;
2610 break;
2611 case DAHDI_EVENT_DTMFDOWN:
2612 res = ANALOG_EVENT_DTMFDOWN;
2613 break;
2614 case DAHDI_EVENT_DTMFUP:
2615 res = ANALOG_EVENT_DTMFUP;
2616 break;
2617 default:
2618 switch(event & 0xFFFF0000) {
2619 case DAHDI_EVENT_PULSEDIGIT:
2620 case DAHDI_EVENT_DTMFDOWN:
2621 case DAHDI_EVENT_DTMFUP:
2622 /* The event includes a digit number in the low word.
2623 * Converting it to a 'enum analog_event' would remove
2624 * that information. Thus it is returned as-is.
2625 */
2626 return event;
2627 }
2628
2629 res = ANALOG_EVENT_ERROR;
2630 break;
2631 }
2632
2633 return res;
2634 }
2635
2636 static inline int dahdi_wait_event(int fd);
2637
2638 static int my_wait_event(void *pvt)
2639 {
2640 struct dahdi_pvt *p = pvt;
2641
2642 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
2643 }
2644
2645 static int my_get_event(void *pvt)
2646 {
2647 struct dahdi_pvt *p = pvt;
2648 int res;
2649
2650 if (p->fake_event) {
2651 res = p->fake_event;
2652 p->fake_event = 0;
2653 } else
2654 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
2655
2656 return dahdievent_to_analogevent(res);
2657 }
2658
2659 static int my_is_off_hook(void *pvt)
2660 {
2661 struct dahdi_pvt *p = pvt;
2662 int res;
2663 struct dahdi_params par;
2664
2665 memset(&par, 0, sizeof(par));
2666
2667 if (p->subs[SUB_REAL].dfd > -1)
2668 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
2669 else {
2670 /* Assume not off hook on CVRS */
2671 res = 0;
2672 par.rxisoffhook = 0;
2673 }
2674 if (res) {
2675 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
2676 }
2677
2678 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
2679 /* When "onhook" that means no battery on the line, and thus
2680 it is out of service..., if it's on a TDM card... If it's a channel
2681 bank, there is no telling... */
2682 return (par.rxbits > -1) || par.rxisoffhook;
2683 }
2684
2685 return par.rxisoffhook;
2686 }
2687
2688 static int my_set_echocanceller(void *pvt, int enable)
2689 {
2690 struct dahdi_pvt *p = pvt;
2691
2692 if (enable)
2693 dahdi_ec_enable(p);
2694 else
2695 dahdi_ec_disable(p);
2696
2697 return 0;
2698 }
2699
2700 static int dahdi_ring_phone(struct dahdi_pvt *p);
2701
2702 static int my_ring(void *pvt)
2703 {
2704 struct dahdi_pvt *p = pvt;
2705
2706 return dahdi_ring_phone(p);
2707 }
2708
2709 static int my_flash(void *pvt)
2710 {
2711 struct dahdi_pvt *p = pvt;
2712 int func = DAHDI_FLASH;
2713 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
2714 }
2715
2716 static inline int dahdi_set_hook(int fd, int hs);
2717
2718 static int my_off_hook(void *pvt)
2719 {
2720 struct dahdi_pvt *p = pvt;
2721 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
2722 }
2723
2724 static void my_set_needringing(void *pvt, int value)
2725 {
2726 struct dahdi_pvt *p = pvt;
2727 p->subs[SUB_REAL].needringing = value;
2728 }
2729
2730 static void my_set_polarity(void *pvt, int value)
2731 {
2732 struct dahdi_pvt *p = pvt;
2733
2734 if (p->channel == CHAN_PSEUDO) {
2735 return;
2736 }
2737 p->polarity = value;
2738 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
2739 }
2740
2741 static void my_start_polarityswitch(void *pvt)
2742 {
2743 struct dahdi_pvt *p = pvt;
2744
2745 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
2746 my_set_polarity(pvt, 0);
2747 }
2748 }
2749
2750 static void my_answer_polarityswitch(void *pvt)
2751 {
2752 struct dahdi_pvt *p = pvt;
2753
2754 if (!p->answeronpolarityswitch) {
2755 return;
2756 }
2757
2758 my_set_polarity(pvt, 1);
2759 }
2760
2761 static void my_hangup_polarityswitch(void *pvt)
2762 {
2763 struct dahdi_pvt *p = pvt;
2764
2765 if (!p->hanguponpolarityswitch) {
2766 return;
2767 }
2768
2769 if (p->answeronpolarityswitch) {
2770 my_set_polarity(pvt, 0);
2771 } else {
2772 my_set_polarity(pvt, 1);
2773 }
2774 }
2775
2776 /*! \brief Return DAHDI pivot if channel is FXO signalled */
2777 static struct dahdi_pvt *fxo_pvt(struct ast_channel *chan)
2778 {
2779 int res;
2780 struct dahdi_params dahdip;
2781 struct dahdi_pvt *pvt = NULL;
2782
2783 if (strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {
2784 ast_log(LOG_WARNING, "%s is not a DAHDI channel\n", ast_channel_name(chan));
2785 return NULL;
2786 }
2787
2788 memset(&dahdip, 0, sizeof(dahdip));
2789 res = ioctl(ast_channel_fd(chan, 0), DAHDI_GET_PARAMS, &dahdip);
2790
2791 if (res) {
2792 ast_log(LOG_WARNING, "Unable to get parameters of %s: %s\n", ast_channel_name(chan), strerror(errno));
2793 return NULL;
2794 }
2795 if (!(dahdip.sigtype & __DAHDI_SIG_FXO)) {
2796 ast_log(LOG_WARNING, "%s is not FXO signalled\n", ast_channel_name(chan));
2797 return NULL;
2798 }
2799
2800 pvt = ast_channel_tech_pvt(chan);
2801 if (!dahdi_analog_lib_handles(pvt->sig, 0, 0)) {
2802 ast_log(LOG_WARNING, "Channel signalling is not analog");
2803 return NULL;
2804 }
2805
2806 return pvt;
2807 }
2808
2809 static int polarity_read(struct ast_channel *chan, const char *cmd, char *data, char *buffer, size_t buflen)
2810 {
2811 struct dahdi_pvt *pvt;
2812
2813 pvt = fxo_pvt(chan);
2814 if (!pvt) {
2815 return -1;
2816 }
2817
2818 snprintf(buffer, buflen, "%d", pvt->polarity);
2819
2820 return 0;
2821 }
2822
2823 static int polarity_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
2824 {
2825 struct dahdi_pvt *pvt;
2826 int polarity;
2827
2828 pvt = fxo_pvt(chan);
2829 if (!pvt) {
2830 return -1;
2831 }
2832
2833 if (!strcasecmp(value, "idle")) {
2834 polarity = POLARITY_IDLE;
2835 } else if (!strcasecmp(value, "reverse")) {
2836 polarity = POLARITY_REV;
2837 } else {
2838 polarity = atoi(value);
2839 }
2840
2841 if (polarity != POLARITY_IDLE && polarity != POLARITY_REV) {
2842 ast_log(LOG_WARNING, "Invalid polarity: '%s'\n", value);
2843 return -1;
2844 }
2845
2846 my_set_polarity(pvt, polarity);
2847 return 0;
2848 }
2849
2850 static struct ast_custom_function polarity_function = {
2851 .name = "POLARITY",
2852 .write = polarity_write,
2853 .read = polarity_read,
2854 };
2855
2856 static int my_start(void *pvt)
2857 {
2858 struct dahdi_pvt *p = pvt;
2859 int x = DAHDI_START;
2860
2861 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
2862 }
2863
2864 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
2865 {
2866 struct dahdi_pvt *p = pvt;
2867
2868 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
2869 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
2870 return -1;
2871 }
2872
2873 if (sub != ANALOG_SUB_REAL) {
2874 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %u\n",
2875 dop->dialstr, p->channel, sub);
2876 return -1;
2877 }
2878
2879 return dahdi_dial_str(p, DAHDI_DIAL_OP_REPLACE, dop->dialstr);
2880 }
2881
2882 static void dahdi_train_ec(struct dahdi_pvt *p);
2883
2884 static int my_train_echocanceller(void *pvt)
2885 {
2886 struct dahdi_pvt *p = pvt;
2887
2888 dahdi_train_ec(p);
2889
2890 return 0;
2891 }
2892
2893 static int my_is_dialing(void *pvt, enum analog_sub sub)
2894 {
2895 struct dahdi_pvt *p = pvt;
2896 int index;
2897 int x;
2898
2899 index = analogsub_to_dahdisub(sub);
2900
2901 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
2902 ast_debug(1, "DAHDI_DIALING ioctl failed!\n");
2903 return -1;
2904 }
2905
2906 return x;
2907 }
2908
2909 static int my_on_hook(void *pvt)
2910 {
2911 struct dahdi_pvt *p = pvt;
2912 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
2913 }
2914
2915 #if defined(HAVE_PRI)
2916 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
2917 {
2918 struct dahdi_pvt *old_chan = chan_old;
2919 struct dahdi_pvt *new_chan = chan_new;
2920
2921 new_chan->owner = old_chan->owner;
2922 old_chan->owner = NULL;
2923 if (new_chan->owner) {
2924 ast_channel_tech_pvt_set(new_chan->owner, new_chan);
2925 ast_channel_internal_fd_set(new_chan->owner, 0, new_chan->subs[SUB_REAL].dfd);
2926 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
2927 old_chan->subs[SUB_REAL].owner = NULL;
2928 }
2929 /* Copy any DSP that may be present */
2930 new_chan->dsp = old_chan->dsp;
2931 new_chan->dsp_features = old_chan->dsp_features;
2932 old_chan->dsp = NULL;
2933 old_chan->dsp_features = 0;
2934
2935 /* Transfer flags from the old channel. */
2936 new_chan->dialing = old_chan->dialing;
2937 new_chan->digital = old_chan->digital;
2938 new_chan->outgoing = old_chan->outgoing;
2939 old_chan->dialing = 0;
2940 old_chan->digital = 0;
2941 old_chan->outgoing = 0;
2942
2943 /* More stuff to transfer to the new channel. */
2944 new_chan->law = old_chan->law;
2945 strcpy(new_chan->dialstring, old_chan->dialstring);
2946 }
2947 #endif /* defined(HAVE_PRI) */
2948
2949 #if defined(HAVE_PRI)
2950 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
2951 {
2952 switch (tone) {
2953 case SIG_PRI_TONE_RINGTONE:
2954 return DAHDI_TONE_RINGTONE;
2955 case SIG_PRI_TONE_STUTTER:
2956 return DAHDI_TONE_STUTTER;
2957 case SIG_PRI_TONE_CONGESTION:
2958 return DAHDI_TONE_CONGESTION;
2959 case SIG_PRI_TONE_DIALTONE:
2960 return DAHDI_TONE_DIALTONE;
2961 case SIG_PRI_TONE_DIALRECALL:
2962 return DAHDI_TONE_DIALRECALL;
2963 case SIG_PRI_TONE_INFO:
2964 return DAHDI_TONE_INFO;
2965 case SIG_PRI_TONE_BUSY:
2966 return DAHDI_TONE_BUSY;
2967 default:
2968 return -1;
2969 }
2970 }
2971 #endif /* defined(HAVE_PRI) */
2972
2973 #if defined(HAVE_PRI)
2974 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
2975 {
2976 int x;
2977
2978 ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
2979 switch (x) {
2980 case DAHDI_EVENT_NONE:
2981 break;
2982 case DAHDI_EVENT_ALARM:
2983 case DAHDI_EVENT_NOALARM:
2984 if (sig_pri_is_alarm_ignored(pri)) {
2985 break;
2986 }
2987 /* Fall through */
2988 default:
2989 ast_log(LOG_NOTICE, "Got DAHDI event: %s (%d) on D-channel of span %d\n",
2990 event2str(x), x, pri->span);
2991 break;
2992 }
2993 /* Keep track of alarm state */
2994 switch (x) {
2995 case DAHDI_EVENT_ALARM:
2996 pri_event_alarm(pri, index, 0);
2997 break;
2998 case DAHDI_EVENT_NOALARM:
2999 pri_event_noalarm(pri, index, 0);
3000 break;
3001 case DAHDI_EVENT_REMOVED:
3002 pri_queue_for_destruction(pri);
3003 break;
3004 default:
3005 break;
3006 }
3007 }
3008 #endif /* defined(HAVE_PRI) */
3009
3010 #if defined(HAVE_PRI)
3011 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
3012 {
3013 struct dahdi_pvt *p = pvt;
3014
3015 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
3016 }
3017 #endif /* defined(HAVE_PRI) */
3018
3019 #if defined(HAVE_PRI) || defined(HAVE_SS7)
3020 /*!
3021 * \internal
3022 * \brief Set the caller id information.
3023 * \since 1.8
3024 *
3025 * \param pvt DAHDI private structure
3026 * \param caller Caller-id information to set.
3027 */
3028 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
3029 {
3030 struct dahdi_pvt *p = pvt;
3031
3032 ast_copy_string(p->cid_num,
3033 S_COR(caller->id.number.valid, caller->id.number.str, ""),
3034 sizeof(p->cid_num));
3035 ast_copy_string(p->cid_name,
3036 S_COR(caller->id.name.valid, caller->id.name.str, ""),
3037 sizeof(p->cid_name));
3038 ast_copy_string(p->cid_subaddr,
3039 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
3040 sizeof(p->cid_subaddr));
3041 p->cid_ton = caller->id.number.plan;
3042 p->callingpres = ast_party_id_presentation(&caller->id);
3043 if (caller->id.tag) {
3044 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
3045 }
3046 ast_copy_string(p->cid_ani,
3047 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
3048 sizeof(p->cid_ani));
3049 p->cid_ani2 = caller->ani2;
3050 }
3051 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
3052
3053 #if defined(HAVE_PRI) || defined(HAVE_SS7)
3054 /*!
3055 * \internal
3056 * \brief Set the Dialed Number Identifier.
3057 * \since 1.8
3058 *
3059 * \param pvt DAHDI private structure
3060 * \param dnid Dialed Number Identifier string.
3061 */
3062 static void my_set_dnid(void *pvt, const char *dnid)
3063 {
3064 struct dahdi_pvt *p = pvt;
3065
3066 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
3067 }
3068 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
3069
3070 #if defined(HAVE_PRI)
3071 /*!
3072 * \internal
3073 * \brief Set the Redirecting Directory Number Information Service (RDNIS).
3074 * \since 1.8
3075 *
3076 * \param pvt DAHDI private structure
3077 * \param rdnis Redirecting Directory Number Information Service (RDNIS) string.
3078 */
3079 static void my_set_rdnis(void *pvt, const char *rdnis)
3080 {
3081 struct dahdi_pvt *p = pvt;
3082
3083 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
3084 }
3085 #endif /* defined(HAVE_PRI) */
3086
3087 #if defined(HAVE_PRI)
3088 /*!
3089 * \internal
3090 * \brief Make a dialstring for native ISDN CC to recall properly.
3091 * \since 1.8
3092 *
3093 * \param priv Channel private control structure.
3094 * \param buf Where to put the modified dialstring.
3095 * \param buf_size Size of modified dialstring buffer.
3096 *
3097 * \details
3098 * original dialstring:
3099 * \verbatim
3100 DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadence#>|d][/extension[/options]]
3101 \endverbatim
3102 *
3103 * The modified dialstring will have prefixed the channel-group section
3104 * with the ISDN channel restriction.
3105 *
3106 * buf:
3107 * \verbatim
3108 DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadence#>|d][/extension[/options]]
3109 \endverbatim
3110 *
3111 * The routine will check to see if the ISDN channel restriction is already
3112 * in the original dialstring.
3113 */
3114 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
3115 {
3116 char *dial;
3117 struct dahdi_pvt *pvt;
3118 AST_DECLARE_APP_ARGS(args,
3119 AST_APP_ARG(tech); /* channel technology token */
3120 AST_APP_ARG(group); /* channel/group token */
3121 //AST_APP_ARG(ext); /* extension token */
3122 //AST_APP_ARG(opts); /* options token */
3123 //AST_APP_ARG(other); /* Any remining unused arguments */
3124 );
3125
3126 pvt = priv;
3127 dial = ast_strdupa(pvt->dialstring);
3128 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
3129 if (!args.tech) {
3130 ast_copy_string(buf, pvt->dialstring, buf_size);
3131 return;
3132 }
3133 if (!args.group) {
3134 /* Append the ISDN span channel restriction to the dialstring. */
3135 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
3136 return;
3137 }
3138 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
3139 /* The ISDN span channel restriction is not needed or already
3140 * in the dialstring. */
3141 ast_copy_string(buf, pvt->dialstring, buf_size);
3142 return;
3143 }
3144 /* Insert the ISDN span channel restriction into the dialstring. */
3145 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
3146 }
3147 #endif /* defined(HAVE_PRI) */
3148
3149 #if defined(HAVE_PRI)
3150 /*!
3151 * \internal
3152 * \brief Reevaluate the PRI span device state.
3153 * \since 1.8
3154 *
3155 * \param pri Asterisk D channel control structure.
3156 *
3157 * \note Assumes the pri->lock is already obtained.
3158 */
3159 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
3160 {
3161 unsigned idx;
3162 unsigned num_b_chans; /* Number of B channels provisioned on the span. */
3163 unsigned in_use; /* Number of B channels in use on the span. */
3164 unsigned in_alarm; /* TRUE if the span is in alarm condition. */
3165 enum ast_device_state new_state;
3166
3167 /* Count the number of B channels and the number of B channels in use. */
3168 num_b_chans = 0;
3169 in_use = 0;
3170 in_alarm = 1;
3171 for (idx = pri->numchans; idx--;) {
3172 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
3173 /* This is a B channel interface. */
3174 ++num_b_chans;
3175 if (!sig_pri_is_chan_available(pri->pvts[idx])) {
3176 ++in_use;
3177 }
3178 if (!pri->pvts[idx]->inalarm) {
3179 /* There is a channel that is not in alarm. */
3180 in_alarm = 0;
3181 }
3182 }
3183 }
3184
3185 /* Update the span congestion device state and report any change. */
3186 if (in_alarm) {
3187 new_state = AST_DEVICE_UNAVAILABLE;
3188 } else {
3189 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
3190 }
3191 if (pri->congestion_devstate != new_state) {
3192 pri->congestion_devstate = new_state;
3193 ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/congestion", pri->span);
3194 }
3195 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
3196 /* Update the span threshold device state and report any change. */
3197 if (in_alarm) {
3198 new_state = AST_DEVICE_UNAVAILABLE;
3199 } else if (!in_use) {
3200 new_state = AST_DEVICE_NOT_INUSE;
3201 } else if (!pri->user_busy_threshold) {
3202 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
3203 } else {
3204 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
3205 : AST_DEVICE_BUSY;
3206 }
3207 if (pri->threshold_devstate != new_state) {
3208 pri->threshold_devstate = new_state;
3209 ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/threshold", pri->span);
3210 }
3211 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
3212 }
3213 #endif /* defined(HAVE_PRI) */
3214
3215 #if defined(HAVE_PRI)
3216 /*!
3217 * \internal
3218 * \brief Reference this module.
3219 * \since 1.8
3220 */
3221 static void my_module_ref(void)
3222 {
3223 ast_module_ref(ast_module_info->self);
3224 }
3225 #endif /* defined(HAVE_PRI) */
3226
3227 #if defined(HAVE_PRI)
3228 /*!
3229 * \internal
3230 * \brief Unreference this module.
3231 * \since 1.8
3232 */
3233 static void my_module_unref(void)
3234 {
3235 ast_module_unref(ast_module_info->self);
3236 }
3237 #endif /* defined(HAVE_PRI) */
3238
3239 #if defined(HAVE_PRI)
3240 #if defined(HAVE_PRI_CALL_WAITING)
3241 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
3242 #endif /* defined(HAVE_PRI_CALL_WAITING) */
3243 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
3244
3245 struct sig_pri_callback sig_pri_callbacks =
3246 {
3247 .handle_dchan_exception = my_handle_dchan_exception,
3248 .play_tone = my_pri_play_tone,
3249 .set_echocanceller = my_set_echocanceller,
3250 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
3251 .lock_private = my_lock_private,
3252 .unlock_private = my_unlock_private,
3253 .deadlock_avoidance_private = my_deadlock_avoidance_private,
3254 .new_ast_channel = my_new_pri_ast_channel,
3255 .fixup_chans = my_pri_fixup_chans,
3256 .set_alarm = my_set_alarm,
3257 .set_dialing = my_set_dialing,
3258 .set_outgoing = my_set_outgoing,
3259 .set_digital = my_set_digital,
3260 .set_callerid = my_set_callerid,
3261 .set_dnid = my_set_dnid,
3262 .set_rdnis = my_set_rdnis,
3263 .new_nobch_intf = dahdi_new_pri_nobch_channel,
3264 #if defined(HAVE_PRI_CALL_WAITING)
3265 .init_config = my_pri_init_config,
3266 #endif /* defined(HAVE_PRI_CALL_WAITING) */
3267 .get_orig_dialstring = my_get_orig_dialstring,
3268 .make_cc_dialstring = my_pri_make_cc_dialstring,
3269 .update_span_devstate = dahdi_pri_update_span_devstate,
3270 .module_ref = my_module_ref,
3271 .module_unref = my_module_unref,
3272 .dial_digits = my_pri_dial_digits,
3273 .open_media = my_pri_ss7_open_media,
3274 .ami_channel_event = my_ami_channel_event,
3275 .destroy_later = pri_queue_for_destruction,
3276 };
3277 #endif /* defined(HAVE_PRI) */
3278
3279 #if defined(HAVE_SS7)
3280 /*!
3281 * \internal
3282 * \brief Handle the SS7 link exception.
3283 * \since 1.8
3284 *
3285 * \param linkset Controlling linkset for the channel.
3286 * \param which Link index of the signaling channel.
3287 */
3288 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
3289 {
3290 int event;
3291
3292 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
3293 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
3294 linkset->span, which);
3295 return;
3296 }
3297 switch (event) {
3298 case DAHDI_EVENT_NONE:
3299 break;
3300 case DAHDI_EVENT_ALARM:
3301 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
3302 event2str(event), event, linkset->span, which);
3303 sig_ss7_link_alarm(linkset, which);
3304 break;
3305 case DAHDI_EVENT_NOALARM:
3306 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
3307 event2str(event), event, linkset->span, which);
3308 sig_ss7_link_noalarm(linkset, which);
3309 break;
3310 default:
3311 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
3312 event2str(event), event, linkset->span, which);
3313 break;
3314 }
3315 }
3316 #endif /* defined(HAVE_SS7) */
3317
3318 #if defined(HAVE_SS7)
3319 static void my_ss7_set_loopback(void *pvt, int enable)
3320 {
3321 struct dahdi_pvt *p = pvt;
3322
3323 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
3324 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
3325 strerror(errno));
3326 }
3327 }
3328 #endif /* defined(HAVE_SS7) */
3329
3330 #if defined(HAVE_SS7)
3331 /*!
3332 * \internal
3333 * \brief Find the linkset to which SS7 belongs.
3334 * \since 11.0
3335 *
3336 * \param ss7 structure to match on.
3337 *
3338 * \retval linkset if found.
3339 * \retval NULL if not found.
3340 */
3341 static struct sig_ss7_linkset *my_ss7_find_linkset(struct ss7 *ss7)
3342 {
3343 int idx;
3344
3345 if (!ss7) {
3346 return NULL;
3347 }
3348
3349 for (idx = 0; idx < NUM_SPANS; ++idx) {
3350 if (linksets[idx].ss7.ss7 == ss7) {
3351 return &linksets[idx].ss7;
3352 }
3353 }
3354 return NULL;
3355 }
3356 #endif /* defined(HAVE_SS7) */
3357
3358 #if defined(HAVE_SS7)
3359 /*!
3360 * \internal
3361 * \brief Create a new asterisk channel structure for SS7.
3362 * \since 1.8
3363 *
3364 * \param pvt Private channel structure.
3365 * \param state Initial state of new channel.
3366 * \param law Companding law to use.
3367 * \param exten Dialplan extension for incoming call.
3368 * \param requestor Channel requesting this new channel.
3369 * \param assignedids
3370 *
3371 * \retval ast_channel on success.
3372 * \retval NULL on error.
3373 */
3374 static struct ast_channel *my_new_ss7_ast_channel(void *pvt, int state, enum sig_ss7_law law, char *exten, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
3375 {
3376 struct dahdi_pvt *p = pvt;
3377 int audio;
3378 int newlaw;
3379 ast_callid callid = 0;
3380 int callid_created = ast_callid_threadstorage_auto(&callid);
3381
3382 /* Set to audio mode at this point */
3383 audio = 1;
3384 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
3385 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
3386 p->channel, audio, strerror(errno));
3387
3388 if (law != SIG_SS7_DEFLAW) {
3389 dahdi_setlaw(p->subs[SUB_REAL].dfd,
3390 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
3391 }
3392
3393 ast_copy_string(p->exten, exten, sizeof(p->exten));
3394
3395 newlaw = -1;
3396 switch (law) {
3397 case SIG_SS7_DEFLAW:
3398 newlaw = 0;
3399 break;
3400 case SIG_SS7_ALAW:
3401 newlaw = DAHDI_LAW_ALAW;
3402 break;
3403 case SIG_SS7_ULAW:
3404 newlaw = DAHDI_LAW_MULAW;
3405 break;
3406 }
3407 return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, assignedids, requestor, callid, callid_created);
3408 }
3409 #endif /* defined(HAVE_SS7) */
3410
3411 #if defined(HAVE_SS7)
3412 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
3413 {
3414 switch (tone) {
3415 case SIG_SS7_TONE_RINGTONE:
3416 return DAHDI_TONE_RINGTONE;
3417 case SIG_SS7_TONE_STUTTER:
3418 return DAHDI_TONE_STUTTER;
3419 case SIG_SS7_TONE_CONGESTION:
3420 return DAHDI_TONE_CONGESTION;
3421 case SIG_SS7_TONE_DIALTONE:
3422 return DAHDI_TONE_DIALTONE;
3423 case SIG_SS7_TONE_DIALRECALL:
3424 return DAHDI_TONE_DIALRECALL;
3425 case SIG_SS7_TONE_INFO:
3426 return DAHDI_TONE_INFO;
3427 case SIG_SS7_TONE_BUSY:
3428 return DAHDI_TONE_BUSY;
3429 default:
3430 return -1;
3431 }
3432 }
3433 #endif /* defined(HAVE_SS7) */
3434
3435 #if defined(HAVE_SS7)
3436 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
3437 {
3438 struct dahdi_pvt *p = pvt;
3439
3440 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
3441 }
3442 #endif /* defined(HAVE_SS7) */
3443
3444 #if defined(HAVE_SS7)
3445 struct sig_ss7_callback sig_ss7_callbacks =
3446 {
3447 .lock_private = my_lock_private,
3448 .unlock_private = my_unlock_private,
3449 .deadlock_avoidance_private = my_deadlock_avoidance_private,
3450
3451 .set_echocanceller = my_set_echocanceller,
3452 .set_loopback = my_ss7_set_loopback,
3453
3454 .new_ast_channel = my_new_ss7_ast_channel,
3455 .play_tone = my_ss7_play_tone,
3456
3457 .handle_link_exception = my_handle_link_exception,
3458 .set_alarm = my_set_alarm,
3459 .set_dialing = my_set_dialing,
3460 .set_outgoing = my_set_outgoing,
3461 .set_digital = my_set_digital,
3462 .set_inservice = my_set_inservice,
3463 .set_locallyblocked = my_set_locallyblocked,
3464 .set_remotelyblocked = my_set_remotelyblocked,
3465 .set_callerid = my_set_callerid,
3466 .set_dnid = my_set_dnid,
3467 .open_media = my_pri_ss7_open_media,
3468 .find_linkset = my_ss7_find_linkset,
3469 };
3470 #endif /* defined(HAVE_SS7) */
3471
3472 /*!
3473 * \brief Send MWI state change
3474 *
3475 * \param mailbox This is the mailbox associated with the FXO line that the
3476 * MWI state has changed on.
3477 * \param thereornot This argument should simply be set to 1 or 0, to indicate
3478 * whether there are messages waiting or not.
3479 *
3480 * This function does two things:
3481 *
3482 * 1) It generates an internal Asterisk event notifying any other module that
3483 * cares about MWI that the state of a mailbox has changed.
3484 *
3485 * 2) It runs the script specified by the mwimonitornotify option to allow
3486 * some custom handling of the state change.
3487 */
3488 static void notify_message(char *mailbox, int thereornot)
3489 {
3490 char s[sizeof(mwimonitornotify) + 164];
3491
3492 if (ast_strlen_zero(mailbox)) {
3493 return;
3494 }
3495
3496 ast_publish_mwi_state(mailbox, NULL, thereornot, thereornot);
3497 if (!ast_strlen_zero(mwimonitornotify)) {
3498 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
3499 ast_safe_system(s);
3500 }
3501 }
3502
3503 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
3504 {
3505 struct dahdi_pvt *p = pvt;
3506
3507 if (neon_mwievent > -1 && !p->mwimonitor_neon)
3508 return;
3509
3510 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
3511 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
3512 notify_message(p->mailbox, 1);
3513 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
3514 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
3515 notify_message(p->mailbox, 0);
3516 }
3517 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
3518 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
3519 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
3520 ast_hangup(chan);
3521 return;
3522 }
3523 }
3524
3525 static int my_have_progressdetect(void *pvt)
3526 {
3527 struct dahdi_pvt *p = pvt;
3528
3529 if ((p->callprogress & CALLPROGRESS_PROGRESS)
3530 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
3531 return 1;
3532 } else {
3533 /* Don't have progress detection. */
3534 return 0;
3535 }
3536 }
3537
3538 #define gen_pvt_field_callback(type, field) \
3539 static type my_get_##field(void *pvt) \
3540 { \
3541 struct dahdi_pvt *p = pvt; \
3542 return p->field; \
3543 }
3544
3545 gen_pvt_field_callback(int, firstdigit_timeout);
3546 gen_pvt_field_callback(int, interdigit_timeout);
3547 gen_pvt_field_callback(int, matchdigit_timeout);
3548
3549 #undef gen_pvt_field_callback
3550
3551 struct analog_callback analog_callbacks =
3552 {
3553 .play_tone = my_play_tone,
3554 .get_event = my_get_event,
3555 .wait_event = my_wait_event,
3556 .is_off_hook = my_is_off_hook,
3557 .set_echocanceller = my_set_echocanceller,
3558 .ring = my_ring,
3559 .flash = my_flash,
3560 .off_hook = my_off_hook,
3561 .dial_digits = my_dial_digits,
3562 .train_echocanceller = my_train_echocanceller,
3563 .on_hook = my_on_hook,
3564 .is_dialing = my_is_dialing,
3565 .allocate_sub = my_allocate_sub,
3566 .unallocate_sub = my_unallocate_sub,
3567 .swap_subs = my_swap_subchannels,
3568 .has_voicemail = my_has_voicemail,
3569 .check_for_conference = my_check_for_conference,
3570 .conf_add = my_conf_add,
3571 .conf_del = my_conf_del,
3572 .complete_conference_update = my_complete_conference_update,
3573 .start = my_start,
3574 .all_subchannels_hungup = my_all_subchannels_hungup,
3575 .lock_private = my_lock_private,
3576 .unlock_private = my_unlock_private,
3577 .deadlock_avoidance_private = my_deadlock_avoidance_private,
3578 .handle_dtmf = my_handle_dtmf,
3579 .wink = my_wink,
3580 .new_ast_channel = my_new_analog_ast_channel,
3581 .dsp_set_digitmode = my_dsp_set_digitmode,
3582 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
3583 .send_callerid = my_send_callerid,
3584 .callwait = my_callwait,
3585 .stop_callwait = my_stop_callwait,
3586 .get_callerid = my_get_callerid,
3587 .start_cid_detect = my_start_cid_detect,
3588 .stop_cid_detect = my_stop_cid_detect,
3589 .handle_notify_message = my_handle_notify_message,
3590 .increase_ss_count = my_increase_ss_count,
3591 .decrease_ss_count = my_decrease_ss_count,
3592 .distinctive_ring = my_distinctive_ring,
3593 .set_linear_mode = my_set_linear_mode,
3594 .set_inthreeway = my_set_inthreeway,
3595 .get_and_handle_alarms = my_get_and_handle_alarms,
3596 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
3597 .get_sub_fd = my_get_sub_fd,
3598 .set_cadence = my_set_cadence,
3599 .set_alarm = my_set_alarm,
3600 .set_dialing = my_set_dialing,
3601 .set_outgoing = my_set_outgoing,
3602 .set_ringtimeout = my_set_ringtimeout,
3603 .set_waitingfordt = my_set_waitingfordt,
3604 .check_waitingfordt = my_check_waitingfordt,
3605 .set_confirmanswer = my_set_confirmanswer,
3606 .check_confirmanswer = my_check_confirmanswer,
3607 .set_callwaiting = my_set_callwaiting,
3608 .cancel_cidspill = my_cancel_cidspill,
3609 .confmute = my_confmute,
3610 .set_pulsedial = my_set_pulsedial,
3611 .set_new_owner = my_set_new_owner,
3612 .get_orig_dialstring = my_get_orig_dialstring,
3613 .set_needringing = my_set_needringing,
3614 .set_polarity = my_set_polarity,
3615 .start_polarityswitch = my_start_polarityswitch,
3616 .answer_polarityswitch = my_answer_polarityswitch,
3617 .hangup_polarityswitch = my_hangup_polarityswitch,
3618 .have_progressdetect = my_have_progressdetect,
3619 .get_firstdigit_timeout = my_get_firstdigit_timeout,
3620 .get_matchdigit_timeout = my_get_matchdigit_timeout,
3621 .get_interdigit_timeout = my_get_interdigit_timeout,
3622 };
3623
3624 /*! Round robin search locations. */
3625 static struct dahdi_pvt *round_robin[64]; /* groups can range from 0-63 */
3626
3627 int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
3628 {
3629 int res;
3630 if (p->subs[SUB_REAL].owner == ast)
3631 res = 0;
3632 else if (p->subs[SUB_CALLWAIT].owner == ast)
3633 res = 1;
3634 else if (p->subs[SUB_THREEWAY].owner == ast)
3635 res = 2;
3636 else {
3637 res = -1;
3638 if (!nullok)
3639 ast_log(LOG_WARNING,
3640 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
3641 ast ? ast_channel_name(ast) : "", p->channel, fname, line);
3642 }
3643 return res;
3644 }
3645
3646 /*!
3647 * \internal
3648 * \brief Obtain the specified subchannel owner lock if the owner exists.
3649 *
3650 * \param pvt Channel private struct.
3651 * \param sub_idx Subchannel owner to lock.
3652 *
3653 * \note Assumes the pvt->lock is already obtained.
3654 *
3655 * \note
3656 * Because deadlock avoidance may have been necessary, you need to confirm
3657 * the state of things before continuing.
3658 */
3659 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
3660 {
3661 for (;;) {
3662 if (!pvt->subs[sub_idx].owner) {
3663 /* No subchannel owner pointer */
3664 break;
3665 }
3666 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
3667 /* Got subchannel owner lock */
3668 break;
3669 }
3670 /* We must unlock the private to avoid the possibility of a deadlock */
3671 DEADLOCK_AVOIDANCE(&pvt->lock);
3672 }
3673 }
3674
3675 static void wakeup_sub(struct dahdi_pvt *p, int a)
3676 {
3677 dahdi_lock_sub_owner(p, a);
3678 if (p->subs[a].owner) {
3679 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
3680 ast_channel_unlock(p->subs[a].owner);
3681 }
3682 }
3683
3684 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
3685 {
3686 for (;;) {
3687 if (p->owner) {
3688 if (ast_channel_trylock(p->owner)) {
3689 DEADLOCK_AVOIDANCE(&p->lock);
3690 } else {
3691 ast_queue_frame(p->owner, f);
3692 ast_channel_unlock(p->owner);
3693 break;
3694 }
3695 } else
3696 break;
3697 }
3698 }
3699
3700 static void publish_channel_alarm_clear(int channel)
3701 {
3702 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
3703 RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free);
3704 if (!dahdi_chan) {
3705 return;
3706 }
3707
3708 ast_str_set(&dahdi_chan, 0, "%d", channel);
3709 ast_log(LOG_NOTICE, "Alarm cleared on channel DAHDI/%d\n", channel);
3710 body = ast_json_pack("{s: s}", "DAHDIChannel", ast_str_buffer(dahdi_chan));
3711 if (!body) {
3712 return;
3713 }
3714
3715 ast_manager_publish_event("AlarmClear", EVENT_FLAG_SYSTEM, body);
3716 }
3717
3718 static void publish_span_alarm_clear(int span)
3719 {
3720 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
3721
3722 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", span);
3723 body = ast_json_pack("{s: i}", "Span", span);
3724 if (!body) {
3725 return;
3726 }
3727
3728 ast_manager_publish_event("SpanAlarmClear", EVENT_FLAG_SYSTEM, body);
3729 }
3730
3731 static void handle_clear_alarms(struct dahdi_pvt *p)
3732 {
3733 #if defined(HAVE_PRI)
3734 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
3735 return;
3736 }
3737 #endif /* defined(HAVE_PRI) */
3738
3739 if (report_alarms & REPORT_CHANNEL_ALARMS) {
3740 publish_channel_alarm_clear(p->channel);
3741 }
3742 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
3743 publish_span_alarm_clear(p->span);
3744 }
3745 }
3746
3747 #ifdef HAVE_OPENR2
3748 static void mfcr2_queue_for_destruction(const struct dahdi_pvt *p)
3749 {
3750 const struct dahdi_mfcr2 *r2link = p->mfcr2;
3751 struct r2link_entry *cur;
3752 AST_LIST_LOCK(&r2links);
3753 AST_LIST_TRAVERSE_SAFE_BEGIN(&r2links, cur, list) {
3754 if (r2link == &cur->mfcr2) {
3755 ast_debug(3, "MFC/R2 channel %d queued for destruction\n", p->channel);
3756 AST_LIST_MOVE_CURRENT(&nodev_r2links, list);
3757 break;
3758 }
3759 }
3760 AST_LIST_TRAVERSE_SAFE_END;
3761 AST_LIST_UNLOCK(&r2links);
3762 }
3763
3764 static int dahdi_r2_answer(struct dahdi_pvt *p)
3765 {
3766 int res = 0;
3767 /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
3768 * and does not has support for openr2_chan_answer_call_with_mode
3769 * */
3770 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
3771 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
3772 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
3773 if (!double_answer) {
3774 /* this still can result in double answer if the channel context
3775 * was configured that way */
3776 res = openr2_chan_answer_call(p->r2chan);
3777 } else if (wants_double_answer) {
3778 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
3779 } else {
3780 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
3781 }
3782 #else
3783 res = openr2_chan_answer_call(p->r2chan);
3784 #endif
3785 return res;
3786 }
3787
3788
3789
3790 /* should be called with the ast_channel locked */
3791 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
3792 {
3793 openr2_calling_party_category_t cat;
3794 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
3795 struct dahdi_pvt *p = ast_channel_tech_pvt(c);
3796 if (ast_strlen_zero(catstr)) {
3797 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
3798 ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
3799 return p->mfcr2_category;
3800 }
3801 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
3802 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
3803 catstr, ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
3804 return p->mfcr2_category;
3805 }
3806 ast_debug(1, "Using category %s\n", catstr);
3807 return cat;
3808 }
3809
3810 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
3811 {
3812 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3813 ast_mutex_lock(&p->lock);
3814 if (p->mfcr2call) {
3815 ast_mutex_unlock(&p->lock);
3816 /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
3817 interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
3818 can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
3819 the other end will see our seize as a forced release and drop the call, we will see an invalid
3820 pattern that will be seen and treated as protocol error. */
3821 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
3822 return;
3823 }
3824 p->mfcr2call = 1;
3825 /* better safe than sorry ... */
3826 p->cid_name[0] = '\0';
3827 p->cid_num[0] = '\0';
3828 p->cid_subaddr[0] = '\0';
3829 p->rdnis[0] = '\0';
3830 p->exten[0] = '\0';
3831 p->mfcr2_ani_index = '\0';
3832 p->mfcr2_dnis_index = '\0';
3833 p->mfcr2_dnis_matched = 0;
3834 p->mfcr2_answer_pending = 0;
3835 p->mfcr2_call_accepted = 0;
3836 ast_mutex_unlock(&p->lock);
3837 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
3838 }
3839
3840 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
3841 {
3842 int res;
3843 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3844 ast_mutex_lock(&p->lock);
3845 p->inalarm = alarm ? 1 : 0;
3846 if (p->inalarm) {
3847 res = get_alarms(p);
3848 if (res == DAHDI_ALARM_NOTOPEN) {
3849 mfcr2_queue_for_destruction(p);
3850 }
3851 handle_alarms(p, res);
3852 } else {
3853 handle_clear_alarms(p);
3854 }
3855 ast_mutex_unlock(&p->lock);
3856 }
3857
3858 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
3859 {
3860 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3861
3862 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
3863 ast_mutex_lock(&p->lock);
3864 /* Disconnected? */
3865 if (errorcode == ENODEV) {
3866 struct dahdi_mfcr2 *r2link = p->mfcr2;
3867 p->mfcr2call = 0;
3868 if (r2link) {
3869 r2link->nodev = 1;
3870 }
3871 }
3872 ast_mutex_unlock(&p->lock);
3873 }
3874
3875 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
3876 {
3877 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3878 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
3879 if (p->owner) {
3880 ast_channel_hangupcause_set(p->owner, AST_CAUSE_PROTOCOL_ERROR);
3881 ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
3882 }
3883 ast_mutex_lock(&p->lock);
3884 p->mfcr2call = 0;
3885 ast_mutex_unlock(&p->lock);
3886 }
3887
3888 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
3889 {
3890 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
3891 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
3892 p->channel, openr2_proto_get_disconnect_string(cause));
3893 /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
3894 openr2_chan_set_idle(p->r2chan);
3895 ast_mutex_lock(&p->lock);
3896 p->mfcr2call = 0;
3897 ast_mutex_unlock(&p->lock);
3898 }
3899 }
3900
3901 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
3902 {
3903 struct dahdi_pvt *p;
3904 struct ast_channel *c;
3905 ast_callid callid = 0;
3906 int callid_created = ast_callid_threadstorage_auto(&callid);
3907 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
3908 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
3909 openr2_proto_get_category_string(category));
3910 p = openr2_chan_get_client_data(r2chan);
3911 /* if collect calls are not allowed and this is a collect call, reject it! */
3912 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
3913 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
3914 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
3915 goto dahdi_r2_on_call_offered_cleanup;
3916 }
3917 ast_mutex_lock(&p->lock);
3918 p->mfcr2_recvd_category = category;
3919 /* if we're not supposed to use CID, clear whatever we have */
3920 if (!p->use_callerid) {
3921 ast_debug(1, "No CID allowed in configuration, CID is being cleared!\n");
3922 p->cid_num[0] = 0;
3923 p->cid_name[0] = 0;
3924 }
3925 /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
3926 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
3927 ast_debug(1, "Setting exten => s because of immediate or 0 DNIS configured\n");
3928 p->exten[0] = 's';
3929 p->exten[1] = 0;
3930 }
3931 ast_mutex_unlock(&p->lock);
3932 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
3933 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
3934 p->channel, p->exten, p->context);
3935 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
3936 goto dahdi_r2_on_call_offered_cleanup;
3937 }
3938 if (!p->mfcr2_accept_on_offer) {
3939 /* The user wants us to start the PBX thread right away without accepting the call first */
3940 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, NULL, callid);
3941 if (c) {
3942 /* Done here, don't disable reading now since we still need to generate MF tones to accept
3943 the call or reject it and detect the tone off condition of the other end, all of this
3944 will be done in the PBX thread now */
3945 goto dahdi_r2_on_call_offered_cleanup;
3946 }
3947 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
3948 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
3949 } else if (p->mfcr2_charge_calls) {
3950 ast_debug(1, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
3951 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
3952 } else {
3953 ast_debug(1, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
3954 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
3955 }
3956
3957 dahdi_r2_on_call_offered_cleanup:
3958 ast_callid_threadstorage_auto_clean(callid, callid_created);
3959 }
3960
3961 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
3962 {
3963 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3964 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
3965 ast_mutex_lock(&p->lock);
3966 p->mfcr2call = 0;
3967 ast_mutex_unlock(&p->lock);
3968 }
3969
3970 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
3971 {
3972 struct dahdi_pvt *p = NULL;
3973 struct ast_channel *c = NULL;
3974 ast_callid callid = 0;
3975 int callid_created = ast_callid_threadstorage_auto(&callid);
3976 p = openr2_chan_get_client_data(r2chan);
3977 dahdi_ec_enable(p);
3978 p->mfcr2_call_accepted = 1;
3979 /* if it's an incoming call ... */
3980 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
3981 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
3982 /* If accept on offer is not set, it means at this point the PBX thread is already
3983 launched (was launched in the 'on call offered' handler) and therefore this callback
3984 is being executed already in the PBX thread rather than the monitor thread, don't launch
3985 any other thread, just disable the openr2 reading and answer the call if needed */
3986 if (!p->mfcr2_accept_on_offer) {
3987 openr2_chan_disable_read(r2chan);
3988 if (p->mfcr2_answer_pending) {
3989 ast_debug(1, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
3990 dahdi_r2_answer(p);
3991 }
3992 goto dahdi_r2_on_call_accepted_cleanup;
3993 }
3994 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, NULL, callid);
3995 if (c) {
3996 /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
3997 library to forget about it */
3998 openr2_chan_disable_read(r2chan);
3999 goto dahdi_r2_on_call_accepted_cleanup;
4000 }
4001 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
4002 /* failed to create the channel, bail out and report it as an out of order line */
4003 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
4004 goto dahdi_r2_on_call_accepted_cleanup;
4005 }
4006 /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
4007 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
4008 p->subs[SUB_REAL].needringing = 1;
4009 p->dialing = 0;
4010 /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
4011 openr2_chan_disable_read(r2chan);
4012
4013 dahdi_r2_on_call_accepted_cleanup:
4014 ast_callid_threadstorage_auto_clean(callid, callid_created);
4015 }
4016
4017 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
4018 {
4019 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4020 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
4021 p->subs[SUB_REAL].needanswer = 1;
4022 }
4023
4024 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
4025 {
4026 /*ast_debug(1, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
4027 }
4028
4029 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
4030 {
4031 switch (cause) {
4032 case OR2_CAUSE_BUSY_NUMBER:
4033 return AST_CAUSE_BUSY;
4034 case OR2_CAUSE_NETWORK_CONGESTION:
4035 return AST_CAUSE_CONGESTION;
4036 case OR2_CAUSE_OUT_OF_ORDER:
4037 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
4038 case OR2_CAUSE_UNALLOCATED_NUMBER:
4039 return AST_CAUSE_UNREGISTERED;
4040 case OR2_CAUSE_NO_ANSWER:
4041 return AST_CAUSE_NO_ANSWER;
4042 case OR2_CAUSE_NORMAL_CLEARING:
4043 return AST_CAUSE_NORMAL_CLEARING;
4044 case OR2_CAUSE_UNSPECIFIED:
4045 default:
4046 return AST_CAUSE_NOTDEFINED;
4047 }
4048 }
4049
4050 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
4051 {
4052 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4053 char cause_str[50];
4054 struct ast_control_pvt_cause_code *cause_code;
4055 int datalen = sizeof(*cause_code);
4056
4057 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
4058 ast_mutex_lock(&p->lock);
4059 if (!p->owner) {
4060 ast_mutex_unlock(&p->lock);
4061 /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
4062 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
4063 return;
4064 }
4065
4066 snprintf(cause_str, sizeof(cause_str), "R2 DISCONNECT (%s)", openr2_proto_get_disconnect_string(cause));
4067 datalen += strlen(cause_str);
4068 cause_code = ast_alloca(datalen);
4069 memset(cause_code, 0, datalen);
4070 cause_code->ast_cause = dahdi_r2_cause_to_ast_cause(cause);
4071 ast_copy_string(cause_code->chan_name, ast_channel_name(p->owner), AST_CHANNEL_NAME);
4072 ast_copy_string(cause_code->code, cause_str, datalen + 1 - sizeof(*cause_code));
4073 ast_queue_control_data(p->owner, AST_CONTROL_PVT_CAUSE_CODE, cause_code, datalen);
4074 ast_channel_hangupcause_hash_set(p->owner, cause_code, datalen);
4075 ast_channel_hangupcause_set(p->owner, cause_code->ast_cause);
4076
4077 /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
4078 be done in dahdi_hangup */
4079 if (ast_channel_state(p->owner) == AST_STATE_UP) {
4080 ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
4081 ast_mutex_unlock(&p->lock);
4082 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
4083 /* being the forward side we must report what happened to the call to whoever requested it */
4084 switch (cause) {
4085 case OR2_CAUSE_BUSY_NUMBER:
4086 p->subs[SUB_REAL].needbusy = 1;
4087 break;
4088 case OR2_CAUSE_NETWORK_CONGESTION:
4089 case OR2_CAUSE_OUT_OF_ORDER:
4090 case OR2_CAUSE_UNALLOCATED_NUMBER:
4091 case OR2_CAUSE_NO_ANSWER:
4092 case OR2_CAUSE_UNSPECIFIED:
4093 case OR2_CAUSE_NORMAL_CLEARING:
4094 p->subs[SUB_REAL].needcongestion = 1;
4095 break;
4096 default:
4097 ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
4098 }
4099 ast_mutex_unlock(&p->lock);
4100 } else {
4101 ast_mutex_unlock(&p->lock);
4102 /* being the backward side and not UP yet, we only need to request hangup */
4103 /* TODO: what about doing this same thing when were AST_STATE_UP? */
4104 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
4105 }
4106 }
4107
4108 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
4109 {
4110 switch (level) {
4111 case OR2_LOG_NOTICE:
4112 ast_verbose("%s", logmessage);
4113 break;
4114 case OR2_LOG_WARNING:
4115 ast_log(LOG_WARNING, "%s", logmessage);
4116 break;
4117 case OR2_LOG_ERROR:
4118 ast_log(LOG_ERROR, "%s", logmessage);
4119 break;
4120 case OR2_LOG_STACK_TRACE:
4121 case OR2_LOG_MF_TRACE:
4122 case OR2_LOG_CAS_TRACE:
4123 case OR2_LOG_DEBUG:
4124 case OR2_LOG_EX_DEBUG:
4125 ast_debug(1, "%s", logmessage);
4126 break;
4127 default:
4128 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
4129 ast_debug(1, "%s", logmessage);
4130 break;
4131 }
4132 }
4133
4134 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
4135 {
4136 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4137 ast_mutex_lock(&p->lock);
4138 p->remotelyblocked = 1;
4139 ast_mutex_unlock(&p->lock);
4140 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
4141 }
4142
4143 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
4144 {
4145 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4146 ast_mutex_lock(&p->lock);
4147 p->remotelyblocked = 0;
4148 ast_mutex_unlock(&p->lock);
4149 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
4150 }
4151
4152 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
4153 __attribute__((format (printf, 3, 0)));
4154 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
4155 {
4156 #define CONTEXT_TAG "Context - "
4157 char logmsg[256];
4158 char completemsg[sizeof(logmsg) * 2];
4159 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
4160 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
4161 dahdi_r2_write_log(level, completemsg);
4162 #undef CONTEXT_TAG
4163 }
4164
4165 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
4166 __attribute__((format (printf, 3, 0)));
4167 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
4168 {
4169 #define CHAN_TAG "Chan "
4170 char logmsg[256];
4171 char completemsg[sizeof(logmsg) * 2];
4172 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
4173 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
4174 dahdi_r2_write_log(level, completemsg);
4175 #undef CHAN_TAG
4176 }
4177
4178 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
4179 {
4180 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4181 /* if 'immediate' is set, let's stop requesting DNIS */
4182 if (p->immediate) {
4183 return 0;
4184 }
4185 p->exten[p->mfcr2_dnis_index] = digit;
4186 p->rdnis[p->mfcr2_dnis_index] = digit;
4187 p->mfcr2_dnis_index++;
4188 p->exten[p->mfcr2_dnis_index] = 0;
4189 p->rdnis[p->mfcr2_dnis_index] = 0;
4190 /* if the DNIS is a match and cannot match more, stop requesting DNIS */
4191 if ((p->mfcr2_dnis_matched ||
4192 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
4193 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
4194 return 0;
4195 }
4196 /* otherwise keep going */
4197 return 1;
4198 }
4199
4200 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
4201 {
4202 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4203 p->cid_num[p->mfcr2_ani_index] = digit;
4204 p->cid_name[p->mfcr2_ani_index] = digit;
4205 p->mfcr2_ani_index++;
4206 p->cid_num[p->mfcr2_ani_index] = 0;
4207 p->cid_name[p->mfcr2_ani_index] = 0;
4208 }
4209
4210 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
4211 {
4212 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
4213 }
4214
4215 static openr2_event_interface_t dahdi_r2_event_iface = {
4216 .on_call_init = dahdi_r2_on_call_init,
4217 .on_call_offered = dahdi_r2_on_call_offered,
4218 .on_call_accepted = dahdi_r2_on_call_accepted,
4219 .on_call_answered = dahdi_r2_on_call_answered,
4220 .on_call_disconnect = dahdi_r2_on_call_disconnect,
4221 .on_call_end = dahdi_r2_on_call_end,
4222 .on_call_read = dahdi_r2_on_call_read,
4223 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
4224 .on_os_error = dahdi_r2_on_os_error,
4225 .on_protocol_error = dahdi_r2_on_protocol_error,
4226 .on_line_blocked = dahdi_r2_on_line_blocked,
4227 .on_line_idle = dahdi_r2_on_line_idle,
4228 /* cast seems to be needed to get rid of the annoying warning regarding format attribute */
4229 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
4230 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
4231 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
4232 /* so far we do nothing with billing pulses */
4233 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
4234 };
4235
4236 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
4237 {
4238 return AST_ALAW(sample);
4239 }
4240
4241 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
4242 {
4243 return AST_LIN2A(sample);
4244 }
4245
4246 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
4247 dahdi_r2_alaw_to_linear,
4248 dahdi_r2_linear_to_alaw
4249 };
4250
4251 #endif /* HAVE_OPENR2 */
4252
4253 static void swap_subs(struct dahdi_pvt *p, int a, int b)
4254 {
4255 int tchan;
4256 int tinthreeway;
4257 struct ast_channel *towner;
4258
4259 ast_debug(1, "Swapping %d and %d\n", a, b);
4260
4261 tchan = p->subs[a].chan;
4262 towner = p->subs[a].owner;
4263 tinthreeway = p->subs[a].inthreeway;
4264
4265 p->subs[a].chan = p->subs[b].chan;
4266 p->subs[a].owner = p->subs[b].owner;
4267 p->subs[a].inthreeway = p->subs[b].inthreeway;
4268
4269 p->subs[b].chan = tchan;
4270 p->subs[b].owner = towner;
4271 p->subs[b].inthreeway = tinthreeway;
4272
4273 if (p->subs[a].owner)
4274 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
4275 if (p->subs[b].owner)
4276 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
4277 wakeup_sub(p, a);
4278 wakeup_sub(p, b);
4279 }
4280
4281 static int dahdi_open(char *fn)
4282 {
4283 int fd;
4284 int isnum;
4285 int chan = 0;
4286 int bs;
4287 int x;
4288 isnum = 1;
4289 for (x = 0; x < strlen(fn); x++) {
4290 if (!isdigit(fn[x])) {
4291 isnum = 0;
4292 break;
4293 }
4294 }
4295 if (isnum) {
4296 chan = atoi(fn);
4297 if (chan < 1) {
4298 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
4299 return -1;
4300 }
4301 fn = "/dev/dahdi/channel";
4302 }
4303 fd = open(fn, O_RDWR | O_NONBLOCK);
4304 if (fd < 0) {
4305 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
4306 return -1;
4307 }
4308 if (chan) {
4309 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
4310 x = errno;
4311 close(fd);
4312 errno = x;
4313 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
4314 return -1;
4315 }
4316 }
4317 bs = READ_SIZE;
4318 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
4319 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
4320 x = errno;
4321 close(fd);
4322 errno = x;
4323 return -1;
4324 }
4325 return fd;
4326 }
4327
4328 static void dahdi_close(int fd)
4329 {
4330 if (fd > 0)
4331 close(fd);
4332 }
4333
4334 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
4335 {
4336 dahdi_close(chan_pvt->subs[sub_num].dfd);
4337 chan_pvt->subs[sub_num].dfd = -1;
4338 }
4339
4340 #if defined(HAVE_PRI)
4341 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
4342 {
4343 dahdi_close(pri->pri.fds[fd_num]);
4344 pri->pri.fds[fd_num] = -1;
4345 }
4346 #endif /* defined(HAVE_PRI) */
4347
4348 #if defined(HAVE_SS7)
4349 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
4350 {
4351 dahdi_close(ss7->ss7.fds[fd_num]);
4352 ss7->ss7.fds[fd_num] = -1;
4353 }
4354 #endif /* defined(HAVE_SS7) */
4355
4356 static int dahdi_setlinear(int dfd, int linear)
4357 {
4358 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
4359 }
4360
4361
4362 static int alloc_sub(struct dahdi_pvt *p, int x)
4363 {
4364 struct dahdi_bufferinfo bi;
4365 int res;
4366 if (p->subs[x].dfd >= 0) {
4367 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
4368 return -1;
4369 }
4370
4371 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
4372 if (p->subs[x].dfd <= -1) {
4373 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
4374 return -1;
4375 }
4376
4377 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
4378 if (!res) {
4379 bi.txbufpolicy = p->buf_policy;
4380 bi.rxbufpolicy = p->buf_policy;
4381 bi.numbufs = p->buf_no;
4382 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
4383 if (res < 0) {
4384 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
4385 }
4386 } else
4387 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
4388
4389 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
4390 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
4391 dahdi_close_sub(p, x);
4392 p->subs[x].dfd = -1;
4393 return -1;
4394 }
4395 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
4396 return 0;
4397 }
4398
4399 static int unalloc_sub(struct dahdi_pvt *p, int x)
4400 {
4401 if (!x) {
4402 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
4403 return -1;
4404 }
4405 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
4406 dahdi_close_sub(p, x);
4407 p->subs[x].linear = 0;
4408 p->subs[x].chan = 0;
4409 p->subs[x].owner = NULL;
4410 p->subs[x].inthreeway = 0;
4411 p->polarity = POLARITY_IDLE;
4412 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
4413 return 0;
4414 }
4415
4416 static int digit_to_dtmfindex(char digit)
4417 {
4418 if (isdigit(digit))
4419 return DAHDI_TONE_DTMF_BASE + (digit - '0');
4420 else if (digit >= 'A' && digit <= 'D')
4421 return DAHDI_TONE_DTMF_A + (digit - 'A');
4422 else if (digit >= 'a' && digit <= 'd')
4423 return DAHDI_TONE_DTMF_A + (digit - 'a');
4424 else if (digit == '*')
4425 return DAHDI_TONE_DTMF_s;
4426 else if (digit == '#')
4427 return DAHDI_TONE_DTMF_p;
4428 else
4429 return -1;
4430 }
4431
4432 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
4433 {
4434 struct dahdi_pvt *pvt;
4435 int idx;
4436 int dtmf;
4437 int res;
4438
4439 pvt = ast_channel_tech_pvt(chan);
4440
4441 ast_mutex_lock(&pvt->lock);
4442
4443 idx = dahdi_get_index(chan, pvt, 0);
4444
4445 if ((idx != SUB_REAL) || !pvt->owner)
4446 goto out;
4447
4448 #ifdef HAVE_PRI
4449 switch (pvt->sig) {
4450 case SIG_PRI_LIB_HANDLE_CASES:
4451 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
4452 if (!res)
4453 goto out;
4454 break;
4455 default:
4456 break;
4457 }
4458 #endif
4459 dtmf = digit_to_dtmfindex(digit);
4460 if (dtmf == -1) {
4461 /* Not a valid DTMF digit */
4462 goto out;
4463 }
4464
4465 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
4466 char dial_str[] = { 'T', digit, '\0' };
4467
4468 res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
4469 if (!res) {
4470 pvt->dialing = 1;
4471 }
4472 } else {
4473 pvt->dialing = 1;
4474 pvt->begindigit = digit;
4475
4476 /* Flush the write buffer in DAHDI to start sending the digit immediately. */
4477 dtmf = DAHDI_FLUSH_WRITE;
4478 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &dtmf);
4479 if (res) {
4480 ast_log(LOG_WARNING, "Unable to flush the DAHDI write buffer to send DTMF on channel %d: %s\n",
4481 pvt->channel, strerror(errno));
4482 }
4483
4484 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
4485 ast_channel_name(chan), digit);
4486 }
4487
4488 out:
4489 ast_mutex_unlock(&pvt->lock);
4490
4491 return 0;
4492 }
4493
4494 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
4495 {
4496 struct dahdi_pvt *pvt;
4497 int res = 0;
4498 int idx;
4499 int x;
4500
4501 pvt = ast_channel_tech_pvt(chan);
4502
4503 ast_mutex_lock(&pvt->lock);
4504
4505 idx = dahdi_get_index(chan, pvt, 0);
4506
4507 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
4508 goto out;
4509
4510 #ifdef HAVE_PRI
4511 /* This means that the digit was already sent via PRI signalling */
4512 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
4513 goto out;
4514 }
4515 #endif
4516
4517 if (pvt->begindigit) {
4518 x = -1;
4519 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
4520 ast_channel_name(chan), digit);
4521 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
4522 pvt->dialing = 0;
4523 pvt->begindigit = 0;
4524 }
4525
4526 out:
4527 ast_mutex_unlock(&pvt->lock);
4528
4529 return res;
4530 }
4531
4532 static const char * const events[] = {
4533 "No event",
4534 "On hook",
4535 "Ring/Answered",
4536 "Wink/Flash",
4537 "Alarm",
4538 "No more alarm",
4539 "HDLC Abort",
4540 "HDLC Overrun",
4541 "HDLC Bad FCS",
4542 "Dial Complete",
4543 "Ringer On",
4544 "Ringer Off",
4545 "Hook Transition Complete",
4546 "Bits Changed",
4547 "Pulse Start",
4548 "Timer Expired",
4549 "Timer Ping",
4550 "Polarity Reversal",
4551 "Ring Begin",
4552 };
4553
4554 static struct {
4555 int alarm;
4556 char *name;
4557 } alarms[] = {
4558 { DAHDI_ALARM_RED, "Red Alarm" },
4559 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
4560 { DAHDI_ALARM_BLUE, "Blue Alarm" },
4561 { DAHDI_ALARM_RECOVER, "Recovering" },
4562 { DAHDI_ALARM_LOOPBACK, "Loopback" },
4563 { DAHDI_ALARM_NOTOPEN, "Not Open" },
4564 { DAHDI_ALARM_NONE, "None" },
4565 };
4566
4567 static char *alarm2str(int alm)
4568 {
4569 int x;
4570 for (x = 0; x < ARRAY_LEN(alarms); x++) {
4571 if (alarms[x].alarm & alm)
4572 return alarms[x].name;
4573 }
4574 return alm ? "Unknown Alarm" : "No Alarm";
4575 }
4576
4577 static const char *event2str(int event)
4578 {
4579 static char buf[256];
4580 if ((event > -1) && (event < (ARRAY_LEN(events))) )
4581 return events[event];
4582 sprintf(buf, "Event %d", event); /* safe */
4583 return buf;
4584 }
4585
4586 static char *dahdi_sig2str(int sig)
4587 {
4588 static char buf[256];
4589 switch (sig) {
4590 case SIG_EM:
4591 return "E & M Immediate";
4592 case SIG_EMWINK:
4593 return "E & M Wink";
4594 case SIG_EM_E1:
4595 return "E & M E1";
4596 case SIG_FEATD:
4597 return "Feature Group D (DTMF)";
4598 case SIG_FEATDMF:
4599 return "Feature Group D (MF)";
4600 case SIG_FEATDMF_TA:
4601 return "Feature Group D (MF) Tandem Access";
4602 case SIG_FEATB:
4603 return "Feature Group B (MF)";
4604 case SIG_E911:
4605 return "E911 (MF)";
4606 case SIG_FGC_CAMA:
4607 return "FGC/CAMA (Dialpulse)";
4608 case SIG_FGC_CAMAMF:
4609 return "FGC/CAMA (MF)";
4610 case SIG_FXSLS:
4611 return "FXS Loopstart";
4612 case SIG_FXSGS:
4613 return "FXS Groundstart";
4614 case SIG_FXSKS:
4615 return "FXS Kewlstart";
4616 case SIG_FXOLS:
4617 return "FXO Loopstart";
4618 case SIG_FXOGS:
4619 return "FXO Groundstart";
4620 case SIG_FXOKS:
4621 return "FXO Kewlstart";
4622 case SIG_PRI:
4623 return "ISDN PRI";
4624 case SIG_BRI:
4625 return "ISDN BRI Point to Point";
4626 case SIG_BRI_PTMP:
4627 return "ISDN BRI Point to MultiPoint";
4628 case SIG_SS7:
4629 return "SS7";
4630 case SIG_MFCR2:
4631 return "MFC/R2";
4632 case SIG_SF:
4633 return "SF (Tone) Immediate";
4634 case SIG_SFWINK:
4635 return "SF (Tone) Wink";
4636 case SIG_SF_FEATD:
4637 return "SF (Tone) with Feature Group D (DTMF)";
4638 case SIG_SF_FEATDMF:
4639 return "SF (Tone) with Feature Group D (MF)";
4640 case SIG_SF_FEATB:
4641 return "SF (Tone) with Feature Group B (MF)";
4642 case 0:
4643 return "Pseudo";
4644 default:
4645 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
4646 return buf;
4647 }
4648 }
4649
4650 #define sig2str dahdi_sig2str
4651
4652 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
4653 {
4654 /* If the conference already exists, and we're already in it
4655 don't bother doing anything */
4656 struct dahdi_confinfo zi;
4657
4658 memset(&zi, 0, sizeof(zi));
4659 zi.chan = 0;
4660
4661 if (slavechannel > 0) {
4662 /* If we have only one slave, do a digital mon */
4663 zi.confmode = DAHDI_CONF_DIGITALMON;
4664 zi.confno = slavechannel;
4665 } else {
4666 if (!idx) {
4667 /* Real-side and pseudo-side both participate in conference */
4668 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
4669 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
4670 } else
4671 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
4672 zi.confno = p->confno;
4673 }
4674 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
4675 return 0;
4676 if (c->dfd < 0)
4677 return 0;
4678 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4679 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
4680 return -1;
4681 }
4682 if (slavechannel < 1) {
4683 p->confno = zi.confno;
4684 }
4685 c->curconf = zi;
4686 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4687 return 0;
4688 }
4689
4690 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
4691 {
4692 /* If they're listening to our channel, they're ours */
4693 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
4694 return 1;
4695 /* If they're a talker on our (allocated) conference, they're ours */
4696 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
4697 return 1;
4698 return 0;
4699 }
4700
4701 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
4702 {
4703 struct dahdi_confinfo zi;
4704 if (/* Can't delete if there's no dfd */
4705 (c->dfd < 0) ||
4706 /* Don't delete from the conference if it's not our conference */
4707 !isourconf(p, c)
4708 /* Don't delete if we don't think it's conferenced at all (implied) */
4709 ) return 0;
4710 memset(&zi, 0, sizeof(zi));
4711 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4712 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
4713 return -1;
4714 }
4715 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4716 memcpy(&c->curconf, &zi, sizeof(c->curconf));
4717 return 0;
4718 }
4719
4720 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
4721 {
4722 int x;
4723 int useslavenative;
4724 struct dahdi_pvt *slave = NULL;
4725 /* Start out optimistic */
4726 useslavenative = 1;
4727 /* Update conference state in a stateless fashion */
4728 for (x = 0; x < 3; x++) {
4729 /* Any three-way calling makes slave native mode *definitely* out
4730 of the question */
4731 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
4732 useslavenative = 0;
4733 }
4734 /* If we don't have any 3-way calls, check to see if we have
4735 precisely one slave */
4736 if (useslavenative) {
4737 for (x = 0; x < MAX_SLAVES; x++) {
4738 if (p->slaves[x]) {
4739 if (slave) {
4740 /* Whoops already have a slave! No
4741 slave native and stop right away */
4742 slave = NULL;
4743 useslavenative = 0;
4744 break;
4745 } else {
4746 /* We have one slave so far */
4747 slave = p->slaves[x];
4748 }
4749 }
4750 }
4751 }
4752 /* If no slave, slave native definitely out */
4753 if (!slave)
4754 useslavenative = 0;
4755 else if (slave->law != p->law) {
4756 useslavenative = 0;
4757 slave = NULL;
4758 }
4759 if (out)
4760 *out = slave;
4761 return useslavenative;
4762 }
4763
4764 static int reset_conf(struct dahdi_pvt *p)
4765 {
4766 p->confno = -1;
4767 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
4768 if (p->subs[SUB_REAL].dfd > -1) {
4769 struct dahdi_confinfo zi;
4770
4771 memset(&zi, 0, sizeof(zi));
4772 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
4773 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
4774 }
4775 return 0;
4776 }
4777
4778 void dahdi_conf_update(struct dahdi_pvt *p)
4779 {
4780 int needconf = 0;
4781 int x;
4782 int useslavenative;
4783 struct dahdi_pvt *slave = NULL;
4784
4785 useslavenative = isslavenative(p, &slave);
4786 /* Start with the obvious, general stuff */
4787 for (x = 0; x < 3; x++) {
4788 /* Look for three way calls */
4789 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
4790 conf_add(p, &p->subs[x], x, 0);
4791 needconf++;
4792 } else {
4793 conf_del(p, &p->subs[x], x);
4794 }
4795 }
4796 /* If we have a slave, add him to our conference now. or DAX
4797 if this is slave native */
4798 for (x = 0; x < MAX_SLAVES; x++) {
4799 if (p->slaves[x]) {
4800 if (useslavenative)
4801 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
4802 else {
4803 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
4804 needconf++;
4805 }
4806 }
4807 }
4808 /* If we're supposed to be in there, do so now */
4809 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
4810 if (useslavenative)
4811 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
4812 else {
4813 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
4814 needconf++;
4815 }
4816 }
4817 /* If we have a master, add ourselves to his conference */
4818 if (p->master) {
4819 if (isslavenative(p->master, NULL)) {
4820 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
4821 } else {
4822 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
4823 }
4824 }
4825 if (!needconf) {
4826 /* Nobody is left (or should be left) in our conference.
4827 Kill it. */
4828 p->confno = -1;
4829 }
4830 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
4831 }
4832
4833 void dahdi_ec_enable(struct dahdi_pvt *p)
4834 {
4835 int res;
4836 if (!p)
4837 return;
4838 if (p->echocanon) {
4839 ast_debug(1, "Echo cancellation already on\n");
4840 return;
4841 }
4842 if (p->digital) {
4843 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
4844 return;
4845 }
4846 if (p->echocancel.head.tap_length) {
4847 #if defined(HAVE_PRI) || defined(HAVE_SS7)
4848 switch (p->sig) {
4849 #if defined(HAVE_PRI)
4850 case SIG_PRI_LIB_HANDLE_CASES:
4851 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
4852 /*
4853 * PRI nobch pseudo channel. Does not need ec anyway.
4854 * Does not handle ioctl(DAHDI_AUDIOMODE)
4855 */
4856 return;
4857 }
4858 /* Fall through */
4859 #endif /* defined(HAVE_PRI) */
4860 #if defined(HAVE_SS7)
4861 case SIG_SS7:
4862 #endif /* defined(HAVE_SS7) */
4863 {
4864 int x = 1;
4865
4866 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
4867 if (res)
4868 ast_log(LOG_WARNING,
4869 "Unable to enable audio mode on channel %d (%s)\n",
4870 p->channel, strerror(errno));
4871 }
4872 break;
4873 default:
4874 break;
4875 }
4876 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
4877 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
4878 if (res) {
4879 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
4880 } else {
4881 p->echocanon = 1;
4882 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
4883 }
4884 } else
4885 ast_debug(1, "No echo cancellation requested\n");
4886 }
4887
4888 static void dahdi_train_ec(struct dahdi_pvt *p)
4889 {
4890 int x;
4891 int res;
4892
4893 if (p && p->echocanon && p->echotraining) {
4894 x = p->echotraining;
4895 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
4896 if (res)
4897 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
4898 else
4899 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
4900 } else {
4901 ast_debug(1, "No echo training requested\n");
4902 }
4903 }
4904
4905 void dahdi_ec_disable(struct dahdi_pvt *p)
4906 {
4907 int res;
4908
4909 if (p->echocanon) {
4910 struct dahdi_echocanparams ecp = { .tap_length = 0 };
4911
4912 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
4913
4914 if (res)
4915 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
4916 else
4917 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
4918 }
4919
4920 p->echocanon = 0;
4921 }
4922
4923 static int set_hwgain(int fd, float gain, int tx_direction)
4924 {
4925 struct dahdi_hwgain hwgain;
4926
4927 hwgain.newgain = gain * 10.0;
4928 hwgain.tx = tx_direction;
4929 return ioctl(fd, DAHDI_SET_HWGAIN, &hwgain) < 0;
4930 }
4931
4932 /* perform a dynamic range compression transform on the given sample */
4933 static int drc_sample(int sample, float drc)
4934 {
4935 float neg;
4936 float shallow, steep;
4937 float max = SHRT_MAX;
4938
4939 neg = (sample < 0 ? -1 : 1);
4940 steep = drc*sample;
4941 shallow = neg*(max-max/drc)+(float)sample/drc;
4942 if (fabsf(steep) < fabsf(shallow)) {
4943 sample = steep;
4944 }
4945 else {
4946 sample = shallow;
4947 }
4948
4949 return sample;
4950 }
4951
4952
4953 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
4954 {
4955 int j;
4956 int k;
4957
4958 float linear_gain = pow(10.0, gain / 20.0);
4959
4960 switch (law) {
4961 case DAHDI_LAW_ALAW:
4962 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
4963 if (gain || drc) {
4964 k = AST_ALAW(j);
4965 if (drc) {
4966 k = drc_sample(k, drc);
4967 }
4968 k = (float)k * linear_gain;
4969 if (k > 32767) {
4970 k = 32767;
4971 } else if (k < -32768) {
4972 k = -32768;
4973 }
4974 g->txgain[j] = AST_LIN2A(k);
4975 } else {
4976 g->txgain[j] = j;
4977 }
4978 }
4979 break;
4980 case DAHDI_LAW_MULAW:
4981 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
4982 if (gain || drc) {
4983 k = AST_MULAW(j);
4984 if (drc) {
4985 k = drc_sample(k, drc);
4986 }
4987 k = (float)k * linear_gain;
4988 if (k > 32767) {
4989 k = 32767;
4990 } else if (k < -32768) {
4991 k = -32768;
4992 }
4993 g->txgain[j] = AST_LIN2MU(k);
4994
4995 } else {
4996 g->txgain[j] = j;
4997 }
4998 }
4999 break;
5000 }
5001 }
5002
5003 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
5004 {
5005 int j;
5006 int k;
5007 float linear_gain = pow(10.0, gain / 20.0);
5008
5009 switch (law) {
5010 case DAHDI_LAW_ALAW:
5011 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
5012 if (gain || drc) {
5013 k = AST_ALAW(j);
5014 if (drc) {
5015 k = drc_sample(k, drc);
5016 }
5017 k = (float)k * linear_gain;
5018 if (k > 32767) {
5019 k = 32767;
5020 } else if (k < -32768) {
5021 k = -32768;
5022 }
5023 g->rxgain[j] = AST_LIN2A(k);
5024 } else {
5025 g->rxgain[j] = j;
5026 }
5027 }
5028 break;
5029 case DAHDI_LAW_MULAW:
5030 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
5031 if (gain || drc) {
5032 k = AST_MULAW(j);
5033 if (drc) {
5034 k = drc_sample(k, drc);
5035 }
5036 k = (float)k * linear_gain;
5037 if (k > 32767) {
5038 k = 32767;
5039 } else if (k < -32768) {
5040 k = -32768;
5041 }
5042 g->rxgain[j] = AST_LIN2MU(k);
5043 } else {
5044 g->rxgain[j] = j;
5045 }
5046 }
5047 break;
5048 }
5049 }
5050
5051 static int set_actual_txgain(int fd, float gain, float drc, int law)
5052 {
5053 struct dahdi_gains g;
5054 int res;
5055
5056 memset(&g, 0, sizeof(g));
5057 res = ioctl(fd, DAHDI_GETGAINS, &g);
5058 if (res) {
5059 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
5060 return res;
5061 }
5062
5063 fill_txgain(&g, gain, drc, law);
5064
5065 return ioctl(fd, DAHDI_SETGAINS, &g);
5066 }
5067
5068 static int set_actual_rxgain(int fd, float gain, float drc, int law)
5069 {
5070 struct dahdi_gains g;
5071 int res;
5072
5073 memset(&g, 0, sizeof(g));
5074 res = ioctl(fd, DAHDI_GETGAINS, &g);
5075 if (res) {
5076 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
5077 return res;
5078 }
5079
5080 fill_rxgain(&g, gain, drc, law);
5081
5082 return ioctl(fd, DAHDI_SETGAINS, &g);
5083 }
5084
5085 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
5086 {
5087 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
5088 }
5089
5090 static int bump_gains(struct dahdi_pvt *p)
5091 {
5092 int res;
5093
5094 /* Bump receive gain by value stored in cid_rxgain */
5095 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5096 if (res) {
5097 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
5098 return -1;
5099 }
5100
5101 return 0;
5102 }
5103
5104 static int restore_gains(struct dahdi_pvt *p)
5105 {
5106 int res;
5107
5108 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5109 if (res) {
5110 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
5111 return -1;
5112 }
5113
5114 return 0;
5115 }
5116
5117 static inline int dahdi_set_hook(int fd, int hs)
5118 {
5119 int x, res;
5120
5121 x = hs;
5122 res = ioctl(fd, DAHDI_HOOK, &x);
5123
5124 if (res < 0) {
5125 if (errno == EINPROGRESS)
5126 return 0;
5127 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
5128 /* will expectedly fail if phone is off hook during operation, such as during a restart */
5129 }
5130
5131 return res;
5132 }
5133
5134 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
5135 {
5136 int x, res;
5137
5138 x = muted;
5139 #if defined(HAVE_PRI) || defined(HAVE_SS7)
5140 switch (p->sig) {
5141 #if defined(HAVE_PRI)
5142 case SIG_PRI_LIB_HANDLE_CASES:
5143 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
5144 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
5145 break;
5146 }
5147 /* Fall through */
5148 #endif /* defined(HAVE_PRI) */
5149 #if defined(HAVE_SS7)
5150 case SIG_SS7:
5151 #endif /* defined(HAVE_SS7) */
5152 {
5153 int y = 1;
5154
5155 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
5156 if (res)
5157 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
5158 p->channel, strerror(errno));
5159 }
5160 break;
5161 default:
5162 break;
5163 }
5164 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
5165 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
5166 if (res < 0)
5167 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
5168 return res;
5169 }
5170
5171 static int save_conference(struct dahdi_pvt *p)
5172 {
5173 struct dahdi_confinfo c;
5174 int res;
5175 if (p->saveconf.confmode) {
5176 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
5177 return -1;
5178 }
5179 p->saveconf.chan = 0;
5180 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
5181 if (res) {
5182 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
5183 p->saveconf.confmode = 0;
5184 return -1;
5185 }
5186 memset(&c, 0, sizeof(c));
5187 c.confmode = DAHDI_CONF_NORMAL;
5188 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
5189 if (res) {
5190 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
5191 return -1;
5192 }
5193 ast_debug(1, "Disabled conferencing\n");
5194 return 0;
5195 }
5196
5197 static int restore_conference(struct dahdi_pvt *p)
5198 {
5199 int res;
5200 if (p->saveconf.confmode) {
5201 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
5202 p->saveconf.confmode = 0;
5203 if (res) {
5204 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
5205 return -1;
5206 }
5207 ast_debug(1, "Restored conferencing\n");
5208 }
5209 return 0;
5210 }
5211
5212 static int send_cwcidspill(struct dahdi_pvt *p)
5213 {
5214 p->callwaitcas = 0;
5215 p->cidcwexpire = 0;
5216 p->cid_suppress_expire = 0;
5217 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
5218 return -1;
5219 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
5220 /* Make sure we account for the end */
5221 p->cidlen += READ_SIZE * 4;
5222 p->cidpos = 0;
5223 send_callerid(p);
5224 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
5225 return 0;
5226 }
5227
5228 static int has_voicemail(struct dahdi_pvt *p)
5229 {
5230 int new_msgs;
5231 RAII_VAR(struct stasis_message *, mwi_message, NULL, ao2_cleanup);
5232
5233 /* A manual MWI disposition has been requested, use that instead
5234 * if this is for sending the new MWI indication. */
5235 if (p->mwioverride_active) {
5236 /* We don't clear p->mwioverride_active automatically,
5237 * because otherwise do_monitor would just change it back to the way it was.
5238 * We need to keep the override active until explicitly disabled by the user,
5239 * so that we can keep returning the correct answer in subsequent calls to do_monitor. */
5240 ast_debug(6, "MWI manual override active on channel %d: pretending that it should be %s\n",
5241 p->channel, p->mwioverride_disposition ? "active" : "inactive");
5242 return p->mwioverride_disposition;
5243 }
5244
5245 mwi_message = stasis_cache_get(ast_mwi_state_cache(), ast_mwi_state_type(), p->mailbox);
5246 if (mwi_message) {
5247 struct ast_mwi_state *mwi_state = stasis_message_data(mwi_message);
5248 new_msgs = mwi_state->new_msgs;
5249 } else {
5250 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
5251 }
5252
5253 return new_msgs;
5254 }
5255
5256
5257
5258 static int send_callerid(struct dahdi_pvt *p)
5259 {
5260 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
5261 int res;
5262 /* Take out of linear mode if necessary */
5263 if (p->subs[SUB_REAL].linear) {
5264 p->subs[SUB_REAL].linear = 0;
5265 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
5266 }
5267 while (p->cidpos < p->cidlen) {
5268 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
5269 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
5270 if (res < 0) {
5271 if (errno == EAGAIN)
5272 return 0;
5273 else {
5274 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
5275 return -1;
5276 }
5277 }
5278 if (!res)
5279 return 0;
5280 p->cidpos += res;
5281 }
5282 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
5283 ast_free(p->cidspill);
5284 p->cidspill = NULL;
5285 if (p->callwaitcas) {
5286 /* Wait for CID/CW to expire */
5287 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
5288 p->cid_suppress_expire = p->cidcwexpire;
5289 } else
5290 restore_conference(p);
5291 return 0;
5292 }
5293
5294 static int dahdi_callwait(struct ast_channel *ast)
5295 {
5296 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5297
5298 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
5299 if (p->cidspill) {
5300 ast_log(LOG_WARNING, "Spill already exists?!?\n");
5301 ast_free(p->cidspill);
5302 }
5303
5304 /*
5305 * SAS: Subscriber Alert Signal, 440Hz for 300ms
5306 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
5307 */
5308 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
5309 return -1;
5310 save_conference(p);
5311 /* Silence */
5312 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
5313 if (!p->callwaitrings && p->callwaitingcallerid) {
5314 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
5315 p->callwaitcas = 1;
5316 p->cidlen = 2400 + 680 + READ_SIZE * 4;
5317 } else {
5318 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
5319 p->callwaitcas = 0;
5320 p->cidlen = 2400 + READ_SIZE * 4;
5321 }
5322 p->cidpos = 0;
5323 send_callerid(p);
5324
5325 return 0;
5326 }
5327
5328 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout)
5329 {
5330 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5331 int x, res, mysig;
5332 char *dest;
5333 AST_DECLARE_APP_ARGS(args,
5334 AST_APP_ARG(group); /* channel/group token */
5335 AST_APP_ARG(ext); /* extension token */
5336 //AST_APP_ARG(opts); /* options token */
5337 AST_APP_ARG(other); /* Any remining unused arguments */
5338 );
5339
5340 ast_mutex_lock(&p->lock);
5341 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
5342
5343 /* Split the dialstring */
5344 dest = ast_strdupa(rdest);
5345 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
5346 if (!args.ext) {
5347 args.ext = "";
5348 }
5349
5350 #if defined(HAVE_PRI)
5351 if (dahdi_sig_pri_lib_handles(p->sig)) {
5352 char *subaddr;
5353
5354 sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
5355
5356 /* Remove any subaddress for uniformity with incoming calls. */
5357 subaddr = strchr(p->exten, ':');
5358 if (subaddr) {
5359 *subaddr = '\0';
5360 }
5361 } else
5362 #endif /* defined(HAVE_PRI) */
5363 {
5364 ast_copy_string(p->exten, args.ext, sizeof(p->exten));
5365 }
5366
5367 if ((ast_channel_state(ast) == AST_STATE_BUSY)) {
5368 p->subs[SUB_REAL].needbusy = 1;
5369 ast_mutex_unlock(&p->lock);
5370 return 0;
5371 }
5372 if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
5373 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
5374 ast_mutex_unlock(&p->lock);
5375 return -1;
5376 }
5377 p->waitingfordt.tv_sec = 0;
5378 p->dialednone = 0;
5379 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
5380 {
5381 /* Special pseudo -- automatically up */
5382 ast_setstate(ast, AST_STATE_UP);
5383 ast_mutex_unlock(&p->lock);
5384 return 0;
5385 }
5386 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
5387 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
5388 if (res)
5389 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
5390 p->outgoing = 1;
5391
5392 if (IS_DIGITAL(ast_channel_transfercapability(ast))){
5393 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
5394 } else {
5395 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5396 }
5397
5398 #ifdef HAVE_PRI
5399 if (dahdi_sig_pri_lib_handles(p->sig)) {
5400 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
5401 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
5402 ast_mutex_unlock(&p->lock);
5403 return res;
5404 }
5405 #endif
5406
5407 #if defined(HAVE_SS7)
5408 if (p->sig == SIG_SS7) {
5409 res = sig_ss7_call(p->sig_pvt, ast, rdest);
5410 ast_mutex_unlock(&p->lock);
5411 return res;
5412 }
5413 #endif /* defined(HAVE_SS7) */
5414
5415 /* If this is analog signalling we can exit here */
5416 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
5417 p->callwaitrings = 0;
5418 res = analog_call(p->sig_pvt, ast, rdest, timeout);
5419 ast_mutex_unlock(&p->lock);
5420 return res;
5421 }
5422
5423 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
5424 switch (mysig) {
5425 case 0:
5426 /* Special pseudo -- automatically up*/
5427 ast_setstate(ast, AST_STATE_UP);
5428 break;
5429 case SIG_MFCR2:
5430 break;
5431 default:
5432 ast_debug(1, "not yet implemented\n");
5433 ast_mutex_unlock(&p->lock);
5434 return -1;
5435 }
5436
5437 #ifdef HAVE_OPENR2
5438 if (p->mfcr2) {
5439 openr2_calling_party_category_t chancat;
5440 int callres = 0;
5441 char *c, *l;
5442
5443 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
5444 p->dialdest[0] = '\0';
5445
5446 c = args.ext;
5447 if (!p->hidecallerid) {
5448 l = ast_channel_connected(ast)->id.number.valid ? ast_channel_connected(ast)->id.number.str : NULL;
5449 } else {
5450 l = NULL;
5451 }
5452 if (strlen(c) < p->stripmsd) {
5453 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
5454 ast_mutex_unlock(&p->lock);
5455 return -1;
5456 }
5457 p->dialing = 1;
5458 chancat = dahdi_r2_get_channel_category(ast);
5459 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
5460 if (-1 == callres) {
5461 ast_mutex_unlock(&p->lock);
5462 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
5463 return -1;
5464 }
5465 p->mfcr2_call_accepted = 0;
5466 p->mfcr2_progress_sent = 0;
5467 ast_setstate(ast, AST_STATE_DIALING);
5468 }
5469 #endif /* HAVE_OPENR2 */
5470 ast_mutex_unlock(&p->lock);
5471 return 0;
5472 }
5473
5474 /*!
5475 * \internal
5476 * \brief Insert the given chan_dahdi interface structure into the interface list.
5477 * \since 1.8
5478 *
5479 * \param pvt chan_dahdi private interface structure to insert.
5480 *
5481 * \details
5482 * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
5483 * Any duplicates are inserted after the existing entries.
5484 *
5485 * \note The new interface must not already be in the list.
5486 */
5487 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
5488 {
5489 struct dahdi_pvt *cur;
5490
5491 pvt->which_iflist = DAHDI_IFLIST_MAIN;
5492
5493 /* Find place in middle of list for the new interface. */
5494 for (cur = iflist; cur; cur = cur->next) {
5495 if (pvt->channel < cur->channel) {
5496 /* New interface goes before the current interface. */
5497 pvt->prev = cur->prev;
5498 pvt->next = cur;
5499 if (cur->prev) {
5500 /* Insert into the middle of the list. */
5501 cur->prev->next = pvt;
5502 } else {
5503 /* Insert at head of list. */
5504 iflist = pvt;
5505 }
5506 cur->prev = pvt;
5507 return;
5508 }
5509 }
5510
5511 /* New interface goes onto the end of the list */
5512 pvt->prev = ifend;
5513 pvt->next = NULL;
5514 if (ifend) {
5515 ifend->next = pvt;
5516 }
5517 ifend = pvt;
5518 if (!iflist) {
5519 /* List was empty */
5520 iflist = pvt;
5521 }
5522 }
5523
5524 /*!
5525 * \internal
5526 * \brief Extract the given chan_dahdi interface structure from the interface list.
5527 * \since 1.8
5528 *
5529 * \param pvt chan_dahdi private interface structure to extract.
5530 *
5531 * \note
5532 * The given interface structure can be either in the interface list or a stand alone
5533 * structure that has not been put in the list if the next and prev pointers are NULL.
5534 */
5535 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
5536 {
5537 /* Extract from the forward chain. */
5538 if (pvt->prev) {
5539 pvt->prev->next = pvt->next;
5540 } else if (iflist == pvt) {
5541 /* Node is at the head of the list. */
5542 iflist = pvt->next;
5543 }
5544
5545 /* Extract from the reverse chain. */
5546 if (pvt->next) {
5547 pvt->next->prev = pvt->prev;
5548 } else if (ifend == pvt) {
5549 /* Node is at the end of the list. */
5550 ifend = pvt->prev;
5551 }
5552
5553 /* Node is no longer in the list. */
5554 pvt->which_iflist = DAHDI_IFLIST_NONE;
5555 pvt->prev = NULL;
5556 pvt->next = NULL;
5557 }
5558
5559 #if defined(HAVE_PRI)
5560 /*!
5561 * \internal
5562 * \brief Insert the given chan_dahdi interface structure into the no B channel list.
5563 * \since 1.8
5564 *
5565 * \param pri sig_pri span control structure holding no B channel list.
5566 * \param pvt chan_dahdi private interface structure to insert.
5567 *
5568 * \details
5569 * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
5570 * Any duplicates are inserted after the existing entries.
5571 *
5572 * \note The new interface must not already be in the list.
5573 */
5574 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
5575 {
5576 struct dahdi_pvt *cur;
5577
5578 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
5579
5580 /* Find place in middle of list for the new interface. */
5581 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
5582 if (pvt->channel < cur->channel) {
5583 /* New interface goes before the current interface. */
5584 pvt->prev = cur->prev;
5585 pvt->next = cur;
5586 if (cur->prev) {
5587 /* Insert into the middle of the list. */
5588 cur->prev->next = pvt;
5589 } else {
5590 /* Insert at head of list. */
5591 pri->no_b_chan_iflist = pvt;
5592 }
5593 cur->prev = pvt;
5594 return;
5595 }
5596 }
5597
5598 /* New interface goes onto the end of the list */
5599 pvt->prev = pri->no_b_chan_end;
5600 pvt->next = NULL;
5601 if (pri->no_b_chan_end) {
5602 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
5603 }
5604 pri->no_b_chan_end = pvt;
5605 if (!pri->no_b_chan_iflist) {
5606 /* List was empty */
5607 pri->no_b_chan_iflist = pvt;
5608 }
5609 }
5610 #endif /* defined(HAVE_PRI) */
5611
5612 #if defined(HAVE_PRI)
5613 /*!
5614 * \internal
5615 * \brief Extract the given chan_dahdi interface structure from the no B channel list.
5616 * \since 1.8
5617 *
5618 * \param pri sig_pri span control structure holding no B channel list.
5619 * \param pvt chan_dahdi private interface structure to extract.
5620 *
5621 * \note
5622 * The given interface structure can be either in the interface list or a stand alone
5623 * structure that has not been put in the list if the next and prev pointers are NULL.
5624 */
5625 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
5626 {
5627 /* Extract from the forward chain. */
5628 if (pvt->prev) {
5629 pvt->prev->next = pvt->next;
5630 } else if (pri->no_b_chan_iflist == pvt) {
5631 /* Node is at the head of the list. */
5632 pri->no_b_chan_iflist = pvt->next;
5633 }
5634
5635 /* Extract from the reverse chain. */
5636 if (pvt->next) {
5637 pvt->next->prev = pvt->prev;
5638 } else if (pri->no_b_chan_end == pvt) {
5639 /* Node is at the end of the list. */
5640 pri->no_b_chan_end = pvt->prev;
5641 }
5642
5643 /* Node is no longer in the list. */
5644 pvt->which_iflist = DAHDI_IFLIST_NONE;
5645 pvt->prev = NULL;
5646 pvt->next = NULL;
5647 }
5648 #endif /* defined(HAVE_PRI) */
5649
5650 #if defined(HAVE_PRI)
5651 /*!
5652 * \internal
5653 * \brief Unlink the channel interface from the PRI private pointer array.
5654 * \since 1.8
5655 *
5656 * \param pvt chan_dahdi private interface structure to unlink.
5657 */
5658 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
5659 {
5660 unsigned idx;
5661 struct sig_pri_span *pri;
5662
5663 pri = pvt->pri;
5664 if (!pri) {
5665 /* Not PRI signaling so cannot be in a PRI private pointer array. */
5666 return;
5667 }
5668 ast_mutex_lock(&pri->lock);
5669 for (idx = 0; idx < pri->numchans; ++idx) {
5670 if (pri->pvts[idx] == pvt->sig_pvt) {
5671 pri->pvts[idx] = NULL;
5672 ast_mutex_unlock(&pri->lock);
5673 return;
5674 }
5675 }
5676 ast_mutex_unlock(&pri->lock);
5677 }
5678 #endif /* defined(HAVE_PRI) */
5679
5680 #if defined(HAVE_SS7)
5681 /*!
5682 * \internal
5683 * \brief Unlink the channel interface from the SS7 private pointer array.
5684 * \since 1.8
5685 *
5686 * \param pvt chan_dahdi private interface structure to unlink.
5687 */
5688 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
5689 {
5690 unsigned idx;
5691 struct sig_ss7_linkset *ss7;
5692
5693 ss7 = pvt->ss7;
5694 if (!ss7) {
5695 /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
5696 return;
5697 }
5698 ast_mutex_lock(&ss7->lock);
5699 for (idx = 0; idx < ss7->numchans; ++idx) {
5700 if (ss7->pvts[idx] == pvt->sig_pvt) {
5701 ss7->pvts[idx] = NULL;
5702 ast_mutex_unlock(&ss7->lock);
5703 return;
5704 }
5705 }
5706 ast_mutex_unlock(&ss7->lock);
5707 }
5708 #endif /* defined(HAVE_SS7) */
5709
5710 #if defined(HAVE_OPENR2)
5711 /*!
5712 * \internal
5713 * \brief Unlink the channel interface from the MFC/R2 private pointer array.
5714 *
5715 * \param pvt chan_dahdi private interface structure to unlink.
5716 */
5717 static void dahdi_unlink_mfcr2_pvt(struct dahdi_pvt *pvt)
5718 {
5719 unsigned idx;
5720 struct dahdi_mfcr2 *mfcr2;
5721 int should_destroy_link = 0;
5722
5723 ast_mutex_lock(&pvt->lock);
5724 if (pvt->r2chan) {
5725 ast_debug(1, "Disable MFC/R2 channel %d read\n", pvt->channel);
5726 openr2_chan_disable_read(pvt->r2chan);
5727 }
5728 mfcr2 = pvt->mfcr2;
5729 if (mfcr2) {
5730 for (idx = 0; idx < mfcr2->numchans; ++idx) {
5731 if (mfcr2->pvts[idx] == pvt) {
5732 ast_debug(1, "Removing MFC/R2 channel %d from the mfcr2 link\n", pvt->channel);
5733 mfcr2->pvts[idx] = NULL;
5734 mfcr2->live_chans--;
5735 break;
5736 }
5737 }
5738 if (!mfcr2->live_chans) {
5739 ast_debug(1, "MFC/R2 link is now empty\n");
5740 should_destroy_link = 1;
5741 }
5742 }
5743 ast_mutex_unlock(&pvt->lock);
5744 if (should_destroy_link) {
5745 ast_debug(1, "MFC/R2 link is now empty\n");
5746 mfcr2_queue_for_destruction(pvt);
5747 }
5748 }
5749 #endif /* defined(HAVE_OPENR2) */
5750
5751 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
5752 {
5753 if (cur->next && cur->next->span == cur->span) {
5754 return cur->next;
5755 } else if (cur->prev && cur->prev->span == cur->span) {
5756 return cur->prev;
5757 }
5758
5759 return NULL;
5760 }
5761
5762 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
5763 {
5764 struct dahdi_pvt *p = pvt;
5765
5766 if (p->manages_span_alarms) {
5767 struct dahdi_pvt *next = find_next_iface_in_span(p);
5768 if (next) {
5769 next->manages_span_alarms = 1;
5770 }
5771 }
5772
5773 /* Remove channel from the list */
5774 #if defined(HAVE_PRI)
5775 dahdi_unlink_pri_pvt(p);
5776 #endif /* defined(HAVE_PRI) */
5777 #if defined(HAVE_SS7)
5778 dahdi_unlink_ss7_pvt(p);
5779 #endif /* defined(HAVE_SS7) */
5780 #if defined(HAVE_OPENR2)
5781 dahdi_unlink_mfcr2_pvt(p);
5782 #endif /* defined(HAVE_SS7) */
5783 switch (pvt->which_iflist) {
5784 case DAHDI_IFLIST_NONE:
5785 break;
5786 case DAHDI_IFLIST_MAIN:
5787 dahdi_iflist_extract(p);
5788 break;
5789 #if defined(HAVE_PRI)
5790 case DAHDI_IFLIST_NO_B_CHAN:
5791 if (p->pri) {
5792 dahdi_nobch_extract(p->pri, p);
5793 }
5794 break;
5795 #endif /* defined(HAVE_PRI) */
5796 }
5797
5798 if (p->sig_pvt) {
5799 if (dahdi_analog_lib_handles(p->sig, 0, 0)) {
5800 analog_delete(p->sig_pvt);
5801 }
5802 switch (p->sig) {
5803 #if defined(HAVE_PRI)
5804 case SIG_PRI_LIB_HANDLE_CASES:
5805 sig_pri_chan_delete(p->sig_pvt);
5806 break;
5807 #endif /* defined(HAVE_PRI) */
5808 #if defined(HAVE_SS7)
5809 case SIG_SS7:
5810 sig_ss7_chan_delete(p->sig_pvt);
5811 break;
5812 #endif /* defined(HAVE_SS7) */
5813 default:
5814 break;
5815 }
5816 }
5817 ast_free(p->cidspill);
5818 if (p->use_smdi) {
5819 ao2_cleanup(p->smdi_iface);
5820 }
5821 if (p->mwi_event_sub) {
5822 p->mwi_event_sub = ast_mwi_unsubscribe(p->mwi_event_sub);
5823 }
5824 if (p->vars) {
5825 ast_variables_destroy(p->vars);
5826 }
5827 if (p->cc_params) {
5828 ast_cc_config_params_destroy(p->cc_params);
5829 }
5830
5831 p->named_callgroups = ast_unref_namedgroups(p->named_callgroups);
5832 p->named_pickupgroups = ast_unref_namedgroups(p->named_pickupgroups);
5833
5834 ast_mutex_destroy(&p->lock);
5835 dahdi_close_sub(p, SUB_REAL);
5836 if (p->owner) {
5837 ast_channel_tech_pvt_set(p->owner, NULL);
5838 }
5839 ast_free(p);
5840 }
5841
5842 static void destroy_channel(struct dahdi_pvt *cur, int now)
5843 {
5844 int i;
5845
5846 if (!now) {
5847 /* Do not destroy the channel now if it is owned by someone. */
5848 if (cur->owner) {
5849 return;
5850 }
5851 for (i = 0; i < 3; i++) {
5852 if (cur->subs[i].owner) {
5853 return;
5854 }
5855 }
5856 }
5857 destroy_dahdi_pvt(cur);
5858 }
5859
5860 static void destroy_all_channels(void)
5861 {
5862 int chan;
5863 #if defined(HAVE_PRI)
5864 unsigned span;
5865 struct sig_pri_span *pri;
5866 #endif /* defined(HAVE_PRI) */
5867 struct dahdi_pvt *p;
5868
5869 while (num_restart_pending) {
5870 usleep(1);
5871 }
5872
5873 ast_mutex_lock(&iflock);
5874 /* Destroy all the interfaces and free their memory */
5875 while (iflist) {
5876 p = iflist;
5877
5878 chan = p->channel;
5879 #if defined(HAVE_PRI_SERVICE_MESSAGES)
5880 {
5881 char db_chan_name[20];
5882 char db_answer[5];
5883 char state;
5884 int why = -1;
5885
5886 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
5887 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
5888 sscanf(db_answer, "%1c:%30d", &state, &why);
5889 }
5890 if (!why) {
5891 /* SRVST persistence is not required */
5892 ast_db_del(db_chan_name, SRVST_DBKEY);
5893 }
5894 }
5895 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
5896 /* Free associated memory */
5897 destroy_dahdi_pvt(p);
5898 ast_verb(3, "Unregistered channel %d\n", chan);
5899 }
5900 ifcount = 0;
5901 ast_mutex_unlock(&iflock);
5902
5903 #if defined(HAVE_PRI)
5904 /* Destroy all of the no B channel interface lists */
5905 for (span = 0; span < NUM_SPANS; ++span) {
5906 if (!pris[span].dchannels[0]) {
5907 break;
5908 }
5909 pri = &pris[span].pri;
5910 ast_mutex_lock(&pri->lock);
5911 while (pri->no_b_chan_iflist) {
5912 p = pri->no_b_chan_iflist;
5913
5914 /* Free associated memory */
5915 destroy_dahdi_pvt(p);
5916 }
5917 ast_mutex_unlock(&pri->lock);
5918 }
5919 #endif /* defined(HAVE_PRI) */
5920 }
5921
5922 #if defined(HAVE_PRI)
5923 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
5924
5925 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
5926 {
5927 /* Data will be our digit string */
5928 struct dahdi_pvt *p;
5929
5930 if (ast_strlen_zero(digits)) {
5931 ast_debug(1, "No digit string sent to application!\n");
5932 return -1;
5933 }
5934
5935 p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
5936
5937 if (!p) {
5938 ast_debug(1, "Unable to find technology private\n");
5939 return -1;
5940 }
5941
5942 pri_send_keypad_facility_exec(p->sig_pvt, digits);
5943
5944 return 0;
5945 }
5946 #endif /* defined(HAVE_PRI) */
5947
5948 #if defined(HAVE_PRI)
5949 #if defined(HAVE_PRI_PROG_W_CAUSE)
5950 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
5951
5952 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
5953 {
5954 /* Data will be our digit string */
5955 struct dahdi_pvt *pvt;
5956 char *parse;
5957 int res;
5958 AST_DECLARE_APP_ARGS(args,
5959 AST_APP_ARG(destination);
5960 AST_APP_ARG(original);
5961 AST_APP_ARG(reason);
5962 );
5963
5964 if (ast_strlen_zero(data)) {
5965 ast_debug(1, "No data sent to application!\n");
5966 return -1;
5967 }
5968 if (ast_channel_tech(chan) != &dahdi_tech) {
5969 ast_debug(1, "Only DAHDI technology accepted!\n");
5970 return -1;
5971 }
5972 pvt = (struct dahdi_pvt *) ast_channel_tech_pvt(chan);
5973 if (!pvt) {
5974 ast_debug(1, "Unable to find technology private\n");
5975 return -1;
5976 }
5977 switch (pvt->sig) {
5978 case SIG_PRI_LIB_HANDLE_CASES:
5979 break;
5980 default:
5981 ast_debug(1, "callrerouting attempted on non-ISDN channel %s\n",
5982 ast_channel_name(chan));
5983 return -1;
5984 }
5985
5986 parse = ast_strdupa(data);
5987 AST_STANDARD_APP_ARGS(args, parse);
5988
5989 if (ast_strlen_zero(args.destination)) {
5990 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
5991 return -1;
5992 }
5993
5994 if (ast_strlen_zero(args.original)) {
5995 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
5996 args.original = NULL;
5997 }
5998
5999 if (ast_strlen_zero(args.reason)) {
6000 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
6001 args.reason = NULL;
6002 }
6003
6004 res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, ast_channel_state(chan),
6005 args.destination, args.original, args.reason);
6006 if (!res) {
6007 /*
6008 * Wait up to 5 seconds for a reply before hanging up this call
6009 * leg if the peer does not disconnect first.
6010 */
6011 ast_safe_sleep(chan, 5000);
6012 }
6013
6014 return -1;
6015 }
6016 #endif /* defined(HAVE_PRI_PROG_W_CAUSE) */
6017 #endif /* defined(HAVE_PRI) */
6018
6019 #if defined(HAVE_OPENR2)
6020 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
6021
6022 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
6023 {
6024 /* data is whether to accept with charge or no charge */
6025 openr2_call_mode_t accept_mode;
6026 int res, timeout, maxloops;
6027 struct ast_frame *f;
6028 struct dahdi_pvt *p;
6029 char *parse;
6030 AST_DECLARE_APP_ARGS(args,
6031 AST_APP_ARG(charge);
6032 );
6033
6034 if (ast_strlen_zero(data)) {
6035 ast_debug(1, "No data sent to application!\n");
6036 return -1;
6037 }
6038
6039 if (ast_channel_tech(chan) != &dahdi_tech) {
6040 ast_debug(1, "Only DAHDI technology accepted!\n");
6041 return -1;
6042 }
6043
6044 p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
6045 if (!p) {
6046 ast_debug(1, "Unable to find technology private!\n");
6047 return -1;
6048 }
6049
6050 parse = ast_strdupa(data);
6051 AST_STANDARD_APP_ARGS(args, parse);
6052
6053 if (ast_strlen_zero(args.charge)) {
6054 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
6055 return -1;
6056 }
6057
6058 ast_mutex_lock(&p->lock);
6059 if (!p->mfcr2 || !p->mfcr2call) {
6060 ast_mutex_unlock(&p->lock);
6061 ast_debug(1, "Channel %s does not seems to be an R2 active channel!\n", ast_channel_name(chan));
6062 return -1;
6063 }
6064
6065 if (p->mfcr2_call_accepted) {
6066 ast_mutex_unlock(&p->lock);
6067 ast_debug(1, "MFC/R2 call already accepted on channel %s!\n", ast_channel_name(chan));
6068 return 0;
6069 }
6070 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
6071 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
6072 ast_mutex_unlock(&p->lock);
6073 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
6074 return -1;
6075 }
6076 ast_mutex_unlock(&p->lock);
6077
6078 res = 0;
6079 timeout = 100;
6080 maxloops = 50; /* wait up to 5 seconds */
6081 /* we need to read() until the call is accepted */
6082 while (maxloops > 0) {
6083 maxloops--;
6084 if (ast_check_hangup(chan)) {
6085 break;
6086 }
6087 res = ast_waitfor(chan, timeout);
6088 if (res < 0) {
6089 ast_debug(1, "ast_waitfor failed on channel %s, going out ...\n", ast_channel_name(chan));
6090 res = -1;
6091 break;
6092 }
6093 if (res == 0) {
6094 continue;
6095 }
6096 res = 0;
6097 f = ast_read(chan);
6098 if (!f) {
6099 ast_debug(1, "No frame read on channel %s, going out ...\n", ast_channel_name(chan));
6100 res = -1;
6101 break;
6102 }
6103 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
6104 ast_debug(1, "Got HANGUP frame on channel %s, going out ...\n", ast_channel_name(chan));
6105 ast_frfree(f);
6106 res = -1;
6107 break;
6108 }
6109 ast_frfree(f);
6110 ast_mutex_lock(&p->lock);
6111 if (p->mfcr2_call_accepted) {
6112 ast_mutex_unlock(&p->lock);
6113 ast_debug(1, "Accepted MFC/R2 call!\n");
6114 break;
6115 }
6116 ast_mutex_unlock(&p->lock);
6117 }
6118 if (res == -1) {
6119 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
6120 }
6121 return res;
6122 }
6123
6124 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
6125 {
6126 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
6127 switch (cause) {
6128 case AST_CAUSE_USER_BUSY:
6129 case AST_CAUSE_CALL_REJECTED:
6130 case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
6131 r2cause = OR2_CAUSE_BUSY_NUMBER;
6132 break;
6133
6134 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
6135 case AST_CAUSE_SWITCH_CONGESTION:
6136 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
6137 break;
6138
6139 case AST_CAUSE_UNALLOCATED:
6140 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
6141 break;
6142
6143 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
6144 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
6145 r2cause = OR2_CAUSE_OUT_OF_ORDER;
6146 break;
6147
6148 case AST_CAUSE_NO_ANSWER:
6149 case AST_CAUSE_NO_USER_RESPONSE:
6150 r2cause = OR2_CAUSE_NO_ANSWER;
6151 break;
6152
6153 default:
6154 r2cause = OR2_CAUSE_NORMAL_CLEARING;
6155 break;
6156 }
6157 ast_debug(1, "ast cause %d resulted in openr2 cause %d/%s\n",
6158 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
6159 return r2cause;
6160 }
6161 #endif
6162
6163 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
6164 {
6165 if (p->bufferoverrideinuse) {
6166 /* faxbuffers are in use, revert them */
6167 struct dahdi_bufferinfo bi = {
6168 .txbufpolicy = p->buf_policy,
6169 .rxbufpolicy = p->buf_policy,
6170 .bufsize = p->bufsize,
6171 .numbufs = p->buf_no
6172 };
6173 int bpres;
6174
6175 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
6176 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast_channel_name(ast), strerror(errno));
6177 }
6178 p->bufferoverrideinuse = 0;
6179 return bpres;
6180 }
6181
6182 return -1;
6183 }
6184
6185 static int dahdi_hangup(struct ast_channel *ast)
6186 {
6187 int res = 0;
6188 int idx,x;
6189 int law;
6190 /*static int restore_gains(struct dahdi_pvt *p);*/
6191 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
6192 struct dahdi_params par;
6193
6194 ast_debug(1, "dahdi_hangup(%s)\n", ast_channel_name(ast));
6195 if (!ast_channel_tech_pvt(ast)) {
6196 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
6197 return 0;
6198 }
6199
6200 ast_mutex_lock(&p->lock);
6201 p->exten[0] = '\0';
6202 /* Always use sig_analog hangup handling for operator mode */
6203 if (dahdi_analog_lib_handles(p->sig, p->radio, 0)) {
6204 p->oprmode = 0;
6205 dahdi_confmute(p, 0);
6206 restore_gains(p);
6207 p->ignoredtmf = 0;
6208 p->waitingfordt.tv_sec = 0;
6209
6210 res = analog_hangup(p->sig_pvt, ast);
6211 revert_fax_buffers(p, ast);
6212
6213 goto hangup_out;
6214 } else {
6215 p->cid_num[0] = '\0';
6216 p->cid_name[0] = '\0';
6217 p->cid_subaddr[0] = '\0';
6218 }
6219
6220 #if defined(HAVE_PRI)
6221 if (dahdi_sig_pri_lib_handles(p->sig)) {
6222 x = 1;
6223 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6224
6225 dahdi_confmute(p, 0);
6226 p->muting = 0;
6227 restore_gains(p);
6228 if (p->dsp) {
6229 ast_dsp_free(p->dsp);
6230 p->dsp = NULL;
6231 }
6232 p->ignoredtmf = 0;
6233
6234 /* Real channel, do some fixup */
6235 p->subs[SUB_REAL].owner = NULL;
6236 p->subs[SUB_REAL].needbusy = 0;
6237 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
6238
6239 p->owner = NULL;
6240 p->cid_tag[0] = '\0';
6241 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */
6242 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
6243 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
6244 p->outgoing = 0;
6245 p->digital = 0;
6246 p->faxhandled = 0;
6247 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
6248
6249 revert_fax_buffers(p, ast);
6250
6251 p->law = p->law_default;
6252 law = p->law_default;
6253 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6254 if (res < 0) {
6255 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
6256 p->channel, strerror(errno));
6257 }
6258
6259 sig_pri_hangup(p->sig_pvt, ast);
6260
6261 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6262 dahdi_ec_disable(p);
6263
6264 x = 0;
6265 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
6266 p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
6267
6268 p->rdnis[0] = '\0';
6269 dahdi_conf_update(p);
6270 reset_conf(p);
6271
6272 /* Restore data mode */
6273 x = 0;
6274 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6275
6276 if (num_restart_pending == 0) {
6277 restart_monitor();
6278 }
6279 goto hangup_out;
6280 }
6281 #endif /* defined(HAVE_PRI) */
6282
6283 #if defined(HAVE_SS7)
6284 if (p->sig == SIG_SS7) {
6285 x = 1;
6286 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6287
6288 dahdi_confmute(p, 0);
6289 p->muting = 0;
6290 restore_gains(p);
6291 if (p->dsp) {
6292 ast_dsp_free(p->dsp);
6293 p->dsp = NULL;
6294 }
6295 p->ignoredtmf = 0;
6296
6297 /* Real channel, do some fixup */
6298 p->subs[SUB_REAL].owner = NULL;
6299 p->subs[SUB_REAL].needbusy = 0;
6300 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
6301
6302 p->owner = NULL;
6303 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */
6304 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
6305 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
6306 p->outgoing = 0;
6307 p->digital = 0;
6308 p->faxhandled = 0;
6309 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
6310
6311 revert_fax_buffers(p, ast);
6312
6313 p->law = p->law_default;
6314 law = p->law_default;
6315 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6316 if (res < 0) {
6317 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
6318 p->channel, strerror(errno));
6319 }
6320
6321 sig_ss7_hangup(p->sig_pvt, ast);
6322
6323 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6324 dahdi_ec_disable(p);
6325
6326 x = 0;
6327 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
6328 p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
6329
6330 dahdi_conf_update(p);
6331 reset_conf(p);
6332
6333 /* Restore data mode */
6334 x = 0;
6335 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6336
6337 if (num_restart_pending == 0) {
6338 restart_monitor();
6339 }
6340 goto hangup_out;
6341 }
6342 #endif /* defined(HAVE_SS7) */
6343
6344 idx = dahdi_get_index(ast, p, 1);
6345
6346 dahdi_confmute(p, 0);
6347 p->muting = 0;
6348 restore_gains(p);
6349 if (p->origcid_num) {
6350 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
6351 ast_free(p->origcid_num);
6352 p->origcid_num = NULL;
6353 }
6354 if (p->origcid_name) {
6355 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
6356 ast_free(p->origcid_name);
6357 p->origcid_name = NULL;
6358 }
6359 if (p->dsp)
6360 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
6361
6362 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
6363 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
6364 p->ignoredtmf = 0;
6365
6366 if (idx > -1) {
6367 /* Real channel, do some fixup */
6368 p->subs[idx].owner = NULL;
6369 p->subs[idx].needanswer = 0;
6370 p->subs[idx].needflash = 0;
6371 p->subs[idx].needringing = 0;
6372 p->subs[idx].needbusy = 0;
6373 p->subs[idx].needcongestion = 0;
6374 p->subs[idx].linear = 0;
6375 p->polarity = POLARITY_IDLE;
6376 dahdi_setlinear(p->subs[idx].dfd, 0);
6377 if (idx == SUB_REAL) {
6378 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
6379 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
6380 if (p->subs[SUB_CALLWAIT].inthreeway) {
6381 /* We had flipped over to answer a callwait and now it's gone */
6382 ast_debug(1, "We were flipped over to the callwait, moving back and not owning.\n");
6383 /* Move to the call-wait, but un-own us until they flip back. */
6384 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
6385 unalloc_sub(p, SUB_CALLWAIT);
6386 p->owner = NULL;
6387 } else {
6388 /* The three way hung up, but we still have a call wait */
6389 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
6390 swap_subs(p, SUB_THREEWAY, SUB_REAL);
6391 unalloc_sub(p, SUB_THREEWAY);
6392 if (p->subs[SUB_REAL].inthreeway) {
6393 /* This was part of a three way call. Immediately make way for
6394 another call */
6395 ast_debug(1, "Call was complete, setting owner to former third call\n");
6396 p->owner = p->subs[SUB_REAL].owner;
6397 } else {
6398 /* This call hasn't been completed yet... Set owner to NULL */
6399 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
6400 p->owner = NULL;
6401 }
6402 p->subs[SUB_REAL].inthreeway = 0;
6403 }
6404 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
6405 /* Move to the call-wait and switch back to them. */
6406 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
6407 unalloc_sub(p, SUB_CALLWAIT);
6408 p->owner = p->subs[SUB_REAL].owner;
6409 if (ast_channel_state(p->owner) != AST_STATE_UP)
6410 p->subs[SUB_REAL].needanswer = 1;
6411 ast_queue_unhold(p->subs[SUB_REAL].owner);
6412 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
6413 swap_subs(p, SUB_THREEWAY, SUB_REAL);
6414 unalloc_sub(p, SUB_THREEWAY);
6415 if (p->subs[SUB_REAL].inthreeway) {
6416 /* This was part of a three way call. Immediately make way for
6417 another call */
6418 ast_debug(1, "Call was complete, setting owner to former third call\n");
6419 p->owner = p->subs[SUB_REAL].owner;
6420 } else {
6421 /* This call hasn't been completed yet... Set owner to NULL */
6422 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
6423 p->owner = NULL;
6424 }
6425 p->subs[SUB_REAL].inthreeway = 0;
6426 }
6427 } else if (idx == SUB_CALLWAIT) {
6428 /* Ditch the holding callwait call, and immediately make it availabe */
6429 if (p->subs[SUB_CALLWAIT].inthreeway) {
6430 /* This is actually part of a three way, placed on hold. Place the third part
6431 on music on hold now */
6432 if (p->subs[SUB_THREEWAY].owner) {
6433 ast_queue_hold(p->subs[SUB_THREEWAY].owner, p->mohsuggest);
6434 }
6435 p->subs[SUB_THREEWAY].inthreeway = 0;
6436 /* Make it the call wait now */
6437 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
6438 unalloc_sub(p, SUB_THREEWAY);
6439 } else
6440 unalloc_sub(p, SUB_CALLWAIT);
6441 } else if (idx == SUB_THREEWAY) {
6442 if (p->subs[SUB_CALLWAIT].inthreeway) {
6443 /* The other party of the three way call is currently in a call-wait state.
6444 Start music on hold for them, and take the main guy out of the third call */
6445 if (p->subs[SUB_CALLWAIT].owner) {
6446 ast_queue_hold(p->subs[SUB_CALLWAIT].owner, p->mohsuggest);
6447 }
6448 p->subs[SUB_CALLWAIT].inthreeway = 0;
6449 }
6450 p->subs[SUB_REAL].inthreeway = 0;
6451 /* If this was part of a three way call index, let us make
6452 another three way call */
6453 unalloc_sub(p, SUB_THREEWAY);
6454 } else {
6455 /* This wasn't any sort of call, but how are we an index? */
6456 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
6457 }
6458 }
6459
6460 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
6461 p->owner = NULL;
6462 p->ringt = 0;
6463 p->distinctivering = 0;
6464 p->confirmanswer = 0;
6465 p->outgoing = 0;
6466 p->digital = 0;
6467 p->faxhandled = 0;
6468 p->pulsedial = 0;
6469 if (p->dsp) {
6470 ast_dsp_free(p->dsp);
6471 p->dsp = NULL;
6472 }
6473
6474 revert_fax_buffers(p, ast);
6475
6476 p->law = p->law_default;
6477 law = p->law_default;
6478 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6479 if (res < 0)
6480 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
6481 /* Perform low level hangup if no owner left */
6482 #ifdef HAVE_OPENR2
6483 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
6484 ast_debug(1, "disconnecting MFC/R2 call on chan %d\n", p->channel);
6485 /* If it's an incoming call, check the mfcr2_forced_release setting */
6486 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
6487 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
6488 } else {
6489 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
6490 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
6491 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
6492 : dahdi_ast_cause_to_r2_cause(ast_channel_hangupcause(ast));
6493 dahdi_r2_disconnect_call(p, r2cause);
6494 }
6495 } else if (p->mfcr2call) {
6496 ast_debug(1, "Clearing call request on channel %d\n", p->channel);
6497 /* since ast_request() was called but not ast_call() we have not yet dialed
6498 and the openr2 stack will not call on_call_end callback, we need to unset
6499 the mfcr2call flag and bump the monitor count so the monitor thread can take
6500 care of this channel events from now on */
6501 p->mfcr2call = 0;
6502 }
6503 #endif
6504 switch (p->sig) {
6505 case SIG_SS7:
6506 case SIG_MFCR2:
6507 case SIG_PRI_LIB_HANDLE_CASES:
6508 case 0:
6509 break;
6510 default:
6511 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6512 break;
6513 }
6514 if (res < 0) {
6515 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast_channel_name(ast));
6516 }
6517 switch (p->sig) {
6518 case SIG_FXOGS:
6519 case SIG_FXOLS:
6520 case SIG_FXOKS:
6521 memset(&par, 0, sizeof(par));
6522 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
6523 if (!res) {
6524 struct analog_pvt *analog_p = p->sig_pvt;
6525 #if 0
6526 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
6527 #endif
6528 /* If they're off hook, try playing congestion */
6529 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
6530 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6531 else
6532 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6533 analog_p->fxsoffhookstate = par.rxisoffhook;
6534 }
6535 break;
6536 case SIG_FXSGS:
6537 case SIG_FXSLS:
6538 case SIG_FXSKS:
6539 /* Make sure we're not made available for at least two seconds assuming
6540 we were actually used for an inbound or outbound call. */
6541 if (ast_channel_state(ast) != AST_STATE_RESERVED) {
6542 time(&p->guardtime);
6543 p->guardtime += 2;
6544 }
6545 break;
6546 default:
6547 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6548 break;
6549 }
6550 if (p->sig)
6551 dahdi_ec_disable(p);
6552 x = 0;
6553 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
6554 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
6555 p->didtdd = 0;
6556 p->callwaitcas = 0;
6557 p->callwaiting = p->permcallwaiting;
6558 p->hidecallerid = p->permhidecallerid;
6559 p->waitingfordt.tv_sec = 0;
6560 p->dialing = 0;
6561 p->rdnis[0] = '\0';
6562 dahdi_conf_update(p);
6563 reset_conf(p);
6564 /* Restore data mode */
6565 switch (p->sig) {
6566 case SIG_PRI_LIB_HANDLE_CASES:
6567 case SIG_SS7:
6568 x = 0;
6569 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
6570 break;
6571 default:
6572 break;
6573 }
6574 if (num_restart_pending == 0)
6575 restart_monitor();
6576 }
6577
6578 p->callwaitingrepeat = 0;
6579 p->cidcwexpire = 0;
6580 p->cid_suppress_expire = 0;
6581 p->oprmode = 0;
6582 hangup_out:
6583 ast_channel_tech_pvt_set(ast, NULL);
6584 ast_free(p->cidspill);
6585 p->cidspill = NULL;
6586
6587 if (p->reoriginate && p->sig == SIG_FXOKS && dahdi_analog_lib_handles(p->sig, p->radio, 0)) {
6588 /* Automatic reorigination: if all calls towards a user have hung up,
6589 * give dial tone again, so user doesn't need to cycle the hook state manually. */
6590 if (my_is_off_hook(p) && !p->owner) {
6591 /* 2 important criteria: channel must be off-hook, with no calls remaining (no owner) */
6592 ast_debug(1, "Queuing reorigination for channel %d\n", p->channel);
6593 my_play_tone(p, SUB_REAL, -1); /* Stop any congestion tone that may be present. */
6594 /* Must wait for the loop disconnect to end.
6595 * Sadly, these definitions are in dahdi/kernel.h, not dahdi/user.h
6596 * Calling usleep on an active DAHDI channel is a no-no, but this is okay.
6597 */
6598 usleep(800000); /* DAHDI_KEWLTIME + DAHDI_AFTERKEWLTIME */
6599 /* If the line is still off-hook and ownerless, actually queue the reorigination.
6600 * do_monitor will actually go ahead and do it. */
6601 if (!p->owner && my_is_off_hook(p)) {
6602 p->doreoriginate = 1; /* Tell do_monitor to reoriginate this channel */
6603 /* Note, my_off_hook will fail if called before the loop disconnect has finished
6604 * (important for FXOKS signaled channels). This is because DAHDI will reject
6605 * DAHDI_OFFHOOK while the channel is in TXSTATE_KEWL or TXSTATE_AFTERKEWL,
6606 * so we have to wait for that to finish (see comment above).
6607 * do_monitor itself cannot block, so make the blocking usleep call
6608 * here in the channel thread instead.
6609 */
6610 my_off_hook(p); /* Now, go ahead and take the channel back off hook (sig_analog put it on hook) */
6611 } else {
6612 ast_debug(1, "Channel %d is no longer eligible for reorigination (went back on hook or became in use)\n", p->channel);
6613 }
6614 }
6615 }
6616
6617 ast_mutex_unlock(&p->lock);
6618 ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast));
6619
6620 ast_mutex_lock(&iflock);
6621 if (p->restartpending) {
6622 num_restart_pending--;
6623 }
6624
6625 if (p->destroy) {
6626 destroy_channel(p, 0);
6627 }
6628 ast_mutex_unlock(&iflock);
6629
6630 ast_module_unref(ast_module_info->self);
6631 return 0;
6632 }
6633
6634 static int dahdi_answer(struct ast_channel *ast)
6635 {
6636 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
6637 int res = 0;
6638 int idx;
6639 ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
6640 ast_mutex_lock(&p->lock);
6641 idx = dahdi_get_index(ast, p, 0);
6642 if (idx < 0)
6643 idx = SUB_REAL;
6644 /* nothing to do if a radio channel */
6645 if ((p->radio || (p->oprmode < 0))) {
6646 ast_mutex_unlock(&p->lock);
6647 return 0;
6648 }
6649
6650 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
6651 res = analog_answer(p->sig_pvt, ast);
6652 ast_mutex_unlock(&p->lock);
6653 return res;
6654 }
6655
6656 switch (p->sig) {
6657 #if defined(HAVE_PRI)
6658 case SIG_PRI_LIB_HANDLE_CASES:
6659 res = sig_pri_answer(p->sig_pvt, ast);
6660 break;
6661 #endif /* defined(HAVE_PRI) */
6662 #if defined(HAVE_SS7)
6663 case SIG_SS7:
6664 res = sig_ss7_answer(p->sig_pvt, ast);
6665 break;
6666 #endif /* defined(HAVE_SS7) */
6667 #ifdef HAVE_OPENR2
6668 case SIG_MFCR2:
6669 if (!p->mfcr2_call_accepted) {
6670 /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
6671 openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
6672 p->mfcr2_answer_pending = 1;
6673 if (p->mfcr2_charge_calls) {
6674 ast_debug(1, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
6675 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
6676 } else {
6677 ast_debug(1, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
6678 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
6679 }
6680 } else {
6681 ast_debug(1, "Answering MFC/R2 call on chan %d\n", p->channel);
6682 dahdi_r2_answer(p);
6683 }
6684 break;
6685 #endif
6686 case 0:
6687 ast_mutex_unlock(&p->lock);
6688 return 0;
6689 default:
6690 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
6691 res = -1;
6692 break;
6693 }
6694 ast_mutex_unlock(&p->lock);
6695 return res;
6696 }
6697
6698 void dahdi_dtmf_detect_disable(struct dahdi_pvt *p)
6699 {
6700 int val = 0;
6701
6702 p->ignoredtmf = 1;
6703
6704 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
6705
6706 if (!p->hardwaredtmf && p->dsp) {
6707 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
6708 ast_dsp_set_features(p->dsp, p->dsp_features);
6709 }
6710 }
6711
6712 void dahdi_dtmf_detect_enable(struct dahdi_pvt *p)
6713 {
6714 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
6715
6716 if (p->channel == CHAN_PSEUDO)
6717 return;
6718
6719 p->ignoredtmf = 0;
6720
6721 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
6722
6723 if (!p->hardwaredtmf && p->dsp) {
6724 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
6725 ast_dsp_set_features(p->dsp, p->dsp_features);
6726 }
6727 }
6728
6729 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
6730 {
6731 char *cp;
6732 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
6733
6734 /* all supported options require data */
6735 if (!p || !data || (*datalen < 1)) {
6736 errno = EINVAL;
6737 return -1;
6738 }
6739
6740 switch (option) {
6741 case AST_OPTION_TDD:
6742 cp = (char *) data;
6743 if (p->mate) {
6744 *cp = 2;
6745 } else {
6746 *cp = p->tdd ? 1 : 0;
6747 }
6748 break;
6749 case AST_OPTION_DIGIT_DETECT:
6750 cp = (char *) data;
6751 *cp = p->ignoredtmf ? 0 : 1;
6752 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
6753 break;
6754 case AST_OPTION_FAX_DETECT:
6755 cp = (char *) data;
6756 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
6757 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
6758 break;
6759 case AST_OPTION_CC_AGENT_TYPE:
6760 #if defined(HAVE_PRI)
6761 #if defined(HAVE_PRI_CCSS)
6762 if (dahdi_sig_pri_lib_handles(p->sig)) {
6763 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
6764 break;
6765 }
6766 #endif /* defined(HAVE_PRI_CCSS) */
6767 #endif /* defined(HAVE_PRI) */
6768 return -1;
6769 default:
6770 return -1;
6771 }
6772
6773 errno = 0;
6774
6775 return 0;
6776 }
6777
6778 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
6779 {
6780 char *cp;
6781 signed char *scp;
6782 int x;
6783 int idx;
6784 struct dahdi_pvt *p = ast_channel_tech_pvt(chan), *pp;
6785 struct oprmode *oprmode;
6786
6787
6788 /* all supported options require data */
6789 if (!p || !data || (datalen < 1)) {
6790 errno = EINVAL;
6791 return -1;
6792 }
6793
6794 switch (option) {
6795 case AST_OPTION_TXGAIN:
6796 scp = (signed char *) data;
6797 idx = dahdi_get_index(chan, p, 0);
6798 if (idx < 0) {
6799 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
6800 return -1;
6801 }
6802 ast_debug(1, "Setting actual tx gain on %s to %f\n", ast_channel_name(chan), p->txgain + (float) *scp);
6803 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
6804 case AST_OPTION_RXGAIN:
6805 scp = (signed char *) data;
6806 idx = dahdi_get_index(chan, p, 0);
6807 if (idx < 0) {
6808 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
6809 return -1;
6810 }
6811 ast_debug(1, "Setting actual rx gain on %s to %f\n", ast_channel_name(chan), p->rxgain + (float) *scp);
6812 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
6813 case AST_OPTION_TONE_VERIFY:
6814 if (!p->dsp)
6815 break;
6816 cp = (char *) data;
6817 switch (*cp) {
6818 case 1:
6819 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",ast_channel_name(chan));
6820 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
6821 break;
6822 case 2:
6823 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",ast_channel_name(chan));
6824 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
6825 break;
6826 default:
6827 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",ast_channel_name(chan));
6828 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
6829 break;
6830 }
6831 break;
6832 case AST_OPTION_TDD:
6833 /* turn on or off TDD */
6834 cp = (char *) data;
6835 p->mate = 0;
6836 if (!*cp) { /* turn it off */
6837 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",ast_channel_name(chan));
6838 if (p->tdd)
6839 tdd_free(p->tdd);
6840 p->tdd = 0;
6841 break;
6842 }
6843 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
6844 (*cp == 2) ? "MATE" : "ON", (int) *cp, ast_channel_name(chan));
6845 dahdi_ec_disable(p);
6846 /* otherwise, turn it on */
6847 if (!p->didtdd) { /* if havent done it yet */
6848 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
6849 unsigned char *buf;
6850 int size, res, fd, len;
6851 struct pollfd fds[1];
6852
6853 buf = mybuf;
6854 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
6855 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */
6856 len = 40000;
6857 idx = dahdi_get_index(chan, p, 0);
6858 if (idx < 0) {
6859 ast_log(LOG_WARNING, "No index in TDD?\n");
6860 return -1;
6861 }
6862 fd = p->subs[idx].dfd;
6863 while (len) {
6864 if (ast_check_hangup(chan))
6865 return -1;
6866 size = len;
6867 if (size > READ_SIZE)
6868 size = READ_SIZE;
6869 fds[0].fd = fd;
6870 fds[0].events = POLLPRI | POLLOUT;
6871 fds[0].revents = 0;
6872 res = poll(fds, 1, -1);
6873 if (!res) {
6874 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
6875 continue;
6876 }
6877 /* if got exception */
6878 if (fds[0].revents & POLLPRI)
6879 return -1;
6880 if (!(fds[0].revents & POLLOUT)) {
6881 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
6882 continue;
6883 }
6884 res = write(fd, buf, size);
6885 if (res != size) {
6886 if (res == -1) return -1;
6887 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
6888 break;
6889 }
6890 len -= size;
6891 buf += size;
6892 }
6893 p->didtdd = 1; /* set to have done it now */
6894 }
6895 if (*cp == 2) { /* Mate mode */
6896 if (p->tdd)
6897 tdd_free(p->tdd);
6898 p->tdd = 0;
6899 p->mate = 1;
6900 break;
6901 }
6902 if (!p->tdd) { /* if we don't have one yet */
6903 p->tdd = tdd_new(); /* allocate one */
6904 }
6905 break;
6906 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
6907 if (!p->dsp)
6908 break;
6909 cp = (char *) data;
6910 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
6911 *cp ? "ON" : "OFF", (int) *cp, ast_channel_name(chan));
6912 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
6913 break;
6914 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
6915 #if defined(HAVE_PRI)
6916 if (dahdi_sig_pri_lib_handles(p->sig)
6917 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
6918 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
6919 break;
6920 }
6921 #endif /* defined(HAVE_PRI) */
6922
6923 cp = (char *) data;
6924 if (!*cp) {
6925 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", ast_channel_name(chan));
6926 x = 0;
6927 dahdi_ec_disable(p);
6928 } else {
6929 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", ast_channel_name(chan));
6930 x = 1;
6931 }
6932 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
6933 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
6934 break;
6935 case AST_OPTION_OPRMODE: /* Operator services mode */
6936 oprmode = (struct oprmode *) data;
6937 /* We don't support operator mode across technologies */
6938 if (strcasecmp(ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type)) {
6939 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
6940 ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type);
6941 errno = EINVAL;
6942 return -1;
6943 }
6944 pp = ast_channel_tech_pvt(oprmode->peer);
6945 p->oprmode = pp->oprmode = 0;
6946 /* setup peers */
6947 p->oprpeer = pp;
6948 pp->oprpeer = p;
6949 /* setup modes, if any */
6950 if (oprmode->mode)
6951 {
6952 pp->oprmode = oprmode->mode;
6953 p->oprmode = -oprmode->mode;
6954 }
6955 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
6956 oprmode->mode, ast_channel_name(chan),ast_channel_name(oprmode->peer));
6957 break;
6958 case AST_OPTION_ECHOCAN:
6959 cp = (char *) data;
6960 if (*cp) {
6961 ast_debug(1, "Enabling echo cancellation on %s\n", ast_channel_name(chan));
6962 dahdi_ec_enable(p);
6963 } else {
6964 ast_debug(1, "Disabling echo cancellation on %s\n", ast_channel_name(chan));
6965 dahdi_ec_disable(p);
6966 }
6967 break;
6968 case AST_OPTION_DIGIT_DETECT:
6969 cp = (char *) data;
6970 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
6971 if (*cp) {
6972 dahdi_dtmf_detect_enable(p);
6973 } else {
6974 dahdi_dtmf_detect_disable(p);
6975 }
6976 break;
6977 case AST_OPTION_FAX_DETECT:
6978 cp = (char *) data;
6979 if (p->dsp) {
6980 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
6981 if (*cp) {
6982 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
6983 } else {
6984 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
6985 }
6986 ast_dsp_set_features(p->dsp, p->dsp_features);
6987 }
6988 break;
6989 default:
6990 return -1;
6991 }
6992 errno = 0;
6993
6994 return 0;
6995 }
6996
6997 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
6998 {
6999 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
7000 int res = 0;
7001
7002 if (!p) {
7003 /* No private structure! */
7004 *buf = '\0';
7005 return -1;
7006 }
7007
7008 if (!strcasecmp(data, "rxgain")) {
7009 ast_mutex_lock(&p->lock);
7010 snprintf(buf, len, "%f", p->rxgain);
7011 ast_mutex_unlock(&p->lock);
7012 } else if (!strcasecmp(data, "txgain")) {
7013 ast_mutex_lock(&p->lock);
7014 snprintf(buf, len, "%f", p->txgain);
7015 ast_mutex_unlock(&p->lock);
7016 } else if (!strcasecmp(data, "dahdi_channel")) {
7017 ast_mutex_lock(&p->lock);
7018 snprintf(buf, len, "%d", p->channel);
7019 ast_mutex_unlock(&p->lock);
7020 } else if (!strcasecmp(data, "dahdi_span")) {
7021 ast_mutex_lock(&p->lock);
7022 snprintf(buf, len, "%d", p->span);
7023 ast_mutex_unlock(&p->lock);
7024 } else if (!strcasecmp(data, "dahdi_group")) {
7025 ast_mutex_lock(&p->lock);
7026 snprintf(buf, len, "%llu", p->group);
7027 ast_mutex_unlock(&p->lock);
7028 } else if (!strcasecmp(data, "dahdi_type")) {
7029 ast_mutex_lock(&p->lock);
7030 switch (p->sig) {
7031 #if defined(HAVE_OPENR2)
7032 case SIG_MFCR2:
7033 ast_copy_string(buf, "mfc/r2", len);
7034 break;
7035 #endif /* defined(HAVE_OPENR2) */
7036 #if defined(HAVE_PRI)
7037 case SIG_PRI_LIB_HANDLE_CASES:
7038 ast_copy_string(buf, "pri", len);
7039 break;
7040 #endif /* defined(HAVE_PRI) */
7041 case 0:
7042 ast_copy_string(buf, "pseudo", len);
7043 break;
7044 #if defined(HAVE_SS7)
7045 case SIG_SS7:
7046 ast_copy_string(buf, "ss7", len);
7047 break;
7048 #endif /* defined(HAVE_SS7) */
7049 default:
7050 /* The only thing left is analog ports. */
7051 ast_copy_string(buf, "analog", len);
7052 break;
7053 }
7054 ast_mutex_unlock(&p->lock);
7055 #if defined(HAVE_PRI)
7056 #if defined(HAVE_PRI_REVERSE_CHARGE)
7057 } else if (!strcasecmp(data, "reversecharge")) {
7058 ast_mutex_lock(&p->lock);
7059 switch (p->sig) {
7060 case SIG_PRI_LIB_HANDLE_CASES:
7061 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
7062 break;
7063 default:
7064 *buf = '\0';
7065 res = -1;
7066 break;
7067 }
7068 ast_mutex_unlock(&p->lock);
7069 #endif
7070 #if defined(HAVE_PRI_SETUP_KEYPAD)
7071 } else if (!strcasecmp(data, "keypad_digits")) {
7072 ast_mutex_lock(&p->lock);
7073 switch (p->sig) {
7074 case SIG_PRI_LIB_HANDLE_CASES:
7075 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
7076 len);
7077 break;
7078 default:
7079 *buf = '\0';
7080 res = -1;
7081 break;
7082 }
7083 ast_mutex_unlock(&p->lock);
7084 #endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
7085 } else if (!strcasecmp(data, "no_media_path")) {
7086 ast_mutex_lock(&p->lock);
7087 switch (p->sig) {
7088 case SIG_PRI_LIB_HANDLE_CASES:
7089 /*
7090 * TRUE if the call is on hold or is call waiting because
7091 * there is no media path available.
7092 */
7093 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
7094 break;
7095 default:
7096 *buf = '\0';
7097 res = -1;
7098 break;
7099 }
7100 ast_mutex_unlock(&p->lock);
7101 #endif /* defined(HAVE_PRI) */
7102 } else if (!strcasecmp(data, "dialmode")) {
7103 struct analog_pvt *analog_p;
7104 ast_mutex_lock(&p->lock);
7105 analog_p = p->sig_pvt;
7106 /* Hardcode p->radio and p->oprmode as 0 since we're using this to check for analogness, not the handler */
7107 if (dahdi_analog_lib_handles(p->sig, 0, 0) && analog_p) {
7108 switch (analog_p->dialmode) {
7109 case ANALOG_DIALMODE_BOTH:
7110 ast_copy_string(buf, "both", len);
7111 break;
7112 case ANALOG_DIALMODE_PULSE:
7113 ast_copy_string(buf, "pulse", len);
7114 break;
7115 case ANALOG_DIALMODE_DTMF:
7116 ast_copy_string(buf, "dtmf", len);
7117 break;
7118 case ANALOG_DIALMODE_NONE:
7119 ast_copy_string(buf, "none", len);
7120 break;
7121 }
7122 } else {
7123 ast_log(LOG_WARNING, "%s only supported on analog channels\n", data);
7124 *buf = '\0';
7125 res = -1;
7126 }
7127 ast_mutex_unlock(&p->lock);
7128 } else {
7129 *buf = '\0';
7130 res = -1;
7131 }
7132
7133 return res;
7134 }
7135
7136
7137 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
7138 {
7139 int res;
7140 char policy_str[21] = "";
7141
7142 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
7143 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
7144 return 1;
7145 }
7146 if (*num_buffers < 0) {
7147 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
7148 return -1;
7149 }
7150 if (!strcasecmp(policy_str, "full")) {
7151 *policy = DAHDI_POLICY_WHEN_FULL;
7152 } else if (!strcasecmp(policy_str, "immediate")) {
7153 *policy = DAHDI_POLICY_IMMEDIATE;
7154 #if defined(HAVE_DAHDI_HALF_FULL)
7155 } else if (!strcasecmp(policy_str, "half")) {
7156 *policy = DAHDI_POLICY_HALF_FULL;
7157 #endif
7158 } else {
7159 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
7160 return -1;
7161 }
7162
7163 return 0;
7164 }
7165
7166 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
7167 {
7168 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
7169 int res = 0;
7170
7171 if (!p) {
7172 /* No private structure! */
7173 return -1;
7174 }
7175
7176 if (!strcasecmp(data, "buffers")) {
7177 int num_bufs, policy;
7178
7179 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
7180 struct dahdi_bufferinfo bi = {
7181 .txbufpolicy = policy,
7182 .rxbufpolicy = policy,
7183 .bufsize = p->bufsize,
7184 .numbufs = num_bufs,
7185 };
7186 int bpres;
7187
7188 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
7189 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
7190 } else {
7191 p->bufferoverrideinuse = 1;
7192 }
7193 } else {
7194 res = -1;
7195 }
7196 } else if (!strcasecmp(data, "echocan_mode")) {
7197 if (!strcasecmp(value, "on")) {
7198 ast_mutex_lock(&p->lock);
7199 dahdi_ec_enable(p);
7200 ast_mutex_unlock(&p->lock);
7201 } else if (!strcasecmp(value, "off")) {
7202 ast_mutex_lock(&p->lock);
7203 dahdi_ec_disable(p);
7204 ast_mutex_unlock(&p->lock);
7205 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
7206 } else if (!strcasecmp(value, "fax")) {
7207 int blah = 1;
7208
7209 ast_mutex_lock(&p->lock);
7210 if (!p->echocanon) {
7211 dahdi_ec_enable(p);
7212 }
7213 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
7214 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
7215 }
7216 ast_mutex_unlock(&p->lock);
7217 } else if (!strcasecmp(value, "voice")) {
7218 int blah = 0;
7219
7220 ast_mutex_lock(&p->lock);
7221 if (!p->echocanon) {
7222 dahdi_ec_enable(p);
7223 }
7224 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
7225 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
7226 }
7227 ast_mutex_unlock(&p->lock);
7228 #endif
7229 } else {
7230 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
7231 res = -1;
7232 }
7233 } else if (!strcasecmp(data, "dialmode")) {
7234 struct analog_pvt *analog_p;
7235
7236 ast_mutex_lock(&p->lock);
7237 analog_p = p->sig_pvt;
7238 if (!dahdi_analog_lib_handles(p->sig, 0, 0) || !analog_p) {
7239 ast_log(LOG_WARNING, "%s only supported on analog channels\n", data);
7240 ast_mutex_unlock(&p->lock);
7241 return -1;
7242 }
7243 /* analog pvt is used for pulse dialing, so update both */
7244 if (!strcasecmp(value, "pulse")) {
7245 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_PULSE;
7246 } else if (!strcasecmp(value, "dtmf") || !strcasecmp(value, "tone")) {
7247 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_DTMF;
7248 } else if (!strcasecmp(value, "none")) {
7249 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_NONE;
7250 } else if (!strcasecmp(value, "both")) {
7251 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_BOTH;
7252 } else {
7253 ast_log(LOG_WARNING, "'%s' is an invalid setting for %s\n", value, data);
7254 res = -1;
7255 }
7256 ast_mutex_unlock(&p->lock);
7257 } else {
7258 res = -1;
7259 }
7260
7261 return res;
7262 }
7263
7264 void dahdi_master_slave_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
7265 {
7266 /* Unlink a specific slave or all slaves/masters from a given master */
7267 int x;
7268 int hasslaves;
7269 if (!master)
7270 return;
7271 if (needlock) {
7272 ast_mutex_lock(&master->lock);
7273 if (slave) {
7274 while (ast_mutex_trylock(&slave->lock)) {
7275 DEADLOCK_AVOIDANCE(&master->lock);
7276 }
7277 }
7278 }
7279 hasslaves = 0;
7280 for (x = 0; x < MAX_SLAVES; x++) {
7281 if (master->slaves[x]) {
7282 if (!slave || (master->slaves[x] == slave)) {
7283 /* Take slave out of the conference */
7284 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
7285 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
7286 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
7287 master->slaves[x]->master = NULL;
7288 master->slaves[x] = NULL;
7289 } else
7290 hasslaves = 1;
7291 }
7292 if (!hasslaves)
7293 master->inconference = 0;
7294 }
7295 if (!slave) {
7296 if (master->master) {
7297 /* Take master out of the conference */
7298 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
7299 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
7300 hasslaves = 0;
7301 for (x = 0; x < MAX_SLAVES; x++) {
7302 if (master->master->slaves[x] == master)
7303 master->master->slaves[x] = NULL;
7304 else if (master->master->slaves[x])
7305 hasslaves = 1;
7306 }
7307 if (!hasslaves)
7308 master->master->inconference = 0;
7309 }
7310 master->master = NULL;
7311 }
7312 dahdi_conf_update(master);
7313 if (needlock) {
7314 if (slave)
7315 ast_mutex_unlock(&slave->lock);
7316 ast_mutex_unlock(&master->lock);
7317 }
7318 }
7319
7320 void dahdi_master_slave_link(struct dahdi_pvt *slave, struct dahdi_pvt *master)
7321 {
7322 int x;
7323 if (!slave || !master) {
7324 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
7325 return;
7326 }
7327 for (x = 0; x < MAX_SLAVES; x++) {
7328 if (!master->slaves[x]) {
7329 master->slaves[x] = slave;
7330 break;
7331 }
7332 }
7333 if (x >= MAX_SLAVES) {
7334 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
7335 master->slaves[MAX_SLAVES - 1] = slave;
7336 }
7337 if (slave->master)
7338 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
7339 slave->master = master;
7340
7341 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
7342 }
7343
7344 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
7345 {
7346 struct dahdi_pvt *p = ast_channel_tech_pvt(newchan);
7347 int x;
7348
7349 ast_mutex_lock(&p->lock);
7350
7351 ast_debug(1, "New owner for channel %d is %s\n", p->channel, ast_channel_name(newchan));
7352 if (p->owner == oldchan) {
7353 p->owner = newchan;
7354 }
7355 for (x = 0; x < 3; x++) {
7356 if (p->subs[x].owner == oldchan) {
7357 if (!x) {
7358 dahdi_master_slave_unlink(NULL, p, 0);
7359 }
7360 p->subs[x].owner = newchan;
7361 }
7362 }
7363 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
7364 analog_fixup(oldchan, newchan, p->sig_pvt);
7365 #if defined(HAVE_PRI)
7366 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
7367 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
7368 #endif /* defined(HAVE_PRI) */
7369 #if defined(HAVE_SS7)
7370 } else if (p->sig == SIG_SS7) {
7371 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
7372 #endif /* defined(HAVE_SS7) */
7373 }
7374 dahdi_conf_update(p);
7375
7376 ast_mutex_unlock(&p->lock);
7377
7378 if (ast_channel_state(newchan) == AST_STATE_RINGING) {
7379 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
7380 }
7381 return 0;
7382 }
7383
7384 static int dahdi_ring_phone(struct dahdi_pvt *p)
7385 {
7386 int x;
7387 int res;
7388 /* Make sure our transmit state is on hook */
7389 x = 0;
7390 x = DAHDI_ONHOOK;
7391 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
7392 do {
7393 x = DAHDI_RING;
7394 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
7395 if (res) {
7396 switch (errno) {
7397 case EBUSY:
7398 case EINTR:
7399 /* Wait just in case */
7400 usleep(10000);
7401 continue;
7402 case EINPROGRESS:
7403 res = 0;
7404 break;
7405 default:
7406 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
7407 res = 0;
7408 }
7409 }
7410 } while (res);
7411 return res;
7412 }
7413
7414 static void *analog_ss_thread(void *data);
7415
7416 /*!
7417 * \internal
7418 * \brief Attempt to transfer 3-way call.
7419 *
7420 * \param p DAHDI private structure.
7421 *
7422 * \note On entry these locks are held: real-call, private, 3-way call.
7423 * \note On exit these locks are held: real-call, private.
7424 *
7425 * \retval 0 on success.
7426 * \retval -1 on error.
7427 */
7428 static int attempt_transfer(struct dahdi_pvt *p)
7429 {
7430 struct ast_channel *owner_real;
7431 struct ast_channel *owner_3way;
7432 enum ast_transfer_result xfer_res;
7433 int res = 0;
7434
7435 owner_real = ast_channel_ref(p->subs[SUB_REAL].owner);
7436 owner_3way = ast_channel_ref(p->subs[SUB_THREEWAY].owner);
7437
7438 ast_verb(3, "TRANSFERRING %s to %s\n",
7439 ast_channel_name(owner_3way), ast_channel_name(owner_real));
7440
7441 ast_channel_unlock(owner_real);
7442 ast_channel_unlock(owner_3way);
7443 ast_mutex_unlock(&p->lock);
7444
7445 xfer_res = ast_bridge_transfer_attended(owner_3way, owner_real);
7446 if (xfer_res != AST_BRIDGE_TRANSFER_SUCCESS) {
7447 ast_softhangup(owner_3way, AST_SOFTHANGUP_DEV);
7448 res = -1;
7449 }
7450
7451 /* Must leave with these locked. */
7452 ast_channel_lock(owner_real);
7453 ast_mutex_lock(&p->lock);
7454
7455 ast_channel_unref(owner_real);
7456 ast_channel_unref(owner_3way);
7457
7458 return res;
7459 }
7460
7461 static int check_for_conference(struct dahdi_pvt *p)
7462 {
7463 struct dahdi_confinfo ci;
7464 /* Fine if we already have a master, etc */
7465 if (p->master || (p->confno > -1))
7466 return 0;
7467 memset(&ci, 0, sizeof(ci));
7468 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
7469 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
7470 return 0;
7471 }
7472 /* If we have no master and don't have a confno, then
7473 if we're in a conference, it's probably a MeetMe room or
7474 some such, so don't let us 3-way out! */
7475 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
7476 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
7477 return 1;
7478 }
7479 return 0;
7480 }
7481
7482 /*! Checks channel for alarms
7483 * \param p a channel to check for alarms.
7484 * \returns the alarms on the span to which the channel belongs, or alarms on
7485 * the channel if no span alarms.
7486 */
7487 static int get_alarms(struct dahdi_pvt *p)
7488 {
7489 int res;
7490 struct dahdi_spaninfo zi;
7491 struct dahdi_params params;
7492
7493 memset(&zi, 0, sizeof(zi));
7494 zi.spanno = p->span;
7495
7496 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
7497 if (zi.alarms != DAHDI_ALARM_NONE)
7498 return zi.alarms;
7499 } else {
7500 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
7501 return 0;
7502 }
7503
7504 /* No alarms on the span. Check for channel alarms. */
7505 memset(&params, 0, sizeof(params));
7506 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
7507 return params.chan_alarms;
7508
7509 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
7510
7511 return DAHDI_ALARM_NONE;
7512 }
7513
7514 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
7515 {
7516 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
7517 struct ast_frame *f = *dest;
7518
7519 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
7520 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
7521 (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
7522
7523 if (p->confirmanswer) {
7524 if (f->frametype == AST_FRAME_DTMF_END) {
7525 ast_debug(1, "Confirm answer on %s!\n", ast_channel_name(ast));
7526 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
7527 of a DTMF digit */
7528 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7529 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
7530 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
7531 p->confirmanswer = 0;
7532 } else {
7533 p->subs[idx].f.frametype = AST_FRAME_NULL;
7534 p->subs[idx].f.subclass.integer = 0;
7535 }
7536 *dest = &p->subs[idx].f;
7537 } else if (p->callwaitcas) {
7538 if (f->frametype == AST_FRAME_DTMF_END) {
7539 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
7540 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
7541 ast_free(p->cidspill);
7542 p->cidspill = NULL;
7543 send_cwcidspill(p);
7544 }
7545 p->callwaitcas = 0;
7546 }
7547 p->subs[idx].f.frametype = AST_FRAME_NULL;
7548 p->subs[idx].f.subclass.integer = 0;
7549 *dest = &p->subs[idx].f;
7550 } else if (f->subclass.integer == 'f') {
7551 if (f->frametype == AST_FRAME_DTMF_END) {
7552 /* Fax tone -- Handle and return NULL */
7553 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
7554 /* If faxbuffers are configured, use them for the fax transmission */
7555 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
7556 struct dahdi_bufferinfo bi = {
7557 .txbufpolicy = p->faxbuf_policy,
7558 .bufsize = p->bufsize,
7559 .numbufs = p->faxbuf_no
7560 };
7561 int res;
7562
7563 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
7564 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
7565 } else {
7566 p->bufferoverrideinuse = 1;
7567 }
7568 }
7569 p->faxhandled = 1;
7570 if (p->dsp) {
7571 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
7572 ast_dsp_set_features(p->dsp, p->dsp_features);
7573 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
7574 }
7575 if (strcmp(ast_channel_exten(ast), "fax")) {
7576 const char *target_context = ast_channel_context(ast);
7577
7578 /*
7579 * We need to unlock 'ast' here because ast_exists_extension has the
7580 * potential to start autoservice on the channel. Such action is prone
7581 * to deadlock if the channel is locked.
7582 *
7583 * ast_async_goto() has its own restriction on not holding the
7584 * channel lock.
7585 */
7586 ast_mutex_unlock(&p->lock);
7587 ast_channel_unlock(ast);
7588 if (ast_exists_extension(ast, target_context, "fax", 1,
7589 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
7590 ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
7591 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
7592 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
7593 if (ast_async_goto(ast, target_context, "fax", 1))
7594 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
7595 } else {
7596 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
7597 }
7598 ast_channel_lock(ast);
7599 ast_mutex_lock(&p->lock);
7600 } else {
7601 ast_debug(1, "Already in a fax extension, not redirecting\n");
7602 }
7603 } else {
7604 ast_debug(1, "Fax already handled\n");
7605 }
7606 dahdi_confmute(p, 0);
7607 }
7608 p->subs[idx].f.frametype = AST_FRAME_NULL;
7609 p->subs[idx].f.subclass.integer = 0;
7610 *dest = &p->subs[idx].f;
7611 }
7612 }
7613
7614 static void publish_span_alarm(int span, const char *alarm_txt)
7615 {
7616 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
7617
7618 body = ast_json_pack("{s: i, s: s}",
7619 "Span", span,
7620 "Alarm", alarm_txt);
7621 if (!body) {
7622 return;
7623 }
7624
7625 ast_manager_publish_event("SpanAlarm", EVENT_FLAG_SYSTEM, body);
7626 }
7627
7628 static void publish_channel_alarm(int channel, const char *alarm_txt)
7629 {
7630 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
7631 RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free);
7632 if (!dahdi_chan) {
7633 return;
7634 }
7635
7636 ast_str_set(&dahdi_chan, 0, "%d", channel);
7637 body = ast_json_pack("{s: s, s: s}",
7638 "DAHDIChannel", ast_str_buffer(dahdi_chan),
7639 "Alarm", alarm_txt);
7640 if (!body) {
7641 return;
7642 }
7643
7644 ast_manager_publish_event("Alarm", EVENT_FLAG_SYSTEM, body);
7645 }
7646
7647 static void handle_alarms(struct dahdi_pvt *p, int alms)
7648 {
7649 const char *alarm_str;
7650
7651 #if defined(HAVE_PRI)
7652 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
7653 return;
7654 }
7655 #endif /* defined(HAVE_PRI) */
7656
7657 alarm_str = alarm2str(alms);
7658 if (report_alarms & REPORT_CHANNEL_ALARMS) {
7659 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
7660 publish_channel_alarm(p->channel, alarm_str);
7661 }
7662
7663 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
7664 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
7665 publish_span_alarm(p->span, alarm_str);
7666 }
7667 }
7668
7669 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
7670 {
7671 int res, x;
7672 int idx, mysig;
7673 char *c;
7674 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
7675 pthread_t threadid;
7676 struct ast_channel *chan;
7677 struct ast_frame *f;
7678
7679 idx = dahdi_get_index(ast, p, 0);
7680 if (idx < 0) {
7681 return &ast_null_frame;
7682 }
7683 mysig = p->sig;
7684 if (p->outsigmod > -1)
7685 mysig = p->outsigmod;
7686 p->subs[idx].f.frametype = AST_FRAME_NULL;
7687 p->subs[idx].f.subclass.integer = 0;
7688 p->subs[idx].f.datalen = 0;
7689 p->subs[idx].f.samples = 0;
7690 p->subs[idx].f.mallocd = 0;
7691 p->subs[idx].f.offset = 0;
7692 p->subs[idx].f.src = "dahdi_handle_event";
7693 p->subs[idx].f.data.ptr = NULL;
7694 f = &p->subs[idx].f;
7695
7696 if (p->fake_event) {
7697 res = p->fake_event;
7698 p->fake_event = 0;
7699 } else
7700 res = dahdi_get_event(p->subs[idx].dfd);
7701
7702 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
7703
7704 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
7705 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
7706 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
7707 #if defined(HAVE_PRI)
7708 if (dahdi_sig_pri_lib_handles(p->sig)
7709 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
7710 && p->pri
7711 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
7712 /* absorb event */
7713 } else
7714 #endif /* defined(HAVE_PRI) */
7715 {
7716 /* Unmute conference */
7717 dahdi_confmute(p, 0);
7718 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
7719 p->subs[idx].f.subclass.integer = res & 0xff;
7720 dahdi_handle_dtmf(ast, idx, &f);
7721 }
7722 return f;
7723 }
7724
7725 if (res & DAHDI_EVENT_DTMFDOWN) {
7726 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
7727 #if defined(HAVE_PRI)
7728 if (dahdi_sig_pri_lib_handles(p->sig)
7729 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
7730 && p->pri
7731 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
7732 /* absorb event */
7733 } else
7734 #endif /* defined(HAVE_PRI) */
7735 {
7736 /* Mute conference */
7737 dahdi_confmute(p, 1);
7738 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
7739 p->subs[idx].f.subclass.integer = res & 0xff;
7740 dahdi_handle_dtmf(ast, idx, &f);
7741 }
7742 return &p->subs[idx].f;
7743 }
7744
7745 switch (res) {
7746 case DAHDI_EVENT_EC_DISABLED:
7747 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
7748 p->echocanon = 0;
7749 break;
7750 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
7751 case DAHDI_EVENT_TX_CED_DETECTED:
7752 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
7753 break;
7754 case DAHDI_EVENT_RX_CED_DETECTED:
7755 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
7756 break;
7757 case DAHDI_EVENT_EC_NLP_DISABLED:
7758 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
7759 break;
7760 case DAHDI_EVENT_EC_NLP_ENABLED:
7761 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
7762 break;
7763 #endif
7764 case DAHDI_EVENT_BITSCHANGED:
7765 #ifdef HAVE_OPENR2
7766 if (p->sig != SIG_MFCR2) {
7767 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
7768 } else {
7769 ast_debug(1, "bits changed in chan %d\n", p->channel);
7770 openr2_chan_handle_cas(p->r2chan);
7771 }
7772 #else
7773 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
7774 #endif
7775 break;
7776 case DAHDI_EVENT_PULSE_START:
7777 /* Stop tone if there's a pulse start and the PBX isn't started */
7778 if (!ast_channel_pbx(ast))
7779 tone_zone_play_tone(p->subs[idx].dfd, -1);
7780 break;
7781 case DAHDI_EVENT_DIALCOMPLETE:
7782 /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
7783 #if defined(HAVE_PRI)
7784 if (dahdi_sig_pri_lib_handles(p->sig)) {
7785 if (p->inalarm) {
7786 break;
7787 }
7788 if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
7789 ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",
7790 ast_channel_name(ast), strerror(errno));
7791 return NULL;
7792 }
7793 if (x) {
7794 /* Still dialing in DAHDI driver */
7795 break;
7796 }
7797 /*
7798 * The ast channel is locked and the private may be locked more
7799 * than once.
7800 */
7801 sig_pri_dial_complete(p->sig_pvt, ast);
7802 break;
7803 }
7804 #endif /* defined(HAVE_PRI) */
7805 #ifdef HAVE_OPENR2
7806 if ((p->sig & SIG_MFCR2) && p->r2chan && ast_channel_state(ast) != AST_STATE_UP) {
7807 /* we don't need to do anything for this event for R2 signaling
7808 if the call is being setup */
7809 break;
7810 }
7811 #endif
7812 if (p->inalarm) break;
7813 if ((p->radio || (p->oprmode < 0))) break;
7814 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
7815 ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",ast_channel_name(ast), strerror(errno));
7816 return NULL;
7817 }
7818 if (!x) { /* if not still dialing in driver */
7819 dahdi_ec_enable(p);
7820 if (p->echobreak) {
7821 dahdi_train_ec(p);
7822 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
7823 p->dop.op = DAHDI_DIAL_OP_REPLACE;
7824 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
7825 p->echobreak = 0;
7826 } else {
7827 p->dialing = 0;
7828 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
7829 /* if thru with dialing after offhook */
7830 if (ast_channel_state(ast) == AST_STATE_DIALING_OFFHOOK) {
7831 ast_setstate(ast, AST_STATE_UP);
7832 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7833 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
7834 break;
7835 } else { /* if to state wait for offhook to dial rest */
7836 /* we now wait for off hook */
7837 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
7838 }
7839 }
7840 if (ast_channel_state(ast) == AST_STATE_DIALING) {
7841 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
7842 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
7843 } else if (p->confirmanswer || (!p->dialednone
7844 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
7845 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
7846 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
7847 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
7848 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
7849 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
7850 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
7851 || (mysig == SIG_SF_FEATB)))) {
7852 ast_setstate(ast, AST_STATE_RINGING);
7853 } else if (!p->answeronpolarityswitch) {
7854 ast_setstate(ast, AST_STATE_UP);
7855 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7856 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
7857 /* If aops=0 and hops=1, this is necessary */
7858 p->polarity = POLARITY_REV;
7859 } else {
7860 /* Start clean, so we can catch the change to REV polarity when party answers */
7861 p->polarity = POLARITY_IDLE;
7862 }
7863 }
7864 }
7865 }
7866 break;
7867 case DAHDI_EVENT_ALARM:
7868 switch (p->sig) {
7869 #if defined(HAVE_PRI)
7870 case SIG_PRI_LIB_HANDLE_CASES:
7871 sig_pri_chan_alarm_notify(p->sig_pvt, 0);
7872 break;
7873 #endif /* defined(HAVE_PRI) */
7874 #if defined(HAVE_SS7)
7875 case SIG_SS7:
7876 sig_ss7_set_alarm(p->sig_pvt, 1);
7877 break;
7878 #endif /* defined(HAVE_SS7) */
7879 default:
7880 p->inalarm = 1;
7881 break;
7882 }
7883 res = get_alarms(p);
7884 handle_alarms(p, res);
7885 #ifdef HAVE_PRI
7886 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
7887 /* fall through intentionally */
7888 } else {
7889 break;
7890 }
7891 #endif
7892 #if defined(HAVE_SS7)
7893 if (p->sig == SIG_SS7)
7894 break;
7895 #endif /* defined(HAVE_SS7) */
7896 #ifdef HAVE_OPENR2
7897 if (p->sig == SIG_MFCR2)
7898 break;
7899 #endif
7900 case DAHDI_EVENT_ONHOOK:
7901 if (p->radio) {
7902 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7903 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
7904 break;
7905 }
7906 if (p->oprmode < 0)
7907 {
7908 if (p->oprmode != -1) { /* Operator flash recall */
7909 ast_verb(4, "Operator mode enabled on channel %d, holding line for channel %d\n", p->channel, p->oprpeer->channel);
7910 break;
7911 }
7912 /* Otherwise, immediate recall */
7913 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
7914 {
7915 /* Make sure it starts ringing */
7916 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
7917 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
7918 save_conference(p->oprpeer);
7919 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
7920 ast_verb(4, "Operator recall, channel %d ringing back channel %d\n", p->oprpeer->channel, p->channel);
7921 }
7922 break;
7923 }
7924 switch (p->sig) {
7925 case SIG_FXOLS:
7926 case SIG_FXOGS:
7927 case SIG_FXOKS:
7928 /* Check for some special conditions regarding call waiting */
7929 if (idx == SUB_REAL) {
7930 /* The normal line was hung up */
7931 if (p->subs[SUB_CALLWAIT].owner) {
7932 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
7933 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
7934 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
7935 unalloc_sub(p, SUB_CALLWAIT);
7936 #if 0
7937 p->subs[idx].needanswer = 0;
7938 p->subs[idx].needringing = 0;
7939 #endif
7940 p->callwaitingrepeat = 0;
7941 p->cidcwexpire = 0;
7942 p->cid_suppress_expire = 0;
7943 p->owner = NULL;
7944 /* Don't start streaming audio yet if the incoming call isn't up yet */
7945 if (ast_channel_state(p->subs[SUB_REAL].owner) != AST_STATE_UP)
7946 p->dialing = 1;
7947 dahdi_ring_phone(p);
7948 } else if (p->subs[SUB_THREEWAY].owner) {
7949 unsigned int mssinceflash;
7950 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
7951 the private structure -- not especially easy or clean */
7952 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
7953 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
7954 DLA_UNLOCK(&p->lock);
7955 CHANNEL_DEADLOCK_AVOIDANCE(ast);
7956 /* We can grab ast and p in that order, without worry. We should make sure
7957 nothing seriously bad has happened though like some sort of bizarre double
7958 masquerade! */
7959 DLA_LOCK(&p->lock);
7960 if (p->owner != ast) {
7961 ast_log(LOG_WARNING, "This isn't good...\n");
7962 return NULL;
7963 }
7964 }
7965 if (!p->subs[SUB_THREEWAY].owner) {
7966 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
7967 return NULL;
7968 }
7969 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
7970 ast_debug(1, "Last flash was %u ms ago\n", mssinceflash);
7971 if (mssinceflash < MIN_MS_SINCE_FLASH) {
7972 /* It hasn't been long enough since the last flashook. This is probably a bounce on
7973 hanging up. Hangup both channels now */
7974 if (p->subs[SUB_THREEWAY].owner)
7975 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
7976 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
7977 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
7978 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
7979 } else if ((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) {
7980 if (p->transfer) {
7981 /* In any case this isn't a threeway call anymore */
7982 p->subs[SUB_REAL].inthreeway = 0;
7983 p->subs[SUB_THREEWAY].inthreeway = 0;
7984 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
7985 if (!p->transfertobusy && ast_channel_state(ast) == AST_STATE_BUSY) {
7986 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
7987 /* Swap subs and dis-own channel */
7988 swap_subs(p, SUB_THREEWAY, SUB_REAL);
7989 p->owner = NULL;
7990 /* Ring the phone */
7991 dahdi_ring_phone(p);
7992 } else if (!attempt_transfer(p)) {
7993 /*
7994 * Transfer successful. Don't actually hang up at this point.
7995 * Let our channel legs of the calls die off as the transfer
7996 * percolates through the core.
7997 */
7998 break;
7999 }
8000 } else {
8001 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
8002 if (p->subs[SUB_THREEWAY].owner)
8003 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
8004 }
8005 } else {
8006 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
8007 /* Swap subs and dis-own channel */
8008 swap_subs(p, SUB_THREEWAY, SUB_REAL);
8009 p->owner = NULL;
8010 /* Ring the phone */
8011 dahdi_ring_phone(p);
8012 }
8013 }
8014 } else {
8015 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
8016 }
8017 /* Fall through */
8018 default:
8019 dahdi_ec_disable(p);
8020 return NULL;
8021 }
8022 break;
8023 case DAHDI_EVENT_RINGOFFHOOK:
8024 if (p->inalarm) break;
8025 if (p->oprmode < 0)
8026 {
8027 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
8028 {
8029 /* Make sure it stops ringing */
8030 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
8031 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
8032 restore_conference(p->oprpeer);
8033 ast_debug(1, "Operator recall by channel %d for channel %d complete\n", p->oprpeer->channel, p->channel);
8034 }
8035 break;
8036 }
8037 if (p->radio)
8038 {
8039 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8040 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
8041 break;
8042 }
8043 /* for E911, its supposed to wait for offhook then dial
8044 the second half of the dial string */
8045 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast_channel_state(ast) == AST_STATE_DIALING_OFFHOOK)) {
8046 c = strchr(p->dialdest, '/');
8047 if (c)
8048 c++;
8049 else
8050 c = p->dialdest;
8051
8052 if (*c) {
8053 int numchars = snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
8054 if (numchars >= sizeof(p->dop.dialstr)) {
8055 ast_log(LOG_WARNING, "Dial string '%s' truncated\n", c);
8056 }
8057 } else {
8058 ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
8059 }
8060
8061 if (strlen(p->dop.dialstr) > 4) {
8062 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
8063 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
8064 p->echorest[sizeof(p->echorest) - 1] = '\0';
8065 p->echobreak = 1;
8066 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
8067 } else
8068 p->echobreak = 0;
8069 if (dahdi_dial_str(p, p->dop.op, p->dop.dialstr)) {
8070 x = DAHDI_ONHOOK;
8071 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
8072 return NULL;
8073 }
8074 p->dialing = 1;
8075 return &p->subs[idx].f;
8076 }
8077 switch (p->sig) {
8078 case SIG_FXOLS:
8079 case SIG_FXOGS:
8080 case SIG_FXOKS:
8081 switch (ast_channel_state(ast)) {
8082 case AST_STATE_RINGING:
8083 dahdi_ec_enable(p);
8084 dahdi_train_ec(p);
8085 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8086 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
8087 /* Make sure it stops ringing */
8088 p->subs[SUB_REAL].needringing = 0;
8089 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
8090 ast_debug(1, "channel %d answered\n", p->channel);
8091
8092 /* Cancel any running CallerID spill */
8093 ast_free(p->cidspill);
8094 p->cidspill = NULL;
8095 restore_conference(p);
8096
8097 p->dialing = 0;
8098 p->callwaitcas = 0;
8099 if (p->confirmanswer) {
8100 /* Ignore answer if "confirm answer" is enabled */
8101 p->subs[idx].f.frametype = AST_FRAME_NULL;
8102 p->subs[idx].f.subclass.integer = 0;
8103 } else if (!ast_strlen_zero(p->dop.dialstr)) {
8104 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
8105 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8106 if (res) {
8107 p->dop.dialstr[0] = '\0';
8108 return NULL;
8109 } else {
8110 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
8111 p->subs[idx].f.frametype = AST_FRAME_NULL;
8112 p->subs[idx].f.subclass.integer = 0;
8113 p->dialing = 1;
8114 }
8115 p->dop.dialstr[0] = '\0';
8116 ast_setstate(ast, AST_STATE_DIALING);
8117 } else
8118 ast_setstate(ast, AST_STATE_UP);
8119 return &p->subs[idx].f;
8120 case AST_STATE_DOWN:
8121 ast_setstate(ast, AST_STATE_RING);
8122 ast_channel_rings_set(ast, 1);
8123 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8124 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
8125 ast_debug(1, "channel %d picked up\n", p->channel);
8126 return &p->subs[idx].f;
8127 case AST_STATE_UP:
8128 /* Make sure it stops ringing */
8129 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
8130 /* Okay -- probably call waiting*/
8131 ast_queue_unhold(p->owner);
8132 p->subs[idx].needunhold = 1;
8133 break;
8134 case AST_STATE_RESERVED:
8135 /* Start up dialtone */
8136 if (has_voicemail(p))
8137 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
8138 else
8139 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
8140 break;
8141 default:
8142 ast_log(LOG_WARNING, "FXO phone off hook in weird state %u??\n", ast_channel_state(ast));
8143 }
8144 break;
8145 case SIG_FXSLS:
8146 case SIG_FXSGS:
8147 case SIG_FXSKS:
8148 if (ast_channel_state(ast) == AST_STATE_RING) {
8149 p->ringt = p->ringt_base;
8150 }
8151
8152 /* If we get a ring then we cannot be in
8153 * reversed polarity. So we reset to idle */
8154 ast_debug(1, "Setting IDLE polarity due "
8155 "to ring. Old polarity was %d\n",
8156 p->polarity);
8157 p->polarity = POLARITY_IDLE;
8158
8159 /* Fall through */
8160 case SIG_EM:
8161 case SIG_EM_E1:
8162 case SIG_EMWINK:
8163 case SIG_FEATD:
8164 case SIG_FEATDMF:
8165 case SIG_FEATDMF_TA:
8166 case SIG_E911:
8167 case SIG_FGC_CAMA:
8168 case SIG_FGC_CAMAMF:
8169 case SIG_FEATB:
8170 case SIG_SF:
8171 case SIG_SFWINK:
8172 case SIG_SF_FEATD:
8173 case SIG_SF_FEATDMF:
8174 case SIG_SF_FEATB:
8175 if (ast_channel_state(ast) == AST_STATE_PRERING)
8176 ast_setstate(ast, AST_STATE_RING);
8177 if ((ast_channel_state(ast) == AST_STATE_DOWN) || (ast_channel_state(ast) == AST_STATE_RING)) {
8178 ast_debug(1, "Ring detected\n");
8179 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8180 p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
8181 } else if (p->outgoing && ((ast_channel_state(ast) == AST_STATE_RINGING) || (ast_channel_state(ast) == AST_STATE_DIALING))) {
8182 ast_debug(1, "Line answered\n");
8183 if (p->confirmanswer) {
8184 p->subs[idx].f.frametype = AST_FRAME_NULL;
8185 p->subs[idx].f.subclass.integer = 0;
8186 } else {
8187 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8188 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
8189 ast_setstate(ast, AST_STATE_UP);
8190 }
8191 } else if (ast_channel_state(ast) != AST_STATE_RING)
8192 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %u on channel %d\n", ast_channel_state(ast), p->channel);
8193 break;
8194 default:
8195 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
8196 }
8197 break;
8198 case DAHDI_EVENT_RINGBEGIN:
8199 switch (p->sig) {
8200 case SIG_FXSLS:
8201 case SIG_FXSGS:
8202 case SIG_FXSKS:
8203 if (ast_channel_state(ast) == AST_STATE_RING) {
8204 p->ringt = p->ringt_base;
8205 }
8206 break;
8207 }
8208 break;
8209 case DAHDI_EVENT_RINGERON:
8210 break;
8211 case DAHDI_EVENT_NOALARM:
8212 switch (p->sig) {
8213 #if defined(HAVE_PRI)
8214 case SIG_PRI_LIB_HANDLE_CASES:
8215 sig_pri_chan_alarm_notify(p->sig_pvt, 1);
8216 break;
8217 #endif /* defined(HAVE_PRI) */
8218 #if defined(HAVE_SS7)
8219 case SIG_SS7:
8220 sig_ss7_set_alarm(p->sig_pvt, 0);
8221 break;
8222 #endif /* defined(HAVE_SS7) */
8223 default:
8224 p->inalarm = 0;
8225 break;
8226 }
8227 handle_clear_alarms(p);
8228 break;
8229 case DAHDI_EVENT_WINKFLASH:
8230 if (p->inalarm) break;
8231 if (p->radio) break;
8232 if (p->oprmode < 0) break;
8233 if (p->oprmode > 1)
8234 {
8235 struct dahdi_params par;
8236
8237 memset(&par, 0, sizeof(par));
8238 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
8239 {
8240 if (!par.rxisoffhook)
8241 {
8242 /* Make sure it stops ringing */
8243 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
8244 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
8245 save_conference(p);
8246 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
8247 ast_verb(4, "Operator flash recall, channel %d ringing back channel %d\n", p->oprpeer->channel, p->channel);
8248 }
8249 }
8250 break;
8251 }
8252 /* Remember last time we got a flash-hook */
8253 p->flashtime = ast_tvnow();
8254 switch (mysig) {
8255 case SIG_FXOLS:
8256 case SIG_FXOGS:
8257 case SIG_FXOKS:
8258 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
8259 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
8260
8261 /* Cancel any running CallerID spill */
8262 ast_free(p->cidspill);
8263 p->cidspill = NULL;
8264 restore_conference(p);
8265 p->callwaitcas = 0;
8266
8267 if (idx != SUB_REAL) {
8268 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
8269 goto winkflashdone;
8270 }
8271
8272 if (p->subs[SUB_CALLWAIT].owner) {
8273 /* Swap to call-wait */
8274 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
8275 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
8276 p->owner = p->subs[SUB_REAL].owner;
8277 ast_debug(1, "Making %s the new owner\n", ast_channel_name(p->owner));
8278 if (ast_channel_state(p->owner) == AST_STATE_RINGING) {
8279 ast_setstate(p->owner, AST_STATE_UP);
8280 p->subs[SUB_REAL].needanswer = 1;
8281 }
8282 p->callwaitingrepeat = 0;
8283 p->cidcwexpire = 0;
8284 p->cid_suppress_expire = 0;
8285 /* Start music on hold if appropriate */
8286 if (!p->subs[SUB_CALLWAIT].inthreeway) {
8287 ast_queue_hold(p->subs[SUB_CALLWAIT].owner, p->mohsuggest);
8288 }
8289 p->subs[SUB_CALLWAIT].needhold = 1;
8290 ast_queue_hold(p->subs[SUB_REAL].owner, p->mohsuggest);
8291 p->subs[SUB_REAL].needunhold = 1;
8292 } else if (!p->subs[SUB_THREEWAY].owner) {
8293 if (!p->threewaycalling) {
8294 /* Just send a flash if no 3-way calling */
8295 p->subs[SUB_REAL].needflash = 1;
8296 goto winkflashdone;
8297 } else if (!check_for_conference(p)) {
8298 ast_callid callid = 0;
8299 int callid_created;
8300 char cid_num[256];
8301 char cid_name[256];
8302
8303 cid_num[0] = 0;
8304 cid_name[0] = 0;
8305 if (p->dahditrcallerid && p->owner) {
8306 if (ast_channel_caller(p->owner)->id.number.valid
8307 && ast_channel_caller(p->owner)->id.number.str) {
8308 ast_copy_string(cid_num, ast_channel_caller(p->owner)->id.number.str,
8309 sizeof(cid_num));
8310 }
8311 if (ast_channel_caller(p->owner)->id.name.valid
8312 && ast_channel_caller(p->owner)->id.name.str) {
8313 ast_copy_string(cid_name, ast_channel_caller(p->owner)->id.name.str,
8314 sizeof(cid_name));
8315 }
8316 }
8317 /* XXX This section needs much more error checking!!! XXX */
8318 /* Start a 3-way call if feasible */
8319 if (!((ast_channel_pbx(ast)) ||
8320 (ast_channel_state(ast) == AST_STATE_UP) ||
8321 (ast_channel_state(ast) == AST_STATE_RING))) {
8322 ast_debug(1, "Flash when call not up or ringing\n");
8323 goto winkflashdone;
8324 }
8325 if (alloc_sub(p, SUB_THREEWAY)) {
8326 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
8327 goto winkflashdone;
8328 }
8329 callid_created = ast_callid_threadstorage_auto(&callid);
8330 /*
8331 * Make new channel
8332 *
8333 * We cannot hold the p or ast locks while creating a new
8334 * channel.
8335 */
8336 ast_mutex_unlock(&p->lock);
8337 ast_channel_unlock(ast);
8338 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL, NULL, callid);
8339 ast_channel_lock(ast);
8340 ast_mutex_lock(&p->lock);
8341 if (p->dahditrcallerid) {
8342 if (!p->origcid_num)
8343 p->origcid_num = ast_strdup(p->cid_num);
8344 if (!p->origcid_name)
8345 p->origcid_name = ast_strdup(p->cid_name);
8346 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
8347 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
8348 }
8349 /* Swap things around between the three-way and real call */
8350 swap_subs(p, SUB_THREEWAY, SUB_REAL);
8351 /* Disable echo canceller for better dialing */
8352 dahdi_ec_disable(p);
8353 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
8354 if (res)
8355 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
8356 p->owner = chan;
8357 if (!chan) {
8358 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
8359 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
8360 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
8361 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
8362 dahdi_ec_enable(p);
8363 ast_hangup(chan);
8364 } else {
8365 ast_verb(3, "Started three way call on channel %d\n", p->channel);
8366
8367 /* Start music on hold */
8368 ast_queue_hold(p->subs[SUB_THREEWAY].owner, p->mohsuggest);
8369 p->subs[SUB_THREEWAY].needhold = 1;
8370 }
8371 ast_callid_threadstorage_auto_clean(callid, callid_created);
8372 }
8373 } else {
8374 /* Already have a 3 way call */
8375 if (p->subs[SUB_THREEWAY].inthreeway) {
8376 /* Call is already up, drop the last person */
8377 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
8378 /* If the primary call isn't answered yet, use it */
8379 if ((ast_channel_state(p->subs[SUB_REAL].owner) != AST_STATE_UP) && (ast_channel_state(p->subs[SUB_THREEWAY].owner) == AST_STATE_UP)) {
8380 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
8381 swap_subs(p, SUB_THREEWAY, SUB_REAL);
8382 p->owner = p->subs[SUB_REAL].owner;
8383 }
8384 /* Drop the last call and stop the conference */
8385 ast_verb(3, "Dropping three-way call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
8386 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
8387 p->subs[SUB_REAL].inthreeway = 0;
8388 p->subs[SUB_THREEWAY].inthreeway = 0;
8389 } else {
8390 /* Lets see what we're up to */
8391 if (((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) &&
8392 (p->transfertobusy || (ast_channel_state(ast) != AST_STATE_BUSY))) {
8393 int otherindex = SUB_THREEWAY;
8394
8395 ast_verb(3, "Building conference call with %s and %s\n",
8396 ast_channel_name(p->subs[SUB_THREEWAY].owner),
8397 ast_channel_name(p->subs[SUB_REAL].owner));
8398 /* Put them in the threeway, and flip */
8399 p->subs[SUB_THREEWAY].inthreeway = 1;
8400 p->subs[SUB_REAL].inthreeway = 1;
8401 if (ast_channel_state(ast) == AST_STATE_UP) {
8402 swap_subs(p, SUB_THREEWAY, SUB_REAL);
8403 otherindex = SUB_REAL;
8404 }
8405 if (p->subs[otherindex].owner) {
8406 ast_queue_unhold(p->subs[otherindex].owner);
8407 }
8408 p->subs[otherindex].needunhold = 1;
8409 p->owner = p->subs[SUB_REAL].owner;
8410 } else {
8411 ast_verb(3, "Dumping incomplete call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
8412 swap_subs(p, SUB_THREEWAY, SUB_REAL);
8413 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
8414 p->owner = p->subs[SUB_REAL].owner;
8415 if (p->subs[SUB_REAL].owner) {
8416 ast_queue_unhold(p->subs[SUB_REAL].owner);
8417 }
8418 p->subs[SUB_REAL].needunhold = 1;
8419 dahdi_ec_enable(p);
8420 }
8421 }
8422 }
8423 winkflashdone:
8424 dahdi_conf_update(p);
8425 break;
8426 case SIG_EM:
8427 case SIG_EM_E1:
8428 case SIG_FEATD:
8429 case SIG_SF:
8430 case SIG_SFWINK:
8431 case SIG_SF_FEATD:
8432 case SIG_FXSLS:
8433 case SIG_FXSGS:
8434 if (p->dialing)
8435 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
8436 else
8437 ast_debug(1, "Got wink in weird state %u on channel %d\n", ast_channel_state(ast), p->channel);
8438 break;
8439 case SIG_FEATDMF_TA:
8440 switch (p->whichwink) {
8441 case 0:
8442 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", ast_channel_caller(p->owner)->ani2,
8443 S_COR(ast_channel_caller(p->owner)->ani.number.valid,
8444 ast_channel_caller(p->owner)->ani.number.str, ""));
8445 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
8446 ast_channel_caller(p->owner)->ani2,
8447 S_COR(ast_channel_caller(p->owner)->ani.number.valid,
8448 ast_channel_caller(p->owner)->ani.number.str, ""));
8449 break;
8450 case 1:
8451 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
8452 break;
8453 case 2:
8454 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
8455 return NULL;
8456 }
8457 p->whichwink++;
8458 /* Fall through */
8459 case SIG_FEATDMF:
8460 case SIG_E911:
8461 case SIG_FGC_CAMAMF:
8462 case SIG_FGC_CAMA:
8463 case SIG_FEATB:
8464 case SIG_SF_FEATDMF:
8465 case SIG_SF_FEATB:
8466 case SIG_EMWINK:
8467 /* FGD MF and EMWINK *Must* wait for wink */
8468 if (!ast_strlen_zero(p->dop.dialstr)) {
8469 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8470 if (res) {
8471 p->dop.dialstr[0] = '\0';
8472 return NULL;
8473 } else
8474 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
8475 }
8476 p->dop.dialstr[0] = '\0';
8477 break;
8478 default:
8479 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
8480 }
8481 break;
8482 case DAHDI_EVENT_HOOKCOMPLETE:
8483 if (p->inalarm) break;
8484 if ((p->radio || (p->oprmode < 0))) break;
8485 if (p->waitingfordt.tv_sec) break;
8486 switch (mysig) {
8487 case SIG_FXSLS: /* only interesting for FXS */
8488 case SIG_FXSGS:
8489 case SIG_FXSKS:
8490 case SIG_EM:
8491 case SIG_EM_E1:
8492 case SIG_EMWINK:
8493 case SIG_FEATD:
8494 case SIG_SF:
8495 case SIG_SFWINK:
8496 case SIG_SF_FEATD:
8497 if (!ast_strlen_zero(p->dop.dialstr)) {
8498 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8499 if (res) {
8500 p->dop.dialstr[0] = '\0';
8501 return NULL;
8502 } else
8503 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
8504 }
8505 p->dop.dialstr[0] = '\0';
8506 p->dop.op = DAHDI_DIAL_OP_REPLACE;
8507 break;
8508 case SIG_FEATDMF:
8509 case SIG_FEATDMF_TA:
8510 case SIG_E911:
8511 case SIG_FGC_CAMA:
8512 case SIG_FGC_CAMAMF:
8513 case SIG_FEATB:
8514 case SIG_SF_FEATDMF:
8515 case SIG_SF_FEATB:
8516 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
8517 break;
8518 default:
8519 break;
8520 }
8521 break;
8522 case DAHDI_EVENT_POLARITY:
8523 /*
8524 * If we get a Polarity Switch event, check to see
8525 * if we should change the polarity state and
8526 * mark the channel as UP or if this is an indication
8527 * of remote end disconnect.
8528 */
8529 if (p->polarity == POLARITY_IDLE) {
8530 p->polarity = POLARITY_REV;
8531 if (p->answeronpolarityswitch &&
8532 ((ast_channel_state(ast) == AST_STATE_DIALING) ||
8533 (ast_channel_state(ast) == AST_STATE_RINGING))) {
8534 ast_debug(1, "Answering on polarity switch!\n");
8535 ast_setstate(p->owner, AST_STATE_UP);
8536 if (p->hanguponpolarityswitch) {
8537 p->polaritydelaytv = ast_tvnow();
8538 }
8539 } else
8540 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %u\n", p->channel, ast_channel_state(ast));
8541 }
8542 /* Removed else statement from here as it was preventing hangups from ever happening*/
8543 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
8544 if (p->hanguponpolarityswitch &&
8545 (p->polarityonanswerdelay > 0) &&
8546 (p->polarity == POLARITY_REV) &&
8547 ((ast_channel_state(ast) == AST_STATE_UP) || (ast_channel_state(ast) == AST_STATE_RING)) ) {
8548 /* Added log_debug information below to provide a better indication of what is going on */
8549 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) );
8550
8551 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
8552 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
8553 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
8554 p->polarity = POLARITY_IDLE;
8555 } else
8556 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));
8557
8558 } else {
8559 p->polarity = POLARITY_IDLE;
8560 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %u\n", p->channel, ast_channel_state(ast));
8561 }
8562 /* Added more log_debug information below to provide a better indication of what is going on */
8563 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) );
8564 break;
8565 default:
8566 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
8567 }
8568 return &p->subs[idx].f;
8569 }
8570
8571 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
8572 {
8573 int res;
8574 int idx;
8575 struct ast_frame *f;
8576 int usedindex = -1;
8577 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8578
8579 if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
8580 idx = SUB_REAL;
8581 }
8582
8583 p->subs[idx].f.frametype = AST_FRAME_NULL;
8584 p->subs[idx].f.datalen = 0;
8585 p->subs[idx].f.samples = 0;
8586 p->subs[idx].f.mallocd = 0;
8587 p->subs[idx].f.offset = 0;
8588 p->subs[idx].f.subclass.integer = 0;
8589 p->subs[idx].f.delivery = ast_tv(0,0);
8590 p->subs[idx].f.src = "dahdi_exception";
8591 p->subs[idx].f.data.ptr = NULL;
8592
8593
8594 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
8595 /* If nobody owns us, absorb the event appropriately, otherwise
8596 we loop indefinitely. This occurs when, during call waiting, the
8597 other end hangs up our channel so that it no longer exists, but we
8598 have neither FLASH'd nor ONHOOK'd to signify our desire to
8599 change to the other channel. */
8600 if (p->fake_event) {
8601 res = p->fake_event;
8602 p->fake_event = 0;
8603 } else
8604 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
8605 /* Switch to real if there is one and this isn't something really silly... */
8606 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
8607 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
8608 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
8609 p->owner = p->subs[SUB_REAL].owner;
8610 if (p->owner) {
8611 ast_queue_unhold(p->owner);
8612 }
8613 p->subs[SUB_REAL].needunhold = 1;
8614 }
8615 switch (res) {
8616 case DAHDI_EVENT_ONHOOK:
8617 dahdi_ec_disable(p);
8618 if (p->owner) {
8619 ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
8620 dahdi_ring_phone(p);
8621 p->callwaitingrepeat = 0;
8622 p->cidcwexpire = 0;
8623 p->cid_suppress_expire = 0;
8624 } else
8625 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8626 dahdi_conf_update(p);
8627 break;
8628 case DAHDI_EVENT_RINGOFFHOOK:
8629 dahdi_ec_enable(p);
8630 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
8631 if (p->owner && (ast_channel_state(p->owner) == AST_STATE_RINGING)) {
8632 p->subs[SUB_REAL].needanswer = 1;
8633 p->dialing = 0;
8634 }
8635 break;
8636 case DAHDI_EVENT_HOOKCOMPLETE:
8637 case DAHDI_EVENT_RINGERON:
8638 case DAHDI_EVENT_RINGEROFF:
8639 /* Do nothing */
8640 break;
8641 case DAHDI_EVENT_WINKFLASH:
8642 p->flashtime = ast_tvnow();
8643 if (p->owner) {
8644 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, ast_channel_name(p->owner));
8645 if (ast_channel_state(p->owner) != AST_STATE_UP) {
8646 /* Answer if necessary */
8647 usedindex = dahdi_get_index(p->owner, p, 0);
8648 if (usedindex > -1) {
8649 p->subs[usedindex].needanswer = 1;
8650 }
8651 ast_setstate(p->owner, AST_STATE_UP);
8652 }
8653 p->callwaitingrepeat = 0;
8654 p->cidcwexpire = 0;
8655 p->cid_suppress_expire = 0;
8656 ast_queue_unhold(p->owner);
8657 p->subs[SUB_REAL].needunhold = 1;
8658 } else
8659 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8660 dahdi_conf_update(p);
8661 break;
8662 default:
8663 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
8664 }
8665 f = &p->subs[idx].f;
8666 return f;
8667 }
8668 if (!(p->radio || (p->oprmode < 0)))
8669 ast_debug(1, "Exception on %d, channel %d\n", ast_channel_fd(ast, 0), p->channel);
8670 /* If it's not us, return NULL immediately */
8671 if (ast != p->owner) {
8672 if (p->owner) {
8673 ast_log(LOG_WARNING, "We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->owner));
8674 }
8675 f = &p->subs[idx].f;
8676 return f;
8677 }
8678
8679 f = dahdi_handle_event(ast);
8680 if (!f) {
8681 const char *name = ast_strdupa(ast_channel_name(ast));
8682
8683 /* Tell the CDR this DAHDI device hung up */
8684 ast_mutex_unlock(&p->lock);
8685 ast_channel_unlock(ast);
8686 ast_set_hangupsource(ast, name, 0);
8687 ast_channel_lock(ast);
8688 ast_mutex_lock(&p->lock);
8689 }
8690 return f;
8691 }
8692
8693 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
8694 {
8695 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8696 struct ast_frame *f;
8697 ast_mutex_lock(&p->lock);
8698 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8699 struct analog_pvt *analog_p = p->sig_pvt;
8700 f = analog_exception(analog_p, ast);
8701 } else {
8702 f = __dahdi_exception(ast);
8703 }
8704 ast_mutex_unlock(&p->lock);
8705 return f;
8706 }
8707
8708 static struct ast_frame *dahdi_read(struct ast_channel *ast)
8709 {
8710 struct dahdi_pvt *p;
8711 int res;
8712 int idx;
8713 void *readbuf;
8714 struct ast_frame *f;
8715
8716 /*
8717 * For analog channels, we must do deadlock avoidance because
8718 * analog ports can have more than one Asterisk channel using
8719 * the same private structure.
8720 */
8721 p = ast_channel_tech_pvt(ast);
8722 while (ast_mutex_trylock(&p->lock)) {
8723 CHANNEL_DEADLOCK_AVOIDANCE(ast);
8724
8725 /*
8726 * Check to see if the channel is still associated with the same
8727 * private structure. While the Asterisk channel was unlocked
8728 * the following events may have occured:
8729 *
8730 * 1) A masquerade may have associated the channel with another
8731 * technology or private structure.
8732 *
8733 * 2) For PRI calls, call signaling could change the channel
8734 * association to another B channel (private structure).
8735 */
8736 if (ast_channel_tech_pvt(ast) != p) {
8737 /* The channel is no longer associated. Quit gracefully. */
8738 return &ast_null_frame;
8739 }
8740 }
8741
8742 idx = dahdi_get_index(ast, p, 0);
8743
8744 /* Hang up if we don't really exist */
8745 if (idx < 0) {
8746 ast_log(LOG_WARNING, "We don't exist?\n");
8747 ast_mutex_unlock(&p->lock);
8748 return NULL;
8749 }
8750
8751 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
8752 ast_mutex_unlock(&p->lock);
8753 return NULL;
8754 }
8755
8756 p->subs[idx].f.frametype = AST_FRAME_NULL;
8757 p->subs[idx].f.datalen = 0;
8758 p->subs[idx].f.samples = 0;
8759 p->subs[idx].f.mallocd = 0;
8760 p->subs[idx].f.offset = 0;
8761 p->subs[idx].f.subclass.integer = 0;
8762 p->subs[idx].f.delivery = ast_tv(0,0);
8763 p->subs[idx].f.src = "dahdi_read";
8764 p->subs[idx].f.data.ptr = NULL;
8765
8766 /* make sure it sends initial key state as first frame */
8767 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
8768 {
8769 struct dahdi_params ps;
8770
8771 memset(&ps, 0, sizeof(ps));
8772 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
8773 ast_mutex_unlock(&p->lock);
8774 return NULL;
8775 }
8776 p->firstradio = 1;
8777 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8778 if (ps.rxisoffhook)
8779 {
8780 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
8781 }
8782 else
8783 {
8784 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
8785 }
8786 ast_mutex_unlock(&p->lock);
8787 return &p->subs[idx].f;
8788 }
8789 if (p->ringt > 0) {
8790 if (!(--p->ringt)) {
8791 ast_mutex_unlock(&p->lock);
8792 return NULL;
8793 }
8794 }
8795
8796 #ifdef HAVE_OPENR2
8797 if (p->mfcr2) {
8798 openr2_chan_process_event(p->r2chan);
8799 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
8800 struct ast_frame fr = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS } };
8801 /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
8802 * now enqueue a progress frame to bridge the media up */
8803 if (p->mfcr2_call_accepted &&
8804 !p->mfcr2_progress_sent &&
8805 ast_channel_state(ast) == AST_STATE_RINGING) {
8806 ast_debug(1, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
8807 ast_queue_frame(p->owner, &fr);
8808 p->mfcr2_progress_sent = 1;
8809 }
8810 }
8811 }
8812 #endif
8813
8814 if (p->subs[idx].needringing) {
8815 /* Send ringing frame if requested */
8816 p->subs[idx].needringing = 0;
8817 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8818 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
8819 ast_setstate(ast, AST_STATE_RINGING);
8820 ast_mutex_unlock(&p->lock);
8821 return &p->subs[idx].f;
8822 }
8823
8824 if (p->subs[idx].needbusy) {
8825 /* Send busy frame if requested */
8826 p->subs[idx].needbusy = 0;
8827 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8828 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
8829 ast_mutex_unlock(&p->lock);
8830 return &p->subs[idx].f;
8831 }
8832
8833 if (p->subs[idx].needcongestion) {
8834 /* Send congestion frame if requested */
8835 p->subs[idx].needcongestion = 0;
8836 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8837 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
8838 ast_mutex_unlock(&p->lock);
8839 return &p->subs[idx].f;
8840 }
8841
8842 if (p->subs[idx].needanswer) {
8843 /* Send answer frame if requested */
8844 p->subs[idx].needanswer = 0;
8845 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8846 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
8847 ast_mutex_unlock(&p->lock);
8848 return &p->subs[idx].f;
8849 }
8850 #ifdef HAVE_OPENR2
8851 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
8852 /* openr2 took care of reading and handling any event
8853 (needanswer, needbusy etc), if we continue we will read()
8854 twice, lets just return a null frame. This should only
8855 happen when openr2 is dialing out */
8856 ast_mutex_unlock(&p->lock);
8857 return &ast_null_frame;
8858 }
8859 #endif
8860
8861 if (p->subs[idx].needflash) {
8862 /* Send answer frame if requested */
8863 p->subs[idx].needflash = 0;
8864 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8865 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
8866 ast_mutex_unlock(&p->lock);
8867 return &p->subs[idx].f;
8868 }
8869
8870 if (p->subs[idx].needhold) {
8871 /* Send answer frame if requested */
8872 p->subs[idx].needhold = 0;
8873 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8874 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
8875 ast_mutex_unlock(&p->lock);
8876 ast_debug(1, "Sending hold on '%s'\n", ast_channel_name(ast));
8877 return &p->subs[idx].f;
8878 }
8879
8880 if (p->subs[idx].needunhold) {
8881 /* Send answer frame if requested */
8882 p->subs[idx].needunhold = 0;
8883 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8884 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
8885 ast_mutex_unlock(&p->lock);
8886 ast_debug(1, "Sending unhold on '%s'\n", ast_channel_name(ast));
8887 return &p->subs[idx].f;
8888 }
8889
8890 /*
8891 * If we have a fake_event, fake an exception to handle it only
8892 * if this channel owns the private.
8893 */
8894 if (p->fake_event && p->owner == ast) {
8895 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8896 struct analog_pvt *analog_p = p->sig_pvt;
8897
8898 f = analog_exception(analog_p, ast);
8899 } else {
8900 f = __dahdi_exception(ast);
8901 }
8902 ast_mutex_unlock(&p->lock);
8903 return f;
8904 }
8905
8906 if (ast_format_cmp(ast_channel_rawreadformat(ast), ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
8907 if (!p->subs[idx].linear) {
8908 p->subs[idx].linear = 1;
8909 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
8910 if (res)
8911 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
8912 }
8913 } else {
8914 if (p->subs[idx].linear) {
8915 p->subs[idx].linear = 0;
8916 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
8917 if (res)
8918 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
8919 }
8920 }
8921 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
8922 CHECK_BLOCKING(ast);
8923 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
8924 ast_clear_flag(ast_channel_flags(ast), AST_FLAG_BLOCKING);
8925 /* Check for hangup */
8926 if (res < 0) {
8927 f = NULL;
8928 if (res == -1) {
8929 if (errno == EAGAIN) {
8930 /* Return "NULL" frame if there is nobody there */
8931 ast_mutex_unlock(&p->lock);
8932 return &p->subs[idx].f;
8933 } else if (errno == ELAST) {
8934 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8935 struct analog_pvt *analog_p = p->sig_pvt;
8936 f = analog_exception(analog_p, ast);
8937 } else {
8938 f = __dahdi_exception(ast);
8939 }
8940 } else
8941 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
8942 }
8943 ast_mutex_unlock(&p->lock);
8944 return f;
8945 }
8946 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
8947 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
8948 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8949 struct analog_pvt *analog_p = p->sig_pvt;
8950 f = analog_exception(analog_p, ast);
8951 } else {
8952 f = __dahdi_exception(ast);
8953 }
8954 ast_mutex_unlock(&p->lock);
8955 return f;
8956 }
8957 if (p->tdd) { /* if in TDD mode, see if we receive that */
8958 int c;
8959
8960 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
8961 if (c < 0) {
8962 ast_debug(1,"tdd_feed failed\n");
8963 ast_mutex_unlock(&p->lock);
8964 return NULL;
8965 }
8966 if (c) { /* if a char to return */
8967 p->subs[idx].f.subclass.integer = 0;
8968 p->subs[idx].f.frametype = AST_FRAME_TEXT;
8969 p->subs[idx].f.mallocd = 0;
8970 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
8971 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
8972 p->subs[idx].f.datalen = 1;
8973 *((char *) p->subs[idx].f.data.ptr) = c;
8974 ast_mutex_unlock(&p->lock);
8975 return &p->subs[idx].f;
8976 }
8977 }
8978 if (idx == SUB_REAL) {
8979 /* Ensure the CW timers decrement only on a single subchannel */
8980 if (p->cidcwexpire) {
8981 if (!--p->cidcwexpire) {
8982 /* Expired CID/CW */
8983 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
8984 restore_conference(p);
8985 }
8986 }
8987 if (p->cid_suppress_expire) {
8988 --p->cid_suppress_expire;
8989 }
8990 if (p->callwaitingrepeat) {
8991 if (!--p->callwaitingrepeat) {
8992 /* Expired, Repeat callwaiting tone */
8993 ++p->callwaitrings;
8994 dahdi_callwait(ast);
8995 }
8996 }
8997 }
8998 if (p->subs[idx].linear) {
8999 p->subs[idx].f.datalen = READ_SIZE * 2;
9000 } else
9001 p->subs[idx].f.datalen = READ_SIZE;
9002
9003 /* Handle CallerID Transmission */
9004 if ((p->owner == ast) && p->cidspill) {
9005 send_callerid(p);
9006 }
9007
9008 p->subs[idx].f.frametype = AST_FRAME_VOICE;
9009 p->subs[idx].f.subclass.format = ast_channel_rawreadformat(ast);
9010 p->subs[idx].f.samples = READ_SIZE;
9011 p->subs[idx].f.mallocd = 0;
9012 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
9013 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
9014 #if 0
9015 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
9016 #endif
9017 if ((p->dialing && !p->waitingfordt.tv_sec) || p->radio || /* Transmitting something */
9018 (idx && (ast_channel_state(ast) != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
9019 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
9020 ) {
9021 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
9022 don't send anything */
9023 p->subs[idx].f.frametype = AST_FRAME_NULL;
9024 p->subs[idx].f.subclass.integer = 0;
9025 p->subs[idx].f.samples = 0;
9026 p->subs[idx].f.mallocd = 0;
9027 p->subs[idx].f.offset = 0;
9028 p->subs[idx].f.data.ptr = NULL;
9029 p->subs[idx].f.datalen= 0;
9030 }
9031 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec || p->dialtone_detect) && !idx) {
9032 /* Perform busy detection etc on the dahdi line */
9033 int mute;
9034
9035 if ((p->dsp_features & DSP_FEATURE_FAX_DETECT)
9036 && p->faxdetect_timeout
9037 && p->faxdetect_timeout <= ast_channel_get_up_time(ast)) {
9038 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
9039 ast_dsp_set_features(p->dsp, p->dsp_features);
9040 ast_debug(1, "Channel driver fax CNG detection timeout on %s\n",
9041 ast_channel_name(ast));
9042 }
9043
9044 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
9045
9046 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
9047 mute = ast_dsp_was_muted(p->dsp);
9048 if (p->muting != mute) {
9049 p->muting = mute;
9050 dahdi_confmute(p, mute);
9051 }
9052
9053 if (f) {
9054 if ((p->dsp_features & DSP_FEATURE_WAITDIALTONE) && (p->dialtone_detect > 0)
9055 && !p->outgoing && ast_channel_state(ast) == AST_STATE_UP) {
9056 if (++p->dialtone_scanning_time_elapsed >= p->dialtone_detect) {
9057 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
9058 ast_dsp_set_features(p->dsp, p->dsp_features);
9059 }
9060 }
9061 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
9062 if ((ast_channel_state(ast) == AST_STATE_UP) && !p->outgoing) {
9063 /*
9064 * Treat this as a "hangup" instead of a "busy" on the
9065 * assumption that a busy means the incoming call went away.
9066 */
9067 ast_frfree(f);
9068 f = NULL;
9069 }
9070 } else if (p->dialtone_detect && !p->outgoing && f->frametype == AST_FRAME_VOICE) {
9071 if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE) && (ast_dsp_get_tcount(p->dsp) > 9)) {
9072 /* Dialtone detected on inbound call; hangup the channel */
9073 ast_frfree(f);
9074 f = NULL;
9075 }
9076 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
9077 || f->frametype == AST_FRAME_DTMF_END) {
9078 #ifdef HAVE_PRI
9079 if (dahdi_sig_pri_lib_handles(p->sig)
9080 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
9081 && p->pri
9082 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
9083 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
9084 /* Don't accept in-band DTMF when in overlap dial mode */
9085 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
9086 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
9087 (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
9088
9089 f->frametype = AST_FRAME_NULL;
9090 f->subclass.integer = 0;
9091 }
9092 #endif
9093 /* DSP clears us of being pulse */
9094 p->pulsedial = 0;
9095 } else if (p->waitingfordt.tv_sec) {
9096 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
9097 p->waitingfordt.tv_sec = 0;
9098 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
9099 ast_frfree(f);
9100 f = NULL;
9101 } else if (f->frametype == AST_FRAME_VOICE) {
9102 f->frametype = AST_FRAME_NULL;
9103 f->subclass.integer = 0;
9104 if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE || ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_RINGING) && ast_dsp_get_tcount(p->dsp) > 9) {
9105 p->waitingfordt.tv_sec = 0;
9106 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
9107 ast_dsp_set_features(p->dsp, p->dsp_features);
9108 ast_debug(1, "Got 10 samples of dialtone!\n");
9109 if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
9110 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
9111 if (res) {
9112 p->dop.dialstr[0] = '\0';
9113 ast_mutex_unlock(&p->lock);
9114 ast_frfree(f);
9115 return NULL;
9116 } else {
9117 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
9118 p->dialing = 1;
9119 p->dop.dialstr[0] = '\0';
9120 p->dop.op = DAHDI_DIAL_OP_REPLACE;
9121 ast_setstate(ast, AST_STATE_DIALING);
9122 }
9123 }
9124 }
9125 }
9126 }
9127 }
9128 } else
9129 f = &p->subs[idx].f;
9130
9131 if (f) {
9132 switch (f->frametype) {
9133 case AST_FRAME_DTMF_BEGIN:
9134 case AST_FRAME_DTMF_END:
9135 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
9136 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
9137 } else {
9138 dahdi_handle_dtmf(ast, idx, &f);
9139 }
9140 if (!(p->dialmode == ANALOG_DIALMODE_BOTH || p->dialmode == ANALOG_DIALMODE_DTMF)) {
9141 if (f->frametype == AST_FRAME_DTMF_END) { /* only show this message when the key is let go of */
9142 ast_debug(1, "Dropping DTMF digit '%c' because tone dialing is disabled\n", f->subclass.integer);
9143 }
9144 f->frametype = AST_FRAME_NULL;
9145 f->subclass.integer = 0;
9146 }
9147 break;
9148 case AST_FRAME_VOICE:
9149 if (p->cidspill || p->cid_suppress_expire) {
9150 /* We are/were sending a caller id spill. Suppress any echo. */
9151 p->subs[idx].f.frametype = AST_FRAME_NULL;
9152 p->subs[idx].f.subclass.integer = 0;
9153 p->subs[idx].f.samples = 0;
9154 p->subs[idx].f.mallocd = 0;
9155 p->subs[idx].f.offset = 0;
9156 p->subs[idx].f.data.ptr = NULL;
9157 p->subs[idx].f.datalen= 0;
9158 }
9159 break;
9160 default:
9161 break;
9162 }
9163 }
9164
9165 ast_mutex_unlock(&p->lock);
9166 return f;
9167 }
9168
9169 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
9170 {
9171 int sent=0;
9172 int size;
9173 int res;
9174 int fd;
9175 fd = p->subs[idx].dfd;
9176 while (len) {
9177 size = len;
9178 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
9179 size = (linear ? READ_SIZE * 2 : READ_SIZE);
9180 res = write(fd, buf, size);
9181 if (res != size) {
9182 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
9183 return sent;
9184 }
9185 len -= size;
9186 buf += size;
9187 }
9188 return sent;
9189 }
9190
9191 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
9192 {
9193 struct dahdi_pvt *p;
9194 int res;
9195 int idx;
9196
9197 /* Write a frame of (presumably voice) data */
9198 if (frame->frametype != AST_FRAME_VOICE) {
9199 if (frame->frametype != AST_FRAME_IMAGE) {
9200 ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n",
9201 frame->frametype);
9202 }
9203 return 0;
9204 }
9205
9206 /* Return if it's not valid data */
9207 if (!frame->data.ptr || !frame->datalen) {
9208 return 0;
9209 }
9210
9211 p = ast_channel_tech_pvt(ast);
9212 ast_mutex_lock(&p->lock);
9213
9214 idx = dahdi_get_index(ast, p, 0);
9215 if (idx < 0) {
9216 ast_mutex_unlock(&p->lock);
9217 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast_channel_name(ast));
9218 return -1;
9219 }
9220
9221 if (p->dialing) {
9222 ast_mutex_unlock(&p->lock);
9223 ast_debug(5, "Dropping frame since I'm still dialing on %s...\n",
9224 ast_channel_name(ast));
9225 return 0;
9226 }
9227 if (!p->owner) {
9228 ast_mutex_unlock(&p->lock);
9229 ast_debug(5, "Dropping frame since there is no active owner on %s...\n",
9230 ast_channel_name(ast));
9231 return 0;
9232 }
9233 if (p->cidspill) {
9234 ast_mutex_unlock(&p->lock);
9235 ast_debug(5, "Dropping frame since I've still got a callerid spill on %s...\n",
9236 ast_channel_name(ast));
9237 return 0;
9238 }
9239
9240 if (ast_format_cmp(frame->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
9241 if (!p->subs[idx].linear) {
9242 p->subs[idx].linear = 1;
9243 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
9244 if (res)
9245 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
9246 }
9247 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
9248 } else if (ast_format_cmp(frame->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL
9249 || ast_format_cmp(frame->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
9250 /* x-law already */
9251 if (p->subs[idx].linear) {
9252 p->subs[idx].linear = 0;
9253 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
9254 if (res)
9255 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
9256 }
9257 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
9258 } else {
9259 ast_mutex_unlock(&p->lock);
9260 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n",
9261 ast_format_get_name(frame->subclass.format));
9262 return -1;
9263 }
9264 ast_mutex_unlock(&p->lock);
9265 if (res < 0) {
9266 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
9267 return -1;
9268 }
9269 return 0;
9270 }
9271
9272 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
9273 {
9274 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
9275 int res=-1;
9276 int idx;
9277 int func = DAHDI_FLASH;
9278
9279 ast_mutex_lock(&p->lock);
9280 ast_debug(1, "Requested indication %d on channel %s\n", condition, ast_channel_name(chan));
9281 switch (p->sig) {
9282 #if defined(HAVE_PRI)
9283 case SIG_PRI_LIB_HANDLE_CASES:
9284 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
9285 ast_mutex_unlock(&p->lock);
9286 return res;
9287 #endif /* defined(HAVE_PRI) */
9288 #if defined(HAVE_SS7)
9289 case SIG_SS7:
9290 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
9291 ast_mutex_unlock(&p->lock);
9292 return res;
9293 #endif /* defined(HAVE_SS7) */
9294 default:
9295 break;
9296 }
9297 #ifdef HAVE_OPENR2
9298 if (p->mfcr2 && !p->mfcr2_call_accepted) {
9299 ast_mutex_unlock(&p->lock);
9300 /* if this is an R2 call and the call is not yet accepted, we don't want the
9301 tone indications to mess up with the MF tones */
9302 return 0;
9303 }
9304 #endif
9305 idx = dahdi_get_index(chan, p, 0);
9306 if (idx == SUB_REAL) {
9307 switch (condition) {
9308 case AST_CONTROL_BUSY:
9309 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
9310 break;
9311 case AST_CONTROL_RINGING:
9312 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
9313
9314 if (ast_channel_state(chan) != AST_STATE_UP) {
9315 if ((ast_channel_state(chan) != AST_STATE_RING) ||
9316 ((p->sig != SIG_FXSKS) &&
9317 (p->sig != SIG_FXSLS) &&
9318 (p->sig != SIG_FXSGS)))
9319 ast_setstate(chan, AST_STATE_RINGING);
9320 }
9321 break;
9322 case AST_CONTROL_INCOMPLETE:
9323 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", ast_channel_name(chan));
9324 /* act as a progress or proceeding, allowing the caller to enter additional numbers */
9325 res = 0;
9326 break;
9327 case AST_CONTROL_PROCEEDING:
9328 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", ast_channel_name(chan));
9329 /* don't continue in ast_indicate */
9330 res = 0;
9331 break;
9332 case AST_CONTROL_PROGRESS:
9333 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", ast_channel_name(chan));
9334 /* don't continue in ast_indicate */
9335 res = 0;
9336 break;
9337 case AST_CONTROL_CONGESTION:
9338 /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
9339 switch (ast_channel_hangupcause(chan)) {
9340 case AST_CAUSE_USER_BUSY:
9341 case AST_CAUSE_NORMAL_CLEARING:
9342 case 0:/* Cause has not been set. */
9343 /* Supply a more appropriate cause. */
9344 ast_channel_hangupcause_set(chan, AST_CAUSE_CONGESTION);
9345 break;
9346 default:
9347 break;
9348 }
9349 break;
9350 case AST_CONTROL_HOLD:
9351 ast_moh_start(chan, data, p->mohinterpret);
9352 break;
9353 case AST_CONTROL_UNHOLD:
9354 ast_moh_stop(chan);
9355 break;
9356 case AST_CONTROL_RADIO_KEY:
9357 if (p->radio)
9358 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
9359 res = 0;
9360 break;
9361 case AST_CONTROL_RADIO_UNKEY:
9362 if (p->radio)
9363 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
9364 res = 0;
9365 break;
9366 case AST_CONTROL_FLASH:
9367 /* flash hookswitch */
9368 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
9369 /* Clear out the dial buffer */
9370 p->dop.dialstr[0] = '\0';
9371 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
9372 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
9373 ast_channel_name(chan), strerror(errno));
9374 } else
9375 res = 0;
9376 } else
9377 res = 0;
9378 break;
9379 case AST_CONTROL_SRCUPDATE:
9380 res = 0;
9381 break;
9382 case -1:
9383 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9384 break;
9385 }
9386 } else {
9387 res = 0;
9388 }
9389 ast_mutex_unlock(&p->lock);
9390 return res;
9391 }
9392
9393 #if defined(HAVE_PRI)
9394 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
9395 #else
9396 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
9397 #endif /* defined(HAVE_PRI) */
9398 {
9399 struct ast_str *chan_name;
9400 int x, y;
9401
9402 /* Create the new channel name tail. */
9403 if (!(chan_name = ast_str_create(32))) {
9404 return NULL;
9405 }
9406 if (i->channel == CHAN_PSEUDO) {
9407 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
9408 #if defined(HAVE_PRI)
9409 } else if (i->pri) {
9410 ast_mutex_lock(&i->pri->lock);
9411 y = ++i->pri->new_chan_seq;
9412 if (is_outgoing) {
9413 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y);
9414 address[0] = '\0';
9415 } else if (ast_strlen_zero(i->cid_subaddr)) {
9416 /* Put in caller-id number only since there is no subaddress. */
9417 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y);
9418 } else {
9419 /* Put in caller-id number and subaddress. */
9420 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
9421 i->cid_subaddr, (unsigned)y);
9422 }
9423 ast_mutex_unlock(&i->pri->lock);
9424 #endif /* defined(HAVE_PRI) */
9425 } else {
9426 y = 1;
9427 do {
9428 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
9429 for (x = 0; x < 3; ++x) {
9430 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
9431 ast_channel_name(i->subs[x].owner) + 6)) {
9432 break;
9433 }
9434 }
9435 ++y;
9436 } while (x < 3);
9437 }
9438 return chan_name;
9439 }
9440
9441 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)
9442 {
9443 struct ast_channel *new_channel = dahdi_new(i, state, startpbx, idx, law, assignedids, requestor, callid);
9444
9445 ast_callid_threadstorage_auto_clean(callid, callid_created);
9446
9447 return new_channel;
9448 }
9449
9450 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)
9451 {
9452 struct ast_channel *tmp;
9453 struct ast_format_cap *caps;
9454 struct ast_format *deflaw;
9455 int x;
9456 int features;
9457 struct ast_str *chan_name;
9458 struct ast_variable *v;
9459 char *dashptr;
9460 char device_name[AST_CHANNEL_NAME];
9461
9462 if (i->subs[idx].owner) {
9463 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
9464 return NULL;
9465 }
9466
9467 #if defined(HAVE_PRI)
9468 /*
9469 * The dnid has been stuffed with the called-number[:subaddress]
9470 * by dahdi_request() for outgoing calls.
9471 */
9472 chan_name = create_channel_name(i, i->outgoing, i->dnid);
9473 #else
9474 chan_name = create_channel_name(i);
9475 #endif /* defined(HAVE_PRI) */
9476 if (!chan_name) {
9477 return NULL;
9478 }
9479
9480 caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
9481 if (!caps) {
9482 ast_free(chan_name);
9483 return NULL;
9484 }
9485
9486 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));
9487 ast_free(chan_name);
9488 if (!tmp) {
9489 ao2_ref(caps, -1);
9490 return NULL;
9491 }
9492
9493 ast_channel_stage_snapshot(tmp);
9494
9495 if (callid) {
9496 ast_channel_callid_set(tmp, callid);
9497 }
9498
9499 ast_channel_tech_set(tmp, &dahdi_tech);
9500 #if defined(HAVE_PRI)
9501 if (i->pri) {
9502 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
9503 }
9504 #endif /* defined(HAVE_PRI) */
9505 ast_channel_cc_params_init(tmp, i->cc_params);
9506 if (law) {
9507 i->law = law;
9508 if (law == DAHDI_LAW_ALAW) {
9509 deflaw = ast_format_alaw;
9510 } else {
9511 deflaw = ast_format_ulaw;
9512 }
9513 } else {
9514 switch (i->sig) {
9515 case SIG_PRI_LIB_HANDLE_CASES:
9516 /* Make sure companding law is known. */
9517 i->law = (i->law_default == DAHDI_LAW_ALAW)
9518 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
9519 break;
9520 default:
9521 i->law = i->law_default;
9522 break;
9523 }
9524 if (i->law_default == DAHDI_LAW_ALAW) {
9525 deflaw = ast_format_alaw;
9526 } else {
9527 deflaw = ast_format_ulaw;
9528 }
9529 }
9530 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
9531 ast_format_cap_append(caps, deflaw, 0);
9532 ast_channel_nativeformats_set(tmp, caps);
9533 ao2_ref(caps, -1);
9534 /* Start out assuming ulaw since it's smaller :) */
9535 ast_channel_set_rawreadformat(tmp, deflaw);
9536 ast_channel_set_readformat(tmp, deflaw);
9537 ast_channel_set_rawwriteformat(tmp, deflaw);
9538 ast_channel_set_writeformat(tmp, deflaw);
9539 i->subs[idx].linear = 0;
9540 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
9541 features = 0;
9542 if (idx == SUB_REAL) {
9543 if (i->busydetect && CANBUSYDETECT(i))
9544 features |= DSP_FEATURE_BUSY_DETECT;
9545 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
9546 features |= DSP_FEATURE_CALL_PROGRESS;
9547 if ((i->waitfordialtone || i->dialtone_detect) && CANPROGRESSDETECT(i))
9548 features |= DSP_FEATURE_WAITDIALTONE;
9549 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
9550 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
9551 features |= DSP_FEATURE_FAX_DETECT;
9552 }
9553 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
9554 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
9555 i->hardwaredtmf = 0;
9556 features |= DSP_FEATURE_DIGIT_DETECT;
9557 } else if (NEED_MFDETECT(i)) {
9558 i->hardwaredtmf = 1;
9559 features |= DSP_FEATURE_DIGIT_DETECT;
9560 }
9561 }
9562 if (features) {
9563 if (i->dsp) {
9564 ast_debug(1, "Already have a dsp on %s?\n", ast_channel_name(tmp));
9565 } else {
9566 if (i->channel != CHAN_PSEUDO)
9567 i->dsp = ast_dsp_new();
9568 else
9569 i->dsp = NULL;
9570 if (i->dsp) {
9571 i->dsp_features = features;
9572 #if defined(HAVE_PRI) || defined(HAVE_SS7)
9573 /* We cannot do progress detection until receive PROGRESS message */
9574 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
9575 /* Remember requested DSP features, don't treat
9576 talking as ANSWER */
9577 i->dsp_features = features & ~DSP_PROGRESS_TALK;
9578 features = 0;
9579 }
9580 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9581 ast_dsp_set_features(i->dsp, features);
9582 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
9583 if (!ast_strlen_zero(progzone))
9584 ast_dsp_set_call_progress_zone(i->dsp, progzone);
9585 if (i->busydetect && CANBUSYDETECT(i)) {
9586 ast_dsp_set_busy_count(i->dsp, i->busycount);
9587 ast_dsp_set_busy_pattern(i->dsp, &i->busy_cadence);
9588 }
9589 }
9590 }
9591 }
9592
9593 i->dialtone_scanning_time_elapsed = 0;
9594
9595 if (state == AST_STATE_RING)
9596 ast_channel_rings_set(tmp, 1);
9597 ast_channel_tech_pvt_set(tmp, i);
9598 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
9599 /* Only FXO signalled stuff can be picked up */
9600 ast_channel_callgroup_set(tmp, i->callgroup);
9601 ast_channel_pickupgroup_set(tmp, i->pickupgroup);
9602 ast_channel_named_callgroups_set(tmp, i->named_callgroups);
9603 ast_channel_named_pickupgroups_set(tmp, i->named_pickupgroups);
9604 }
9605 if (!ast_strlen_zero(i->parkinglot))
9606 ast_channel_parkinglot_set(tmp, i->parkinglot);
9607 if (!ast_strlen_zero(i->language))
9608 ast_channel_language_set(tmp, i->language);
9609 if (!i->owner)
9610 i->owner = tmp;
9611 if (!ast_strlen_zero(i->accountcode))
9612 ast_channel_accountcode_set(tmp, i->accountcode);
9613 if (i->amaflags)
9614 ast_channel_amaflags_set(tmp, i->amaflags);
9615 i->subs[idx].owner = tmp;
9616 ast_channel_context_set(tmp, i->context);
9617 if (!dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
9618 ast_channel_call_forward_set(tmp, i->call_forward);
9619 }
9620 /* If we've been told "no ADSI" then enforce it */
9621 if (!i->adsi)
9622 ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
9623 if (!ast_strlen_zero(i->exten))
9624 ast_channel_exten_set(tmp, i->exten);
9625 if (!ast_strlen_zero(i->rdnis)) {
9626 ast_channel_redirecting(tmp)->from.number.valid = 1;
9627 ast_channel_redirecting(tmp)->from.number.str = ast_strdup(i->rdnis);
9628 }
9629 if (!ast_strlen_zero(i->dnid)) {
9630 ast_channel_dialed(tmp)->number.str = ast_strdup(i->dnid);
9631 }
9632
9633 /* Don't use ast_set_callerid() here because it will
9634 * generate a needless NewCallerID event */
9635 #if defined(HAVE_PRI) || defined(HAVE_SS7)
9636 if (!ast_strlen_zero(i->cid_ani)) {
9637 ast_channel_caller(tmp)->ani.number.valid = 1;
9638 ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_ani);
9639 } else if (!ast_strlen_zero(i->cid_num)) {
9640 ast_channel_caller(tmp)->ani.number.valid = 1;
9641 ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
9642 }
9643 #else
9644 if (!ast_strlen_zero(i->cid_num)) {
9645 ast_channel_caller(tmp)->ani.number.valid = 1;
9646 ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
9647 }
9648 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9649 ast_channel_caller(tmp)->id.name.presentation = i->callingpres;
9650 ast_channel_caller(tmp)->id.number.presentation = i->callingpres;
9651 ast_channel_caller(tmp)->id.number.plan = i->cid_ton;
9652 ast_channel_caller(tmp)->ani2 = i->cid_ani2;
9653 ast_channel_caller(tmp)->id.tag = ast_strdup(i->cid_tag);
9654 /* clear the fake event in case we posted one before we had ast_channel */
9655 i->fake_event = 0;
9656 /* Assure there is no confmute on this channel */
9657 dahdi_confmute(i, 0);
9658 i->muting = 0;
9659 /* Configure the new channel jb */
9660 ast_jb_configure(tmp, &global_jbconf);
9661
9662 /* Set initial device state */
9663 ast_copy_string(device_name, ast_channel_name(tmp), sizeof(device_name));
9664 dashptr = strrchr(device_name, '-');
9665 if (dashptr) {
9666 *dashptr = '\0';
9667 }
9668 ast_set_flag(ast_channel_flags(tmp), AST_FLAG_DISABLE_DEVSTATE_CACHE);
9669 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name);
9670
9671 for (v = i->vars ; v ; v = v->next)
9672 pbx_builtin_setvar_helper(tmp, v->name, v->value);
9673
9674 ast_channel_stage_snapshot_done(tmp);
9675
9676 ast_channel_unlock(tmp);
9677
9678 ast_module_ref(ast_module_info->self);
9679
9680 dahdi_ami_channel_event(i, tmp);
9681 if (startpbx) {
9682 #ifdef HAVE_OPENR2
9683 if (i->mfcr2call) {
9684 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
9685 }
9686 #endif
9687 if (ast_pbx_start(tmp)) {
9688 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
9689 ast_hangup(tmp);
9690 return NULL;
9691 }
9692 }
9693 return tmp;
9694 }
9695
9696
9697 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
9698 {
9699 char c;
9700
9701 *str = 0; /* start with empty output buffer */
9702 for (;;)
9703 {
9704 /* Wait for the first digit (up to specified ms). */
9705 c = ast_waitfordigit(chan, ms);
9706 /* if timeout, hangup or error, return as such */
9707 if (c < 1)
9708 return c;
9709 *str++ = c;
9710 *str = 0;
9711 if (strchr(term, c))
9712 return 1;
9713 }
9714 }
9715
9716 static int dahdi_wink(struct dahdi_pvt *p, int idx)
9717 {
9718 int j;
9719 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
9720 for (;;)
9721 {
9722 /* set bits of interest */
9723 j = DAHDI_IOMUX_SIGEVENT;
9724 /* wait for some happening */
9725 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
9726 /* exit loop if we have it */
9727 if (j & DAHDI_IOMUX_SIGEVENT) break;
9728 }
9729 /* get the event info */
9730 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
9731 return 0;
9732 }
9733
9734 static void publish_dnd_state(int channel, const char *status)
9735 {
9736 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
9737 RAII_VAR(struct ast_str *, dahdichan, ast_str_create(32), ast_free);
9738 if (!dahdichan) {
9739 return;
9740 }
9741
9742 ast_str_set(&dahdichan, 0, "%d", channel);
9743
9744 body = ast_json_pack("{s: s, s: s}",
9745 "DAHDIChannel", ast_str_buffer(dahdichan),
9746 "Status", status);
9747 if (!body) {
9748 return;
9749 }
9750
9751 ast_manager_publish_event("DNDState", EVENT_FLAG_SYSTEM, body);
9752 }
9753
9754 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
9755 * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
9756 * \param flag on 1 to enable, 0 to disable, -1 return dnd value
9757 *
9758 * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
9759 * DAHDI channel). Use this to enable or disable it.
9760 *
9761 * \bug the use of the word "channel" for those dahdichans is really confusing.
9762 */
9763 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
9764 {
9765 if (dahdi_analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
9766 return analog_dnd(dahdichan->sig_pvt, flag);
9767 }
9768
9769 if (flag == -1) {
9770 return dahdichan->dnd;
9771 }
9772
9773 /* Do not disturb */
9774 dahdichan->dnd = flag;
9775 ast_verb(3, "%s DND on channel %d\n",
9776 flag? "Enabled" : "Disabled",
9777 dahdichan->channel);
9778 publish_dnd_state(dahdichan->channel, flag ? "enabled" : "disabled");
9779 return 0;
9780 }
9781
9782 static int canmatch_featurecode(const char *pickupexten, const char *exten)
9783 {
9784 int extlen = strlen(exten);
9785
9786 if (!extlen) {
9787 return 1;
9788 }
9789
9790 if (extlen < strlen(pickupexten) && !strncmp(pickupexten, exten, extlen)) {
9791 return 1;
9792 }
9793 /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
9794 if (exten[0] == '*' && extlen < 3) {
9795 if (extlen == 1) {
9796 return 1;
9797 }
9798 /* "*0" should be processed before it gets here */
9799 switch (exten[1]) {
9800 case '6':
9801 case '7':
9802 case '8':
9803 return 1;
9804 }
9805 }
9806 return 0;
9807 }
9808
9809 static void *analog_ss_thread(void *data)
9810 {
9811 struct ast_channel *chan = data;
9812 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
9813 char exten[AST_MAX_EXTENSION] = "";
9814 char exten2[AST_MAX_EXTENSION] = "";
9815 unsigned char buf[256];
9816 char dtmfcid[300];
9817 char dtmfbuf[300];
9818 struct callerid_state *cs = NULL;
9819 char *name = NULL, *number = NULL;
9820 int distMatches;
9821 int curRingData[3];
9822 int receivedRingT;
9823 int counter1;
9824 int counter;
9825 int samples = 0;
9826 struct ast_smdi_md_message *smdi_msg = NULL;
9827 int flags = 0;
9828 int i;
9829 int timeout;
9830 int getforward = 0;
9831 char *s1, *s2;
9832 int len = 0;
9833 int res;
9834 int idx;
9835 RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
9836 const char *pickupexten;
9837
9838 ast_mutex_lock(&ss_thread_lock);
9839 ss_thread_count++;
9840 ast_mutex_unlock(&ss_thread_lock);
9841 /* in the bizarre case where the channel has become a zombie before we
9842 even get started here, abort safely
9843 */
9844 if (!p) {
9845 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", ast_channel_name(chan));
9846 ast_hangup(chan);
9847 goto quit;
9848 }
9849 ast_verb(3, "Starting simple switch on '%s'\n", ast_channel_name(chan));
9850 idx = dahdi_get_index(chan, p, 1);
9851 if (idx < 0) {
9852 ast_log(LOG_WARNING, "Huh?\n");
9853 ast_hangup(chan);
9854 goto quit;
9855 }
9856
9857 ast_channel_lock(chan);
9858 pickup_cfg = ast_get_chan_features_pickup_config(chan);
9859 if (!pickup_cfg) {
9860 ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
9861 pickupexten = "";
9862 } else {
9863 pickupexten = ast_strdupa(pickup_cfg->pickupexten);
9864 }
9865 ast_channel_unlock(chan);
9866
9867 if (p->dsp)
9868 ast_dsp_digitreset(p->dsp);
9869 switch (p->sig) {
9870 case SIG_FEATD:
9871 case SIG_FEATDMF:
9872 case SIG_FEATDMF_TA:
9873 case SIG_E911:
9874 case SIG_FGC_CAMAMF:
9875 case SIG_FEATB:
9876 case SIG_EMWINK:
9877 case SIG_SF_FEATD:
9878 case SIG_SF_FEATDMF:
9879 case SIG_SF_FEATB:
9880 case SIG_SFWINK:
9881 if (dahdi_wink(p, idx))
9882 goto quit;
9883 /* Fall through */
9884 case SIG_EM:
9885 case SIG_EM_E1:
9886 case SIG_SF:
9887 case SIG_FGC_CAMA:
9888 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9889 if (p->dsp)
9890 ast_dsp_digitreset(p->dsp);
9891 /* set digit mode appropriately */
9892 if (p->dsp) {
9893 if (NEED_MFDETECT(p))
9894 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
9895 else
9896 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
9897 }
9898 memset(dtmfbuf, 0, sizeof(dtmfbuf));
9899 /* Wait for the first digit only if immediate=no */
9900 if (!p->immediate)
9901 /* Wait for the first digit (up to 5 seconds). */
9902 res = ast_waitfordigit(chan, 5000);
9903 else
9904 res = 0;
9905 if (res > 0) {
9906 /* save first char */
9907 dtmfbuf[0] = res;
9908 switch (p->sig) {
9909 case SIG_FEATD:
9910 case SIG_SF_FEATD:
9911 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
9912 if (res > 0)
9913 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
9914 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9915 break;
9916 case SIG_FEATDMF_TA:
9917 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9918 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9919 if (dahdi_wink(p, idx)) goto quit;
9920 dtmfbuf[0] = 0;
9921 /* Wait for the first digit (up to 5 seconds). */
9922 res = ast_waitfordigit(chan, 5000);
9923 if (res <= 0) break;
9924 dtmfbuf[0] = res;
9925 /* fall through intentionally */
9926 case SIG_FEATDMF:
9927 case SIG_E911:
9928 case SIG_FGC_CAMAMF:
9929 case SIG_SF_FEATDMF:
9930 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9931 /* if international caca, do it again to get real ANO */
9932 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
9933 {
9934 if (dahdi_wink(p, idx)) goto quit;
9935 dtmfbuf[0] = 0;
9936 /* Wait for the first digit (up to 5 seconds). */
9937 res = ast_waitfordigit(chan, 5000);
9938 if (res <= 0) break;
9939 dtmfbuf[0] = res;
9940 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9941 }
9942 if (res > 0) {
9943 /* if E911, take off hook */
9944 if (p->sig == SIG_E911)
9945 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
9946 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
9947 }
9948 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9949 break;
9950 case SIG_FEATB:
9951 case SIG_SF_FEATB:
9952 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9953 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9954 break;
9955 case SIG_EMWINK:
9956 /* if we received a '*', we are actually receiving Feature Group D
9957 dial syntax, so use that mode; otherwise, fall through to normal
9958 mode
9959 */
9960 if (res == '*') {
9961 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
9962 if (res > 0)
9963 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
9964 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9965 break;
9966 }
9967 default:
9968 /* If we got the first digit, get the rest */
9969 len = 1;
9970 dtmfbuf[len] = '\0';
9971 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
9972 if (ast_exists_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
9973 timeout = p->matchdigit_timeout;
9974 } else {
9975 timeout = p->interdigit_timeout;
9976 }
9977 res = ast_waitfordigit(chan, timeout);
9978 if (res < 0) {
9979 ast_debug(1, "waitfordigit returned < 0...\n");
9980 ast_hangup(chan);
9981 goto quit;
9982 } else if (res) {
9983 dtmfbuf[len++] = res;
9984 dtmfbuf[len] = '\0';
9985 } else {
9986 break;
9987 }
9988 }
9989 break;
9990 }
9991 }
9992 if (res == -1) {
9993 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
9994 ast_hangup(chan);
9995 goto quit;
9996 } else if (res < 0) {
9997 ast_debug(1, "Got hung up before digits finished\n");
9998 ast_hangup(chan);
9999 goto quit;
10000 }
10001
10002 if (p->sig == SIG_FGC_CAMA) {
10003 char anibuf[100];
10004
10005 if (ast_safe_sleep(chan,1000) == -1) {
10006 ast_hangup(chan);
10007 goto quit;
10008 }
10009 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10010 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10011 res = my_getsigstr(chan, anibuf, "#", 10000);
10012 if ((res > 0) && (strlen(anibuf) > 2)) {
10013 if (anibuf[strlen(anibuf) - 1] == '#')
10014 anibuf[strlen(anibuf) - 1] = 0;
10015 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10016 }
10017 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10018 }
10019
10020 ast_copy_string(exten, dtmfbuf, sizeof(exten));
10021 if (ast_strlen_zero(exten))
10022 ast_copy_string(exten, "s", sizeof(exten));
10023 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10024 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
10025 if (exten[0] == '*') {
10026 char *stringp=NULL;
10027 ast_copy_string(exten2, exten, sizeof(exten2));
10028 /* Parse out extension and callerid */
10029 stringp=exten2 +1;
10030 s1 = strsep(&stringp, "*");
10031 s2 = strsep(&stringp, "*");
10032 if (s2) {
10033 if (!ast_strlen_zero(p->cid_num))
10034 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10035 else
10036 ast_set_callerid(chan, s1, NULL, s1);
10037 ast_copy_string(exten, s2, sizeof(exten));
10038 } else
10039 ast_copy_string(exten, s1, sizeof(exten));
10040 } else if (p->sig == SIG_FEATD)
10041 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10042 }
10043 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10044 if (exten[0] == '*') {
10045 char *stringp=NULL;
10046 ast_copy_string(exten2, exten, sizeof(exten2));
10047 /* Parse out extension and callerid */
10048 stringp=exten2 +1;
10049 s1 = strsep(&stringp, "#");
10050 s2 = strsep(&stringp, "#");
10051 if (s2) {
10052 if (!ast_strlen_zero(p->cid_num))
10053 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10054 else
10055 if (*(s1 + 2))
10056 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10057 ast_copy_string(exten, s2 + 1, sizeof(exten));
10058 } else
10059 ast_copy_string(exten, s1 + 2, sizeof(exten));
10060 } else
10061 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10062 }
10063 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10064 if (exten[0] == '*') {
10065 char *stringp=NULL;
10066 ast_copy_string(exten2, exten, sizeof(exten2));
10067 /* Parse out extension and callerid */
10068 stringp=exten2 +1;
10069 s1 = strsep(&stringp, "#");
10070 s2 = strsep(&stringp, "#");
10071 if (s2 && (*(s2 + 1) == '0')) {
10072 if (*(s2 + 2))
10073 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10074 }
10075 if (s1) ast_copy_string(exten, s1, sizeof(exten));
10076 else ast_copy_string(exten, "911", sizeof(exten));
10077 } else
10078 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10079 }
10080 if (p->sig == SIG_FEATB) {
10081 if (exten[0] == '*') {
10082 char *stringp=NULL;
10083 ast_copy_string(exten2, exten, sizeof(exten2));
10084 /* Parse out extension and callerid */
10085 stringp=exten2 +1;
10086 s1 = strsep(&stringp, "#");
10087 ast_copy_string(exten, exten2 + 1, sizeof(exten));
10088 } else
10089 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10090 }
10091 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10092 dahdi_wink(p, idx);
10093 /* some switches require a minimum guard time between
10094 the last FGD wink and something that answers
10095 immediately. This ensures it */
10096 if (ast_safe_sleep(chan, 100)) {
10097 ast_hangup(chan);
10098 goto quit;
10099 }
10100 }
10101 dahdi_ec_enable(p);
10102 if (NEED_MFDETECT(p)) {
10103 if (p->dsp) {
10104 if (!p->hardwaredtmf)
10105 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10106 else {
10107 ast_dsp_free(p->dsp);
10108 p->dsp = NULL;
10109 }
10110 }
10111 }
10112
10113 if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1,
10114 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
10115 ast_channel_exten_set(chan, exten);
10116 if (p->dsp) ast_dsp_digitreset(p->dsp);
10117 res = ast_pbx_run(chan);
10118 if (res) {
10119 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10120 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10121 }
10122 goto quit;
10123 } else {
10124 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, ast_channel_context(chan));
10125 sleep(2);
10126 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10127 if (res < 0)
10128 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10129 else
10130 sleep(1);
10131 res = ast_streamfile(chan, "ss-noservice", ast_channel_language(chan));
10132 if (res >= 0)
10133 ast_waitstream(chan, "");
10134 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10135 ast_hangup(chan);
10136 goto quit;
10137 }
10138 break;
10139 case SIG_FXOLS:
10140 case SIG_FXOGS:
10141 case SIG_FXOKS:
10142 /* Read the first digit */
10143 timeout = p->firstdigit_timeout;
10144 /* If starting a threeway call, never timeout on the first digit so someone
10145 can use flash-hook as a "hold" feature */
10146 if (p->subs[SUB_THREEWAY].owner)
10147 timeout = INT_MAX;
10148 while (len < AST_MAX_EXTENSION-1) {
10149 int is_exten_parking = 0;
10150
10151 /* Read digit unless it's supposed to be immediate, in which case the
10152 only answer is 's' */
10153 if (p->immediate)
10154 res = 's';
10155 else
10156 res = ast_waitfordigit(chan, timeout);
10157 timeout = 0;
10158 if (res < 0) {
10159 ast_debug(1, "waitfordigit returned < 0...\n");
10160 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10161 ast_hangup(chan);
10162 goto quit;
10163 } else if (res) {
10164 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10165 exten[len++]=res;
10166 exten[len] = '\0';
10167 }
10168 if (!ast_ignore_pattern(ast_channel_context(chan), exten)) {
10169 tone_zone_play_tone(p->subs[idx].dfd, -1);
10170 } else {
10171 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10172 }
10173 if (ast_parking_provider_registered()) {
10174 is_exten_parking = ast_parking_is_exten_park(ast_channel_context(chan), exten);
10175 }
10176 if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num) && !is_exten_parking) {
10177 if (!res || !ast_matchmore_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
10178 if (getforward) {
10179 /* Record this as the forwarding extension */
10180 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10181 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10182 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10183 if (res)
10184 break;
10185 usleep(500000);
10186 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10187 sleep(1);
10188 memset(exten, 0, sizeof(exten));
10189 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10190 len = 0;
10191 getforward = 0;
10192 } else {
10193 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10194 ast_channel_lock(chan);
10195 ast_channel_exten_set(chan, exten);
10196 if (!ast_strlen_zero(p->cid_num)) {
10197 if (!p->hidecallerid)
10198 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10199 else
10200 ast_set_callerid(chan, NULL, NULL, p->cid_num);
10201 }
10202 if (!ast_strlen_zero(p->cid_name)) {
10203 if (!p->hidecallerid)
10204 ast_set_callerid(chan, NULL, p->cid_name, NULL);
10205 }
10206 ast_setstate(chan, AST_STATE_RING);
10207 ast_channel_unlock(chan);
10208 dahdi_ec_enable(p);
10209 res = ast_pbx_run(chan);
10210 if (res) {
10211 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10212 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10213 }
10214 goto quit;
10215 }
10216 } else {
10217 /* It's a match, but they just typed a digit, and there is an ambiguous match,
10218 so just set the timeout to matchdigit_timeout and wait some more */
10219 timeout = p->matchdigit_timeout;
10220 }
10221 } else if (res == 0) {
10222 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10223 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10224 dahdi_wait_event(p->subs[idx].dfd);
10225 ast_hangup(chan);
10226 goto quit;
10227 } else if (p->callwaiting && !strcmp(exten, "*70")) {
10228 ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan));
10229 /* Disable call waiting if enabled */
10230 p->callwaiting = 0;
10231 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10232 if (res) {
10233 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10234 ast_channel_name(chan), strerror(errno));
10235 }
10236 len = 0;
10237 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10238 memset(exten, 0, sizeof(exten));
10239 timeout = p->firstdigit_timeout;
10240
10241 } else if (!strcmp(exten, pickupexten)) {
10242 /* Scan all channels and see if there are any
10243 * ringing channels that have call groups
10244 * that equal this channels pickup group
10245 */
10246 if (idx == SUB_REAL) {
10247 /* Switch us from Third call to Call Wait */
10248 if (p->subs[SUB_THREEWAY].owner) {
10249 /* If you make a threeway call and the *8# a call, it should actually
10250 look like a callwait */
10251 alloc_sub(p, SUB_CALLWAIT);
10252 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10253 unalloc_sub(p, SUB_THREEWAY);
10254 }
10255 dahdi_ec_enable(p);
10256 if (ast_pickup_call(chan)) {
10257 ast_debug(1, "No call pickup possible...\n");
10258 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10259 dahdi_wait_event(p->subs[idx].dfd);
10260 }
10261 ast_hangup(chan);
10262 goto quit;
10263 } else {
10264 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10265 ast_hangup(chan);
10266 goto quit;
10267 }
10268
10269 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10270 ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan));
10271 /* Disable Caller*ID if enabled */
10272 p->hidecallerid = 1;
10273 ast_party_number_free(&ast_channel_caller(chan)->id.number);
10274 ast_party_number_init(&ast_channel_caller(chan)->id.number);
10275 ast_party_name_free(&ast_channel_caller(chan)->id.name);
10276 ast_party_name_init(&ast_channel_caller(chan)->id.name);
10277 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10278 if (res) {
10279 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10280 ast_channel_name(chan), strerror(errno));
10281 }
10282 len = 0;
10283 memset(exten, 0, sizeof(exten));
10284 timeout = p->firstdigit_timeout;
10285 } else if (p->callreturn && !strcmp(exten, "*69")) {
10286 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10287 break;
10288 } else if (!strcmp(exten, "*78")) {
10289 dahdi_dnd(p, 1);
10290 /* Do not disturb */
10291 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10292 getforward = 0;
10293 memset(exten, 0, sizeof(exten));
10294 len = 0;
10295 } else if (!strcmp(exten, "*79")) {
10296 dahdi_dnd(p, 0);
10297 /* Do not disturb */
10298 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10299 getforward = 0;
10300 memset(exten, 0, sizeof(exten));
10301 len = 0;
10302 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10303 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10304 getforward = 1;
10305 memset(exten, 0, sizeof(exten));
10306 len = 0;
10307 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10308 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10309 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10310 memset(p->call_forward, 0, sizeof(p->call_forward));
10311 getforward = 0;
10312 memset(exten, 0, sizeof(exten));
10313 len = 0;
10314 } else if ((p->transfer || p->canpark) && is_exten_parking
10315 && p->subs[SUB_THREEWAY].owner) {
10316 struct ast_bridge_channel *bridge_channel;
10317
10318 /*
10319 * This is a three way call, the main call being a real channel,
10320 * and we're parking the first call.
10321 */
10322 ast_channel_lock(p->subs[SUB_THREEWAY].owner);
10323 bridge_channel = ast_channel_get_bridge_channel(p->subs[SUB_THREEWAY].owner);
10324 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
10325 if (bridge_channel) {
10326 if (!ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), exten, NULL, NULL)) {
10327 /*
10328 * Swap things around between the three-way and real call so we
10329 * can hear where the channel got parked.
10330 */
10331 ast_mutex_lock(&p->lock);
10332 p->owner = p->subs[SUB_THREEWAY].owner;
10333 swap_subs(p, SUB_THREEWAY, SUB_REAL);
10334 ast_mutex_unlock(&p->lock);
10335
10336 ast_verb(3, "%s: Parked call\n", ast_channel_name(chan));
10337 ast_hangup(chan);
10338 ao2_ref(bridge_channel, -1);
10339 goto quit;
10340 }
10341 ao2_ref(bridge_channel, -1);
10342 }
10343 break;
10344 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10345 ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan));
10346 /* Enable Caller*ID if enabled */
10347 p->hidecallerid = 0;
10348 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10349 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10350 if (res) {
10351 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10352 ast_channel_name(chan), strerror(errno));
10353 }
10354 len = 0;
10355 memset(exten, 0, sizeof(exten));
10356 timeout = p->firstdigit_timeout;
10357 } else if (!strcmp(exten, "*0")) {
10358 struct ast_channel *nbridge =
10359 p->subs[SUB_THREEWAY].owner;
10360 struct dahdi_pvt *pbridge = NULL;
10361 RAII_VAR(struct ast_channel *, bridged, nbridge ? ast_channel_bridge_peer(nbridge) : NULL, ast_channel_cleanup);
10362
10363 /* set up the private struct of the bridged one, if any */
10364 if (nbridge && bridged) {
10365 pbridge = ast_channel_tech_pvt(bridged);
10366 }
10367 if (nbridge && pbridge &&
10368 (ast_channel_tech(nbridge) == &dahdi_tech) &&
10369 (ast_channel_tech(bridged) == &dahdi_tech) &&
10370 ISTRUNK(pbridge)) {
10371 int func = DAHDI_FLASH;
10372 /* Clear out the dial buffer */
10373 p->dop.dialstr[0] = '\0';
10374 /* flash hookswitch */
10375 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10376 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10377 ast_channel_name(nbridge), strerror(errno));
10378 }
10379 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10380 unalloc_sub(p, SUB_THREEWAY);
10381 p->owner = p->subs[SUB_REAL].owner;
10382 ast_queue_unhold(p->subs[SUB_REAL].owner);
10383 ast_hangup(chan);
10384 goto quit;
10385 } else {
10386 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10387 dahdi_wait_event(p->subs[idx].dfd);
10388 tone_zone_play_tone(p->subs[idx].dfd, -1);
10389 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10390 unalloc_sub(p, SUB_THREEWAY);
10391 p->owner = p->subs[SUB_REAL].owner;
10392 ast_hangup(chan);
10393 goto quit;
10394 }
10395 } else if (!ast_canmatch_extension(chan, ast_channel_context(chan), exten, 1,
10396 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
10397 && !canmatch_featurecode(pickupexten, exten)) {
10398 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10399 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<Unknown Caller>"),
10400 ast_channel_context(chan));
10401 break;
10402 }
10403 if (!timeout)
10404 timeout = p->interdigit_timeout;
10405 if (len && !ast_ignore_pattern(ast_channel_context(chan), exten))
10406 tone_zone_play_tone(p->subs[idx].dfd, -1);
10407 }
10408 break;
10409 case SIG_FXSLS:
10410 case SIG_FXSGS:
10411 case SIG_FXSKS:
10412 /* check for SMDI messages */
10413 if (p->use_smdi && p->smdi_iface) {
10414 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10415
10416 if (smdi_msg != NULL) {
10417 ast_channel_exten_set(chan, smdi_msg->fwd_st);
10418
10419 if (smdi_msg->type == 'B')
10420 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10421 else if (smdi_msg->type == 'N')
10422 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10423
10424 ast_debug(1, "Received SMDI message on %s\n", ast_channel_name(chan));
10425 } else {
10426 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10427 }
10428 }
10429
10430 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10431 number = smdi_msg->calling_st;
10432
10433 /* If we want caller id, we're in a prering state due to a polarity reversal
10434 * and we're set to use a polarity reversal to trigger the start of caller id,
10435 * grab the caller id and wait for ringing to start... */
10436 } else if (p->use_callerid && (ast_channel_state(chan) == AST_STATE_PRERING &&
10437 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10438 /* If set to use DTMF CID signalling, listen for DTMF */
10439 if (p->cid_signalling == CID_SIG_DTMF) {
10440 int k = 0;
10441 int off_ms;
10442 struct timeval start = ast_tvnow();
10443 int ms;
10444 cs = NULL;
10445 ast_debug(1, "Receiving DTMF cid on channel %s\n", ast_channel_name(chan));
10446 dahdi_setlinear(p->subs[idx].dfd, 0);
10447 /*
10448 * We are the only party interested in the Rx stream since
10449 * we have not answered yet. We don't need or even want DTMF
10450 * emulation. The DTMF digits can come so fast that emulation
10451 * can drop some of them.
10452 */
10453 ast_channel_lock(chan);
10454 ast_set_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
10455 ast_channel_unlock(chan);
10456 off_ms = 4000;/* This is a typical OFF time between rings. */
10457 for (;;) {
10458 struct ast_frame *f;
10459
10460 ms = ast_remaining_ms(start, off_ms);
10461 res = ast_waitfor(chan, ms);
10462 if (res <= 0) {
10463 /*
10464 * We do not need to restore the dahdi_setlinear()
10465 * or AST_FLAG_END_DTMF_ONLY flag settings since we
10466 * are hanging up the channel.
10467 */
10468 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10469 "Exiting simple switch\n");
10470 ast_hangup(chan);
10471 goto quit;
10472 }
10473 f = ast_read(chan);
10474 if (!f)
10475 break;
10476 if (f->frametype == AST_FRAME_DTMF) {
10477 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10478 dtmfbuf[k++] = f->subclass.integer;
10479 }
10480 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10481 start = ast_tvnow();
10482 }
10483 ast_frfree(f);
10484 if (ast_channel_state(chan) == AST_STATE_RING ||
10485 ast_channel_state(chan) == AST_STATE_RINGING)
10486 break; /* Got ring */
10487 }
10488 ast_channel_lock(chan);
10489 ast_clear_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
10490 ast_channel_unlock(chan);
10491 dtmfbuf[k] = '\0';
10492 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10493 /* Got cid and ring. */
10494 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10495 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10496 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10497 /* If first byte is NULL, we have no cid */
10498 if (!ast_strlen_zero(dtmfcid))
10499 number = dtmfcid;
10500 else
10501 number = NULL;
10502 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10503 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10504 cs = callerid_new(p->cid_signalling);
10505 if (cs) {
10506 int off_ms;
10507 struct timeval start;
10508 int ms;
10509 samples = 0;
10510 #if 1
10511 bump_gains(p);
10512 #endif
10513 /* Take out of linear mode for Caller*ID processing */
10514 dahdi_setlinear(p->subs[idx].dfd, 0);
10515
10516 /* First we wait and listen for the Caller*ID */
10517 for (;;) {
10518 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10519 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10520 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10521 callerid_free(cs);
10522 ast_hangup(chan);
10523 goto quit;
10524 }
10525 if (i & DAHDI_IOMUX_SIGEVENT) {
10526 res = dahdi_get_event(p->subs[idx].dfd);
10527 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10528 if (res == DAHDI_EVENT_NOALARM) {
10529 p->inalarm = 0;
10530 }
10531
10532 if (p->cid_signalling == CID_SIG_V23_JP) {
10533 if (res == DAHDI_EVENT_RINGBEGIN) {
10534 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10535 usleep(1);
10536 }
10537 } else {
10538 res = 0;
10539 break;
10540 }
10541 } else if (i & DAHDI_IOMUX_READ) {
10542 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10543 if (res < 0) {
10544 if (errno != ELAST) {
10545 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10546 callerid_free(cs);
10547 ast_hangup(chan);
10548 goto quit;
10549 }
10550 break;
10551 }
10552 samples += res;
10553
10554 if (p->cid_signalling == CID_SIG_V23_JP) {
10555 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10556 } else {
10557 res = callerid_feed(cs, buf, res, AST_LAW(p));
10558 }
10559 if (res < 0) {
10560 /*
10561 * The previous diagnostic message output likely
10562 * explains why it failed.
10563 */
10564 ast_log(LOG_WARNING,
10565 "Failed to decode CallerID on channel '%s'\n",
10566 ast_channel_name(chan));
10567 break;
10568 } else if (res)
10569 break;
10570 else if (samples > (8000 * 10))
10571 break;
10572 }
10573 }
10574 if (res == 1) {
10575 callerid_get(cs, &name, &number, &flags);
10576 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10577 }
10578
10579 if (p->cid_signalling == CID_SIG_V23_JP) {
10580 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10581 usleep(1);
10582 }
10583
10584 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10585 start = ast_tvnow();
10586 off_ms = 4000;/* This is a typical OFF time between rings. */
10587 for (;;) {
10588 struct ast_frame *f;
10589
10590 ms = ast_remaining_ms(start, off_ms);
10591 res = ast_waitfor(chan, ms);
10592 if (res <= 0) {
10593 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10594 "Exiting simple switch\n");
10595 ast_hangup(chan);
10596 goto quit;
10597 }
10598 if (!(f = ast_read(chan))) {
10599 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10600 ast_hangup(chan);
10601 goto quit;
10602 }
10603 ast_frfree(f);
10604 if (ast_channel_state(chan) == AST_STATE_RING ||
10605 ast_channel_state(chan) == AST_STATE_RINGING)
10606 break; /* Got ring */
10607 }
10608
10609 /* We must have a ring by now, so, if configured, lets try to listen for
10610 * distinctive ringing */
10611 if (p->usedistinctiveringdetection) {
10612 len = 0;
10613 distMatches = 0;
10614 /* Clear the current ring data array so we don't have old data in it. */
10615 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10616 curRingData[receivedRingT] = 0;
10617 receivedRingT = 0;
10618 counter = 0;
10619 counter1 = 0;
10620 /* Check to see if context is what it should be, if not set to be. */
10621 if (strcmp(p->context,p->defcontext) != 0) {
10622 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10623 ast_channel_context_set(chan, p->defcontext);
10624 }
10625
10626 for (;;) {
10627 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10628 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10629 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10630 callerid_free(cs);
10631 ast_hangup(chan);
10632 goto quit;
10633 }
10634 if (i & DAHDI_IOMUX_SIGEVENT) {
10635 res = dahdi_get_event(p->subs[idx].dfd);
10636 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10637 if (res == DAHDI_EVENT_NOALARM) {
10638 p->inalarm = 0;
10639 }
10640 res = 0;
10641 /* Let us detect distinctive ring */
10642
10643 curRingData[receivedRingT] = p->ringt;
10644
10645 if (p->ringt < p->ringt_base/2)
10646 break;
10647 /* Increment the ringT counter so we can match it against
10648 values in chan_dahdi.conf for distinctive ring */
10649 if (++receivedRingT == ARRAY_LEN(curRingData))
10650 break;
10651 } else if (i & DAHDI_IOMUX_READ) {
10652 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10653 if (res < 0) {
10654 if (errno != ELAST) {
10655 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10656 callerid_free(cs);
10657 ast_hangup(chan);
10658 goto quit;
10659 }
10660 break;
10661 }
10662 if (p->ringt > 0) {
10663 if (!(--p->ringt)) {
10664 res = -1;
10665 break;
10666 }
10667 }
10668 }
10669 }
10670 /* this only shows up if you have n of the dring patterns filled in */
10671 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10672 for (counter = 0; counter < 3; counter++) {
10673 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10674 channel */
10675 distMatches = 0;
10676 for (counter1 = 0; counter1 < 3; counter1++) {
10677 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10678 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10679 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10680 curRingData[counter1]);
10681 distMatches++;
10682 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10683 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10684 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10685 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10686 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10687 distMatches++;
10688 }
10689 }
10690
10691 if (distMatches == 3) {
10692 /* The ring matches, set the context to whatever is for distinctive ring.. */
10693 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10694 ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext));
10695 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10696 break;
10697 }
10698 }
10699 }
10700 /* Restore linear mode (if appropriate) for Caller*ID processing */
10701 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10702 #if 1
10703 restore_gains(p);
10704 #endif
10705 } else
10706 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10707 } else {
10708 ast_log(LOG_WARNING, "Channel %s in prering "
10709 "state, but I have nothing to do. "
10710 "Terminating simple switch, should be "
10711 "restarted by the actual ring.\n",
10712 ast_channel_name(chan));
10713 ast_hangup(chan);
10714 goto quit;
10715 }
10716 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10717 if (p->cid_signalling == CID_SIG_DTMF) {
10718 int k = 0;
10719 int off_ms;
10720 struct timeval start;
10721 int ms;
10722 cs = NULL;
10723 dahdi_setlinear(p->subs[idx].dfd, 0);
10724 off_ms = 2000;
10725 start = ast_tvnow();
10726 for (;;) {
10727 struct ast_frame *f;
10728
10729 ms = ast_remaining_ms(start, off_ms);
10730 res = ast_waitfor(chan, ms);
10731 if (res <= 0) {
10732 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10733 "Exiting simple switch\n");
10734 ast_hangup(chan);
10735 goto quit;
10736 }
10737 f = ast_read(chan);
10738 if (!f) {
10739 /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10740 ast_hangup(chan);
10741 goto quit;
10742 }
10743 if (f->frametype == AST_FRAME_DTMF) {
10744 dtmfbuf[k++] = f->subclass.integer;
10745 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10746 start = ast_tvnow();
10747 }
10748 ast_frfree(f);
10749
10750 if (p->ringt_base == p->ringt)
10751 break;
10752 }
10753 dtmfbuf[k] = '\0';
10754 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10755 /* Got cid and ring. */
10756 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10757 ast_debug(1, "CID is '%s', flags %d\n",
10758 dtmfcid, flags);
10759 /* If first byte is NULL, we have no cid */
10760 if (!ast_strlen_zero(dtmfcid))
10761 number = dtmfcid;
10762 else
10763 number = NULL;
10764 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10765 } else {
10766 /* FSK Bell202 callerID */
10767 cs = callerid_new(p->cid_signalling);
10768 if (cs) {
10769 #if 1
10770 bump_gains(p);
10771 #endif
10772 samples = 0;
10773 len = 0;
10774 distMatches = 0;
10775 /* Clear the current ring data array so we don't have old data in it. */
10776 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10777 curRingData[receivedRingT] = 0;
10778 receivedRingT = 0;
10779 counter = 0;
10780 counter1 = 0;
10781 /* Check to see if context is what it should be, if not set to be. */
10782 if (strcmp(p->context,p->defcontext) != 0) {
10783 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10784 ast_channel_context_set(chan, p->defcontext);
10785 }
10786
10787 /* Take out of linear mode for Caller*ID processing */
10788 dahdi_setlinear(p->subs[idx].dfd, 0);
10789 for (;;) {
10790 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10791 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10792 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10793 callerid_free(cs);
10794 ast_hangup(chan);
10795 goto quit;
10796 }
10797 if (i & DAHDI_IOMUX_SIGEVENT) {
10798 res = dahdi_get_event(p->subs[idx].dfd);
10799 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10800 if (res == DAHDI_EVENT_NOALARM) {
10801 p->inalarm = 0;
10802 }
10803 /* If we get a PR event, they hung up while processing calerid */
10804 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10805 ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10806 p->polarity = POLARITY_IDLE;
10807 callerid_free(cs);
10808 ast_hangup(chan);
10809 goto quit;
10810 }
10811 res = 0;
10812 /* Let us detect callerid when the telco uses distinctive ring */
10813
10814 curRingData[receivedRingT] = p->ringt;
10815
10816 if (p->ringt < p->ringt_base/2)
10817 break;
10818 /* Increment the ringT counter so we can match it against
10819 values in chan_dahdi.conf for distinctive ring */
10820 if (++receivedRingT == ARRAY_LEN(curRingData))
10821 break;
10822 } else if (i & DAHDI_IOMUX_READ) {
10823 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10824 if (res < 0) {
10825 if (errno != ELAST) {
10826 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10827 callerid_free(cs);
10828 ast_hangup(chan);
10829 goto quit;
10830 }
10831 break;
10832 }
10833 if (p->ringt > 0) {
10834 if (!(--p->ringt)) {
10835 res = -1;
10836 break;
10837 }
10838 }
10839 samples += res;
10840 res = callerid_feed(cs, buf, res, AST_LAW(p));
10841 if (res < 0) {
10842 /*
10843 * The previous diagnostic message output likely
10844 * explains why it failed.
10845 */
10846 ast_log(LOG_WARNING,
10847 "Failed to decode CallerID on channel '%s'\n",
10848 ast_channel_name(chan));
10849 break;
10850 } else if (res)
10851 break;
10852 else if (samples > (8000 * 10))
10853 break;
10854 }
10855 }
10856 if (res == 1) {
10857 callerid_get(cs, &name, &number, &flags);
10858 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10859 }
10860 if (distinctiveringaftercid == 1) {
10861 /* Clear the current ring data array so we don't have old data in it. */
10862 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10863 curRingData[receivedRingT] = 0;
10864 }
10865 receivedRingT = 0;
10866 ast_verb(3, "Detecting post-CID distinctive ring\n");
10867 for (;;) {
10868 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10869 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10870 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10871 callerid_free(cs);
10872 ast_hangup(chan);
10873 goto quit;
10874 }
10875 if (i & DAHDI_IOMUX_SIGEVENT) {
10876 res = dahdi_get_event(p->subs[idx].dfd);
10877 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10878 if (res == DAHDI_EVENT_NOALARM) {
10879 p->inalarm = 0;
10880 }
10881 res = 0;
10882 /* Let us detect callerid when the telco uses distinctive ring */
10883
10884 curRingData[receivedRingT] = p->ringt;
10885
10886 if (p->ringt < p->ringt_base/2)
10887 break;
10888 /* Increment the ringT counter so we can match it against
10889 values in chan_dahdi.conf for distinctive ring */
10890 if (++receivedRingT == ARRAY_LEN(curRingData))
10891 break;
10892 } else if (i & DAHDI_IOMUX_READ) {
10893 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10894 if (res < 0) {
10895 if (errno != ELAST) {
10896 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10897 callerid_free(cs);
10898 ast_hangup(chan);
10899 goto quit;
10900 }
10901 break;
10902 }
10903 if (p->ringt > 0) {
10904 if (!(--p->ringt)) {
10905 res = -1;
10906 break;
10907 }
10908 }
10909 }
10910 }
10911 }
10912 if (p->usedistinctiveringdetection) {
10913 /* this only shows up if you have n of the dring patterns filled in */
10914 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10915
10916 for (counter = 0; counter < 3; counter++) {
10917 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10918 channel */
10919 /* this only shows up if you have n of the dring patterns filled in */
10920 ast_verb(3, "Checking %d,%d,%d\n",
10921 p->drings.ringnum[counter].ring[0],
10922 p->drings.ringnum[counter].ring[1],
10923 p->drings.ringnum[counter].ring[2]);
10924 distMatches = 0;
10925 for (counter1 = 0; counter1 < 3; counter1++) {
10926 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10927 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10928 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10929 curRingData[counter1]);
10930 distMatches++;
10931 }
10932 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10933 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10934 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10935 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10936 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10937 distMatches++;
10938 }
10939 }
10940 if (distMatches == 3) {
10941 /* The ring matches, set the context to whatever is for distinctive ring.. */
10942 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10943 ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext));
10944 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10945 break;
10946 }
10947 }
10948 }
10949 /* Restore linear mode (if appropriate) for Caller*ID processing */
10950 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10951 #if 1
10952 restore_gains(p);
10953 #endif
10954 if (res < 0) {
10955 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", ast_channel_name(chan));
10956 }
10957 } else
10958 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10959 }
10960 } else
10961 cs = NULL;
10962
10963 if (number)
10964 ast_shrink_phone_number(number);
10965 ast_set_callerid(chan, number, name, number);
10966
10967 ao2_cleanup(smdi_msg);
10968
10969 if (cs)
10970 callerid_free(cs);
10971
10972 my_handle_notify_message(chan, p, flags, -1);
10973
10974 ast_channel_lock(chan);
10975 ast_setstate(chan, AST_STATE_RING);
10976 ast_channel_rings_set(chan, 1);
10977 ast_channel_unlock(chan);
10978 p->ringt = p->ringt_base;
10979 res = ast_pbx_run(chan);
10980 if (res) {
10981 ast_hangup(chan);
10982 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10983 }
10984 goto quit;
10985 default:
10986 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
10987 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10988 if (res < 0)
10989 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10990 }
10991 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10992 if (res < 0)
10993 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10994 ast_hangup(chan);
10995 quit:
10996 ast_mutex_lock(&ss_thread_lock);
10997 ss_thread_count--;
10998 ast_cond_signal(&ss_thread_complete);
10999 ast_mutex_unlock(&ss_thread_lock);
11000 return NULL;
11001 }
11002
11003 struct mwi_thread_data {
11004 struct dahdi_pvt *pvt;
11005 unsigned char buf[READ_SIZE];
11006 size_t len;
11007 };
11008
11009 static int calc_energy(const unsigned char *buf, int len, struct ast_format *law)
11010 {
11011 int x;
11012 int sum = 0;
11013
11014 if (!len)
11015 return 0;
11016
11017 for (x = 0; x < len; x++)
11018 sum += abs(law == ast_format_ulaw ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11019
11020 return sum / len;
11021 }
11022
11023 static void *mwi_thread(void *data)
11024 {
11025 struct mwi_thread_data *mtd = data;
11026 struct callerid_state *cs;
11027 pthread_t threadid;
11028 int samples = 0;
11029 char *name, *number;
11030 int flags;
11031 int i, res;
11032 unsigned int spill_done = 0;
11033 int spill_result = -1;
11034
11035 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11036 goto quit_no_clean;
11037 }
11038
11039 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11040
11041 bump_gains(mtd->pvt);
11042
11043 for (;;) {
11044 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11045 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11046 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11047 goto quit;
11048 }
11049
11050 if (i & DAHDI_IOMUX_SIGEVENT) {
11051 struct ast_channel *chan;
11052 ast_callid callid = 0;
11053 int callid_created;
11054
11055 /* If we get an event, screen out events that we do not act on.
11056 * Otherwise, cancel and go to the simple switch to let it deal with it.
11057 */
11058 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11059
11060 switch (res) {
11061 case DAHDI_EVENT_NEONMWI_ACTIVE:
11062 case DAHDI_EVENT_NEONMWI_INACTIVE:
11063 case DAHDI_EVENT_NONE:
11064 case DAHDI_EVENT_BITSCHANGED:
11065 break;
11066 case DAHDI_EVENT_NOALARM:
11067 if (dahdi_analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11068 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11069
11070 analog_p->inalarm = 0;
11071 }
11072 mtd->pvt->inalarm = 0;
11073 handle_clear_alarms(mtd->pvt);
11074 break;
11075 case DAHDI_EVENT_ALARM:
11076 if (dahdi_analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11077 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11078
11079 analog_p->inalarm = 1;
11080 }
11081 mtd->pvt->inalarm = 1;
11082 res = get_alarms(mtd->pvt);
11083 handle_alarms(mtd->pvt, res);
11084 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
11085 default:
11086 callid_created = ast_callid_threadstorage_auto(&callid);
11087 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
11088 callerid_free(cs);
11089
11090 restore_gains(mtd->pvt);
11091 mtd->pvt->ringt = mtd->pvt->ringt_base;
11092
11093 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL, NULL, callid))) {
11094 int result;
11095
11096 if (dahdi_analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11097 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11098 } else {
11099 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11100 }
11101 if (result) {
11102 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11103 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11104 if (res < 0)
11105 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11106 ast_hangup(chan);
11107 }
11108 } else {
11109 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11110 }
11111
11112 ast_callid_threadstorage_auto_clean(callid, callid_created);
11113 goto quit_no_clean;
11114 }
11115 } else if (i & DAHDI_IOMUX_READ) {
11116 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11117 if (errno != ELAST) {
11118 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11119 goto quit;
11120 }
11121 break;
11122 }
11123 samples += res;
11124 if (!spill_done) {
11125 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11126 /*
11127 * The previous diagnostic message output likely
11128 * explains why it failed.
11129 */
11130 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11131 break;
11132 } else if (spill_result) {
11133 spill_done = 1;
11134 }
11135 } else {
11136 /* keep reading data until the energy level drops below the threshold
11137 so we don't get another 'trigger' on the remaining carrier signal
11138 */
11139 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11140 break;
11141 }
11142 if (samples > (8000 * 4)) /*Termination case - time to give up*/
11143 break;
11144 }
11145 }
11146
11147 if (spill_result == 1) {
11148 callerid_get(cs, &name, &number, &flags);
11149 if (flags & CID_MSGWAITING) {
11150 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11151 notify_message(mtd->pvt->mailbox, 1);
11152 } else if (flags & CID_NOMSGWAITING) {
11153 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11154 notify_message(mtd->pvt->mailbox, 0);
11155 } else {
11156 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11157 }
11158 }
11159
11160
11161 quit:
11162 callerid_free(cs);
11163
11164 restore_gains(mtd->pvt);
11165
11166 quit_no_clean:
11167 mtd->pvt->mwimonitoractive = 0;
11168 ast_free(mtd);
11169
11170 return NULL;
11171 }
11172
11173 /*
11174 * The following three functions (mwi_send_init, mwi_send_process_buffer,
11175 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
11176 * that are sent out via FXS port on voicemail state change. The execution of
11177 * the mwi send is state driven and can either generate a ring pulse prior to
11178 * sending the fsk spill or simply send an fsk spill.
11179 */
11180 static int mwi_send_init(struct dahdi_pvt * pvt)
11181 {
11182 int x;
11183
11184 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11185 /* Determine how this spill is to be sent */
11186 if (pvt->mwisend_rpas) {
11187 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11188 pvt->mwisendactive = 1;
11189 } else if (pvt->mwisend_fsk) {
11190 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11191 pvt->mwisendactive = 1;
11192 } else {
11193 pvt->mwisendactive = 0;
11194 return 0;
11195 }
11196 #else
11197 if (mwisend_rpas) {
11198 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11199 } else {
11200 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11201 }
11202 pvt->mwisendactive = 1;
11203 #endif
11204
11205 if (pvt->cidspill) {
11206 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11207 ast_free(pvt->cidspill);
11208 pvt->cidspill = NULL;
11209 pvt->cidpos = 0;
11210 pvt->cidlen = 0;
11211 }
11212 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11213 if (!pvt->cidspill) {
11214 pvt->mwisendactive = 0;
11215 return -1;
11216 }
11217 x = DAHDI_FLUSH_BOTH;
11218 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11219 x = 3000;
11220 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11221 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11222 if (pvt->mwisend_fsk) {
11223 #endif
11224 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt),
11225 CID_MWI_TYPE_MDMF_FULL, AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11226 pvt->cidpos = 0;
11227 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11228 }
11229 #endif
11230 return 0;
11231 }
11232
11233 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11234 {
11235 struct timeval now;
11236 int res;
11237
11238 /* sanity check to catch if this had been interrupted previously
11239 * i.e. state says there is more to do but there is no spill allocated
11240 */
11241 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11242 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11243 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11244 /* Normal processing -- Perform mwi send action */
11245 switch ( pvt->mwisend_data.mwisend_current) {
11246 case MWI_SEND_SA:
11247 /* Send the Ring Pulse Signal Alert */
11248 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11249 if (res) {
11250 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11251 goto quit;
11252 }
11253 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11254 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11255 break;
11256 case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */
11257 break;
11258 case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/
11259 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11260 if (pvt->mwisend_fsk) {
11261 #endif
11262 gettimeofday(&now, NULL);
11263 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11264 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11265 }
11266 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11267 } else { /* support for mwisendtype=nofsk */
11268 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11269 }
11270 #endif
11271 break;
11272 case MWI_SEND_SPILL:
11273 /* We read some number of bytes. Write an equal amount of data */
11274 if (0 < num_read) {
11275 if (num_read > pvt->cidlen - pvt->cidpos) {
11276 num_read = pvt->cidlen - pvt->cidpos;
11277 }
11278 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11279 if (res > 0) {
11280 pvt->cidpos += res;
11281 if (pvt->cidpos >= pvt->cidlen) {
11282 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11283 }
11284 } else {
11285 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11286 goto quit;
11287 }
11288 }
11289 break;
11290 case MWI_SEND_CLEANUP:
11291 /* For now, do nothing */
11292 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11293 break;
11294 default:
11295 /* Should not get here, punt*/
11296 goto quit;
11297 }
11298 }
11299
11300 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11301 if (pvt->cidspill) {
11302 ast_free(pvt->cidspill);
11303 pvt->cidspill = NULL;
11304 pvt->cidpos = 0;
11305 pvt->cidlen = 0;
11306 }
11307 pvt->mwisendactive = 0;
11308 }
11309 return 0;
11310 quit:
11311 if (pvt->cidspill) {
11312 ast_free(pvt->cidspill);
11313 pvt->cidspill = NULL;
11314 pvt->cidpos = 0;
11315 pvt->cidlen = 0;
11316 }
11317 pvt->mwisendactive = 0;
11318 return -1;
11319 }
11320
11321 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11322 {
11323 int handled = 0;
11324
11325 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11326 switch (event) {
11327 case DAHDI_EVENT_RINGEROFF:
11328 if (pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11329 handled = 1;
11330
11331 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11332 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11333 ast_free(pvt->cidspill);
11334 pvt->cidspill = NULL;
11335 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11336 pvt->mwisendactive = 0;
11337 } else {
11338 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11339 gettimeofday(&pvt->mwisend_data.pause, NULL);
11340 }
11341 }
11342 break;
11343 /* Going off hook, I need to punt this spill */
11344 case DAHDI_EVENT_RINGOFFHOOK:
11345 if (pvt->cidspill) {
11346 ast_free(pvt->cidspill);
11347 pvt->cidspill = NULL;
11348 pvt->cidpos = 0;
11349 pvt->cidlen = 0;
11350 }
11351 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11352 pvt->mwisendactive = 0;
11353 break;
11354 case DAHDI_EVENT_RINGERON:
11355 case DAHDI_EVENT_HOOKCOMPLETE:
11356 break;
11357 default:
11358 break;
11359 }
11360 }
11361 return handled;
11362 }
11363
11364 /* destroy a range DAHDI channels, identified by their number */
11365 static void dahdi_destroy_channel_range(int start, int end)
11366 {
11367 struct dahdi_pvt *cur;
11368 struct dahdi_pvt *next;
11369 int destroyed_first = 0;
11370 int destroyed_last = 0;
11371
11372 ast_mutex_lock(&iflock);
11373 ast_debug(1, "range: %d-%d\n", start, end);
11374 for (cur = iflist; cur; cur = next) {
11375 next = cur->next;
11376 if (cur->channel >= start && cur->channel <= end) {
11377 int x = DAHDI_FLASH;
11378
11379 if (cur->channel > destroyed_last) {
11380 destroyed_last = cur->channel;
11381 }
11382 if (destroyed_first < 1 || cur->channel < destroyed_first) {
11383 destroyed_first = cur->channel;
11384 }
11385 ast_debug(3, "Destroying %d\n", cur->channel);
11386 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11387 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11388
11389 destroy_channel(cur, 1);
11390 ast_module_unref(ast_module_info->self);
11391 }
11392 }
11393 ast_mutex_unlock(&iflock);
11394 if (destroyed_first > start || destroyed_last < end) {
11395 ast_debug(1, "Asked to destroy %d-%d, destroyed %d-%d,\n",
11396 start, end, destroyed_first, destroyed_last);
11397 }
11398 }
11399
11400 #ifdef HAVE_OPENR2
11401 static void dahdi_r2_destroy_nodev(void)
11402 {
11403 struct r2link_entry *cur;
11404 AST_LIST_LOCK(&nodev_r2links);
11405 AST_LIST_TRAVERSE_SAFE_BEGIN(&nodev_r2links, cur, list) {
11406 int i;
11407 struct dahdi_mfcr2 *r2 = &cur->mfcr2;
11408 ast_debug(3, "About to destroy %d DAHDI channels of MFC/R2 link.\n", r2->numchans);
11409 for (i = 0; i < r2->numchans; i++) {
11410 int channel;
11411 struct dahdi_pvt *pvt = r2->pvts[i];
11412 if (!pvt) {
11413 continue;
11414 }
11415 channel = pvt->channel;
11416 ast_debug(3, "About to destroy B-channel %d.\n", channel);
11417 dahdi_destroy_channel_range(channel, channel);
11418 }
11419 ast_debug(3, "Destroying R2 link\n");
11420 AST_LIST_REMOVE(&nodev_r2links, cur, list);
11421 if (r2->r2master != AST_PTHREADT_NULL) {
11422 pthread_cancel(r2->r2master);
11423 pthread_join(r2->r2master, NULL);
11424 r2->r2master = AST_PTHREADT_NULL;
11425 openr2_context_delete(r2->protocol_context);
11426 }
11427 ast_free(cur);
11428 }
11429 AST_LIST_TRAVERSE_SAFE_END;
11430 AST_LIST_UNLOCK(&nodev_r2links);
11431 }
11432 #endif
11433
11434 static int setup_dahdi(int reload);
11435 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf);
11436
11437 /*!
11438 * \internal
11439 * \brief create a range of new DAHDI channels
11440 *
11441 * \param start first channel in the range
11442 * \param end last channel in the range
11443 *
11444 * \retval RESULT_SUCCESS on success.
11445 * \retval RESULT_FAILURE on error.
11446 */
11447 static int dahdi_create_channel_range(int start, int end)
11448 {
11449 struct dahdi_pvt *cur;
11450 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
11451 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
11452 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
11453 int ret = RESULT_FAILURE; /* be pessimistic */
11454
11455 ast_debug(1, "channel range caps: %d - %d\n", start, end);
11456 ast_mutex_lock(&iflock);
11457 for (cur = iflist; cur; cur = cur->next) {
11458 if (cur->channel >= start && cur->channel <= end) {
11459 ast_log(LOG_ERROR,
11460 "channel range %d-%d is occupied\n",
11461 start, end);
11462 goto out;
11463 }
11464 }
11465 #ifdef HAVE_PRI
11466 {
11467 int i, x;
11468 for (x = 0; x < NUM_SPANS; x++) {
11469 struct dahdi_pri *pri = pris + x;
11470
11471 if (!pris[x].pri.pvts[0]) {
11472 break;
11473 }
11474 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
11475 int channo = pri->dchannels[i];
11476
11477 if (!channo) {
11478 break;
11479 }
11480 if (!pri->pri.fds[i]) {
11481 break;
11482 }
11483 if (channo >= start && channo <= end) {
11484 ast_log(LOG_ERROR,
11485 "channel range %d-%d is occupied by span %d\n",
11486 start, end, x + 1);
11487 goto out;
11488 }
11489 }
11490 }
11491 }
11492 #endif
11493 if (!default_conf.chan.cc_params || !base_conf.chan.cc_params ||
11494 !conf.chan.cc_params) {
11495 goto out;
11496 }
11497 default_conf.wanted_channels_start = start;
11498 base_conf.wanted_channels_start = start;
11499 conf.wanted_channels_start = start;
11500 default_conf.wanted_channels_end = end;
11501 base_conf.wanted_channels_end = end;
11502 conf.wanted_channels_end = end;
11503 if (setup_dahdi_int(0, &default_conf, &base_conf, &conf) == 0) {
11504 ret = RESULT_SUCCESS;
11505 }
11506 out:
11507 ast_cc_config_params_destroy(default_conf.chan.cc_params);
11508 ast_cc_config_params_destroy(base_conf.chan.cc_params);
11509 ast_cc_config_params_destroy(conf.chan.cc_params);
11510 ast_mutex_unlock(&iflock);
11511 return ret;
11512 }
11513
11514
11515 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11516 {
11517 int res;
11518 pthread_t threadid;
11519 struct ast_channel *chan;
11520 ast_callid callid = 0;
11521 int callid_created;
11522
11523 /* Handle an event on a given channel for the monitor thread. */
11524
11525 switch (event) {
11526 case DAHDI_EVENT_NONE:
11527 case DAHDI_EVENT_BITSCHANGED:
11528 break;
11529 case DAHDI_EVENT_WINKFLASH:
11530 case DAHDI_EVENT_RINGOFFHOOK:
11531 if (i->inalarm) break;
11532 if (i->radio) break;
11533 /* Got a ring/answer. What kind of channel are we? */
11534 switch (i->sig) {
11535 case SIG_FXOLS:
11536 case SIG_FXOGS:
11537 case SIG_FXOKS:
11538 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11539 if (res && (errno == EBUSY)) {
11540 break;
11541 }
11542
11543 callid_created = ast_callid_threadstorage_auto(&callid);
11544
11545 /* Cancel VMWI spill */
11546 ast_free(i->cidspill);
11547 i->cidspill = NULL;
11548 restore_conference(i);
11549
11550 if (i->immediate) {
11551 dahdi_ec_enable(i);
11552 /* The channel is immediately up. Start right away */
11553 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11554 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL, NULL, callid);
11555 if (!chan) {
11556 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11557 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11558 if (res < 0)
11559 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11560 }
11561 } else {
11562 /* Check for callerid, digits, etc */
11563 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL, NULL, callid);
11564 if (chan) {
11565 if (has_voicemail(i))
11566 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11567 else
11568 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11569 if (res < 0)
11570 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11571 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11572 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11573 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11574 if (res < 0)
11575 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11576 ast_hangup(chan);
11577 }
11578 } else
11579 ast_log(LOG_WARNING, "Unable to create channel\n");
11580 }
11581
11582 ast_callid_threadstorage_auto_clean(callid, callid_created);
11583 break;
11584 case SIG_FXSLS:
11585 case SIG_FXSGS:
11586 case SIG_FXSKS:
11587 i->ringt = i->ringt_base;
11588 /* Fall through */
11589 case SIG_EMWINK:
11590 case SIG_FEATD:
11591 case SIG_FEATDMF:
11592 case SIG_FEATDMF_TA:
11593 case SIG_E911:
11594 case SIG_FGC_CAMA:
11595 case SIG_FGC_CAMAMF:
11596 case SIG_FEATB:
11597 case SIG_EM:
11598 case SIG_EM_E1:
11599 case SIG_SFWINK:
11600 case SIG_SF_FEATD:
11601 case SIG_SF_FEATDMF:
11602 case SIG_SF_FEATB:
11603 case SIG_SF:
11604 /* Check for callerid, digits, etc */
11605 callid_created = ast_callid_threadstorage_auto(&callid);
11606 if (i->cid_start == CID_START_POLARITY_IN) {
11607 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
11608 } else {
11609 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL, NULL, callid);
11610 }
11611
11612 if (!chan) {
11613 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11614 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11615 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11616 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11617 if (res < 0) {
11618 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11619 }
11620 ast_hangup(chan);
11621 }
11622
11623 ast_callid_threadstorage_auto_clean(callid, callid_created);
11624 break;
11625 default:
11626 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11627 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11628 if (res < 0)
11629 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11630 return NULL;
11631 }
11632 break;
11633 case DAHDI_EVENT_NOALARM:
11634 switch (i->sig) {
11635 #if defined(HAVE_PRI)
11636 case SIG_PRI_LIB_HANDLE_CASES:
11637 ast_mutex_lock(&i->lock);
11638 sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11639 ast_mutex_unlock(&i->lock);
11640 break;
11641 #endif /* defined(HAVE_PRI) */
11642 #if defined(HAVE_SS7)
11643 case SIG_SS7:
11644 sig_ss7_set_alarm(i->sig_pvt, 0);
11645 break;
11646 #endif /* defined(HAVE_SS7) */
11647 default:
11648 i->inalarm = 0;
11649 break;
11650 }
11651 handle_clear_alarms(i);
11652 break;
11653 case DAHDI_EVENT_ALARM:
11654 switch (i->sig) {
11655 #if defined(HAVE_PRI)
11656 case SIG_PRI_LIB_HANDLE_CASES:
11657 ast_mutex_lock(&i->lock);
11658 sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11659 ast_mutex_unlock(&i->lock);
11660 break;
11661 #endif /* defined(HAVE_PRI) */
11662 #if defined(HAVE_SS7)
11663 case SIG_SS7:
11664 sig_ss7_set_alarm(i->sig_pvt, 1);
11665 break;
11666 #endif /* defined(HAVE_SS7) */
11667 default:
11668 i->inalarm = 1;
11669 break;
11670 }
11671 res = get_alarms(i);
11672 handle_alarms(i, res);
11673 /* fall thru intentionally */
11674 case DAHDI_EVENT_ONHOOK:
11675 if (i->radio)
11676 break;
11677 /* Back on hook. Hang up. */
11678 switch (i->sig) {
11679 case SIG_FXOLS:
11680 case SIG_FXOGS:
11681 case SIG_FEATD:
11682 case SIG_FEATDMF:
11683 case SIG_FEATDMF_TA:
11684 case SIG_E911:
11685 case SIG_FGC_CAMA:
11686 case SIG_FGC_CAMAMF:
11687 case SIG_FEATB:
11688 case SIG_EM:
11689 case SIG_EM_E1:
11690 case SIG_EMWINK:
11691 case SIG_SF_FEATD:
11692 case SIG_SF_FEATDMF:
11693 case SIG_SF_FEATB:
11694 case SIG_SF:
11695 case SIG_SFWINK:
11696 case SIG_FXSLS:
11697 case SIG_FXSGS:
11698 case SIG_FXSKS:
11699 case SIG_FXOKS:
11700 dahdi_ec_disable(i);
11701 /* Diddle the battery for the zhone */
11702 #ifdef ZHONE_HACK
11703 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11704 usleep(1);
11705 #endif
11706 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11707 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11708 break;
11709 case SIG_SS7:
11710 case SIG_PRI_LIB_HANDLE_CASES:
11711 dahdi_ec_disable(i);
11712 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11713 break;
11714 default:
11715 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11716 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11717 return NULL;
11718 }
11719 break;
11720 case DAHDI_EVENT_POLARITY:
11721 switch (i->sig) {
11722 case SIG_FXSLS:
11723 case SIG_FXSKS:
11724 case SIG_FXSGS:
11725 /* We have already got a PR before the channel was
11726 created, but it wasn't handled. We need polarity
11727 to be REV for remote hangup detection to work.
11728 At least in Spain */
11729 callid_created = ast_callid_threadstorage_auto(&callid);
11730 if (i->hanguponpolarityswitch)
11731 i->polarity = POLARITY_REV;
11732 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11733 i->polarity = POLARITY_REV;
11734 ast_verb(2, "Starting post polarity "
11735 "CID detection on channel %d\n",
11736 i->channel);
11737 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
11738 if (!chan) {
11739 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11740 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11741 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11742 ast_hangup(chan);
11743 }
11744 }
11745 ast_callid_threadstorage_auto_clean(callid, callid_created);
11746 break;
11747 default:
11748 ast_log(LOG_WARNING, "handle_init_event detected "
11749 "polarity reversal on non-FXO (SIG_FXS) "
11750 "interface %d\n", i->channel);
11751 }
11752 break;
11753 case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11754 ast_log(LOG_NOTICE,
11755 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11756 i->channel);
11757 return i;
11758 case DAHDI_EVENT_NEONMWI_ACTIVE:
11759 if (i->mwimonitor_neon) {
11760 notify_message(i->mailbox, 1);
11761 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11762 }
11763 break;
11764 case DAHDI_EVENT_NEONMWI_INACTIVE:
11765 if (i->mwimonitor_neon) {
11766 notify_message(i->mailbox, 0);
11767 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11768 }
11769 break;
11770 }
11771 return NULL;
11772 }
11773
11774 static void monitor_pfds_clean(void *arg) {
11775 struct pollfd **pfds = arg;
11776 ast_free(*pfds);
11777 }
11778
11779 static void *do_monitor(void *data)
11780 {
11781 int count, res, res2, spoint, pollres=0;
11782 struct dahdi_pvt *i;
11783 struct dahdi_pvt *last = NULL;
11784 struct dahdi_pvt *doomed;
11785 time_t thispass = 0, lastpass = 0;
11786 int found;
11787 char buf[1024];
11788 struct pollfd *pfds=NULL;
11789 int lastalloc = -1;
11790 /* This thread monitors all the frame relay interfaces which are not yet in use
11791 (and thus do not have a separate thread) indefinitely */
11792 /* From here on out, we die whenever asked */
11793 #if 0
11794 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11795 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11796 return NULL;
11797 }
11798 ast_debug(1, "Monitor starting...\n");
11799 #endif
11800 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11801
11802 pthread_cleanup_push(monitor_pfds_clean, &pfds);
11803 for (;;) {
11804 /* Lock the interface list */
11805 ast_mutex_lock(&iflock);
11806 if (!pfds || (lastalloc != ifcount)) {
11807 if (pfds) {
11808 ast_free(pfds);
11809 pfds = NULL;
11810 }
11811 if (ifcount) {
11812 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11813 ast_mutex_unlock(&iflock);
11814 return NULL;
11815 }
11816 }
11817 lastalloc = ifcount;
11818 }
11819 /* Build the stuff we're going to poll on, that is the socket of every
11820 dahdi_pvt that does not have an associated owner channel */
11821 count = 0;
11822 for (i = iflist; i; i = i->next) {
11823 ast_mutex_lock(&i->lock);
11824 if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11825 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11826 struct analog_pvt *p = i->sig_pvt;
11827
11828 if (!p) {
11829 ast_log(LOG_ERROR, "No sig_pvt?\n");
11830 } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11831 /* This needs to be watched, as it lacks an owner */
11832 pfds[count].fd = i->subs[SUB_REAL].dfd;
11833 pfds[count].events = POLLPRI;
11834 pfds[count].revents = 0;
11835 /* Message waiting or r2 channels also get watched for reading */
11836 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11837 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11838 pfds[count].events |= POLLIN;
11839 }
11840 count++;
11841 }
11842 } else {
11843 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11844 /* This needs to be watched, as it lacks an owner */
11845 pfds[count].fd = i->subs[SUB_REAL].dfd;
11846 pfds[count].events = POLLPRI;
11847 pfds[count].revents = 0;
11848 /* If we are monitoring for VMWI or sending CID, we need to
11849 read from the channel as well */
11850 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11851 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11852 pfds[count].events |= POLLIN;
11853 }
11854 count++;
11855 }
11856 }
11857 }
11858 ast_mutex_unlock(&i->lock);
11859 }
11860 /* Okay, now that we know what to do, release the interface lock */
11861 ast_mutex_unlock(&iflock);
11862
11863 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11864 pthread_testcancel();
11865 /* Wait at least a second for something to happen */
11866 res = poll(pfds, count, 1000);
11867 pthread_testcancel();
11868 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11869
11870 /* Okay, poll has finished. Let's see what happened. */
11871 if (res < 0) {
11872 if ((errno != EAGAIN) && (errno != EINTR))
11873 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11874 continue;
11875 }
11876 /* Alright, lock the interface list again, and let's look and see what has
11877 happened */
11878 ast_mutex_lock(&iflock);
11879 found = 0;
11880 spoint = 0;
11881 lastpass = thispass;
11882 thispass = time(NULL);
11883 doomed = NULL;
11884 for (i = iflist;; i = i->next) {
11885 if (doomed) {
11886 dahdi_destroy_channel_range(doomed->channel, doomed->channel);
11887 doomed = NULL;
11888 }
11889 if (!i) {
11890 break;
11891 }
11892
11893 if (thispass != lastpass) {
11894 if (!found && ((i == last) || ((i == iflist) && !last))) {
11895 last = i;
11896 if (last) {
11897 struct analog_pvt *analog_p = last->sig_pvt;
11898 /* Only allow MWI to be initiated on a quiescent fxs port */
11899 if (analog_p
11900 && !last->mwisendactive
11901 && (last->sig & __DAHDI_SIG_FXO)
11902 && !analog_p->fxsoffhookstate
11903 && !last->owner
11904 && (!ast_strlen_zero(last->mailbox) || last->mwioverride_active)
11905 && !analog_p->subs[SUB_REAL].owner /* could be a recall ring from a flash hook hold */
11906 && (thispass - analog_p->onhooktime > 3)) {
11907 res = has_voicemail(last);
11908 if (analog_p->msgstate != res) {
11909 /* Set driver resources for signalling VMWI */
11910 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11911 if (res2) {
11912 /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11913 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11914 }
11915 /* If enabled for FSK spill then initiate it */
11916 if (mwi_send_init(last)) {
11917 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11918 }
11919 analog_p->msgstate = res;
11920 found ++;
11921 }
11922 }
11923 last = last->next;
11924 }
11925 }
11926 }
11927 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11928 if (i->radio && !i->owner)
11929 {
11930 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11931 if (res)
11932 {
11933 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11934 /* Don't hold iflock while handling init events */
11935 ast_mutex_unlock(&iflock);
11936 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode))
11937 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11938 else
11939 doomed = handle_init_event(i, res);
11940 ast_mutex_lock(&iflock);
11941 }
11942 continue;
11943 }
11944 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11945 if (pollres & POLLIN) {
11946 if (i->owner || i->subs[SUB_REAL].owner) {
11947 #ifdef HAVE_PRI
11948 if (!i->pri)
11949 #endif
11950 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11951 continue;
11952 }
11953 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
11954 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11955 continue;
11956 }
11957 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11958 if (res > 0) {
11959 if (i->mwimonitor_fsk) {
11960 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11961 pthread_attr_t attr;
11962 pthread_t threadid;
11963 struct mwi_thread_data *mtd;
11964
11965 pthread_attr_init(&attr);
11966 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11967
11968 ast_debug(1, "Maybe some MWI on port %d!\n", i->channel);
11969 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11970 mtd->pvt = i;
11971 memcpy(mtd->buf, buf, res);
11972 mtd->len = res;
11973 i->mwimonitoractive = 1;
11974 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11975 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11976 i->mwimonitoractive = 0;
11977 ast_free(mtd);
11978 }
11979 }
11980 }
11981 /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
11982 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11983 int energy;
11984 struct timeval now;
11985 /* State machine dtmfcid_holdoff_state allows for the line to settle
11986 * before checking agin for dtmf energy. Presently waits for 500 mS before checking again
11987 */
11988 if (1 == i->dtmfcid_holdoff_state) {
11989 gettimeofday(&i->dtmfcid_delay, NULL);
11990 i->dtmfcid_holdoff_state = 2;
11991 } else if (2 == i->dtmfcid_holdoff_state) {
11992 gettimeofday(&now, NULL);
11993 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11994 i->dtmfcid_holdoff_state = 0;
11995 }
11996 } else {
11997 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11998 if (!i->mwisendactive && energy > dtmfcid_level) {
11999 pthread_t threadid;
12000 struct ast_channel *chan;
12001 ast_mutex_unlock(&iflock);
12002 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
12003 /* just in case this event changes or somehow destroys a channel, set doomed here too */
12004 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
12005 i->dtmfcid_holdoff_state = 1;
12006 } else {
12007 ast_callid callid = 0;
12008 int callid_created = ast_callid_threadstorage_auto(&callid);
12009 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
12010 if (!chan) {
12011 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
12012 } else {
12013 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
12014 if (res) {
12015 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
12016 ast_hangup(chan);
12017 } else {
12018 i->dtmfcid_holdoff_state = 1;
12019 }
12020 }
12021 ast_callid_threadstorage_auto_clean(callid, callid_created);
12022 }
12023 ast_mutex_lock(&iflock);
12024 }
12025 }
12026 }
12027 if (i->mwisendactive) {
12028 mwi_send_process_buffer(i, res);
12029 }
12030 } else {
12031 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
12032 }
12033 }
12034 if (pollres & POLLPRI) {
12035 if (i->owner || i->subs[SUB_REAL].owner) {
12036 #ifdef HAVE_PRI
12037 if (!i->pri)
12038 #endif
12039 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
12040 continue;
12041 }
12042 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12043 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
12044 /* Don't hold iflock while handling init events */
12045 ast_mutex_unlock(&iflock);
12046 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
12047 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode))
12048 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12049 else
12050 doomed = handle_init_event(i, res);
12051 }
12052 if (i->doreoriginate && res == DAHDI_EVENT_HOOKCOMPLETE) {
12053 /* Actually automatically reoriginate this FXS line, if directed to.
12054 * We should get a DAHDI_EVENT_HOOKCOMPLETE from the loop disconnect
12055 * doing its thing (one reason why this is for FXOKS only: FXOLS
12056 * hangups don't give us any DAHDI events to piggyback off of)*/
12057 i->doreoriginate = 0;
12058 /* Double check the channel is still off-hook. There's only about a millisecond
12059 * between when doreoriginate is set high and we see that here, but just to be safe. */
12060 if (!my_is_off_hook(i)) {
12061 ast_debug(1, "Woah! Went back on hook before reoriginate could happen on channel %d\n", i->channel);
12062 } else {
12063 ast_verb(3, "Automatic reorigination on channel %d\n", i->channel);
12064 res = DAHDI_EVENT_RINGOFFHOOK; /* Pretend that the physical channel just went off hook */
12065 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
12066 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12067 } else {
12068 doomed = handle_init_event(i, res);
12069 }
12070 }
12071 }
12072 ast_mutex_lock(&iflock);
12073 }
12074 }
12075 }
12076 ast_mutex_unlock(&iflock);
12077 release_doomed_pris();
12078 #ifdef HAVE_OPENR2
12079 dahdi_r2_destroy_nodev();
12080 #endif
12081 }
12082 /* Never reached */
12083 pthread_cleanup_pop(1);
12084 return NULL;
12085
12086 }
12087
12088 static int restart_monitor(void)
12089 {
12090 /* If we're supposed to be stopped -- stay stopped */
12091 if (monitor_thread == AST_PTHREADT_STOP)
12092 return 0;
12093 ast_mutex_lock(&monlock);
12094 if (monitor_thread == pthread_self()) {
12095 ast_mutex_unlock(&monlock);
12096 ast_log(LOG_WARNING, "Cannot kill myself\n");
12097 return -1;
12098 }
12099 if (monitor_thread != AST_PTHREADT_NULL) {
12100 /* Wake up the thread */
12101 pthread_kill(monitor_thread, SIGURG);
12102 } else {
12103 /* Start a new monitor */
12104 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
12105 ast_mutex_unlock(&monlock);
12106 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12107 return -1;
12108 }
12109 }
12110 ast_mutex_unlock(&monlock);
12111 return 0;
12112 }
12113
12114 #if defined(HAVE_PRI)
12115 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
12116 {
12117 int x;
12118 int trunkgroup;
12119 /* Get appropriate trunk group if there is one */
12120 trunkgroup = pris[*span].mastertrunkgroup;
12121 if (trunkgroup) {
12122 /* Select a specific trunk group */
12123 for (x = 0; x < NUM_SPANS; x++) {
12124 if (pris[x].pri.trunkgroup == trunkgroup) {
12125 *span = x;
12126 return 0;
12127 }
12128 }
12129 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12130 *span = -1;
12131 } else {
12132 if (pris[*span].pri.trunkgroup) {
12133 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);
12134 *span = -1;
12135 } else if (pris[*span].mastertrunkgroup) {
12136 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12137 *span = -1;
12138 } else {
12139 if (si->totalchans == 31) {
12140 /* E1 */
12141 pris[*span].dchannels[0] = 16 + offset;
12142 } else if (si->totalchans == 24) {
12143 /* T1 or J1 */
12144 pris[*span].dchannels[0] = 24 + offset;
12145 } else if (si->totalchans == 3) {
12146 /* BRI */
12147 pris[*span].dchannels[0] = 3 + offset;
12148 } else {
12149 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);
12150 *span = -1;
12151 return 0;
12152 }
12153 pris[*span].pri.span = *span + 1;
12154 }
12155 }
12156 return 0;
12157 }
12158 #endif /* defined(HAVE_PRI) */
12159
12160 #if defined(HAVE_PRI)
12161 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12162 {
12163 struct dahdi_spaninfo si;
12164 struct dahdi_params p;
12165 int fd;
12166 int span;
12167 int ospan=0;
12168 int x,y;
12169 for (x = 0; x < NUM_SPANS; x++) {
12170 if (pris[x].pri.trunkgroup == trunkgroup) {
12171 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12172 return -1;
12173 }
12174 }
12175 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12176 if (!channels[y])
12177 break;
12178 memset(&si, 0, sizeof(si));
12179 memset(&p, 0, sizeof(p));
12180 fd = open("/dev/dahdi/channel", O_RDWR);
12181 if (fd < 0) {
12182 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12183 return -1;
12184 }
12185 x = channels[y];
12186 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12187 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12188 close(fd);
12189 return -1;
12190 }
12191 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12192 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12193 close(fd);
12194 return -1;
12195 }
12196 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12197 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12198 close(fd);
12199 return -1;
12200 }
12201 span = p.spanno - 1;
12202 if (pris[span].pri.trunkgroup) {
12203 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12204 close(fd);
12205 return -1;
12206 }
12207 if (pris[span].pri.pvts[0]) {
12208 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12209 close(fd);
12210 return -1;
12211 }
12212 if (!y) {
12213 pris[span].pri.trunkgroup = trunkgroup;
12214 ospan = span;
12215 }
12216 pris[ospan].dchannels[y] = channels[y];
12217 pris[span].pri.span = span + 1;
12218 close(fd);
12219 }
12220 return 0;
12221 }
12222 #endif /* defined(HAVE_PRI) */
12223
12224 #if defined(HAVE_PRI)
12225 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12226 {
12227 if (pris[span].mastertrunkgroup) {
12228 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);
12229 return -1;
12230 }
12231 pris[span].mastertrunkgroup = trunkgroup;
12232 pris[span].prilogicalspan = logicalspan;
12233 return 0;
12234 }
12235 #endif /* defined(HAVE_PRI) */
12236
12237 #if defined(HAVE_SS7)
12238 static unsigned int parse_pointcode(const char *pcstring)
12239 {
12240 unsigned int code1, code2, code3;
12241 int numvals;
12242
12243 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12244 if (numvals == 1)
12245 return code1;
12246 if (numvals == 3)
12247 return (code1 << 16) | (code2 << 8) | code3;
12248
12249 return 0;
12250 }
12251 #endif /* defined(HAVE_SS7) */
12252
12253 #if defined(HAVE_SS7)
12254 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12255 {
12256 if ((linkset < 0) || (linkset >= NUM_SPANS))
12257 return NULL;
12258 else
12259 return &linksets[linkset - 1];
12260 }
12261 #endif /* defined(HAVE_SS7) */
12262
12263 #ifdef HAVE_OPENR2
12264 static void dahdi_r2_destroy_links(void)
12265 {
12266 struct r2link_entry *cur;
12267
12268 /* Queue everything for removal */
12269 AST_LIST_LOCK(&r2links);
12270 AST_LIST_TRAVERSE_SAFE_BEGIN(&r2links, cur, list) {
12271 ast_debug(3, "MFC/R2 link #%d queued for destruction\n", cur->mfcr2.index);
12272 AST_LIST_MOVE_CURRENT(&nodev_r2links, list);
12273 }
12274 AST_LIST_TRAVERSE_SAFE_END;
12275 AST_LIST_UNLOCK(&r2links);
12276 /* Now destroy properly */
12277 dahdi_r2_destroy_nodev();
12278 }
12279
12280 /* This is an artificial convenient capacity, to keep at most a full E1 of channels in a single thread */
12281 #define R2_LINK_CAPACITY 30
12282 static struct r2link_entry *dahdi_r2_get_link(const struct dahdi_chan_conf *conf)
12283 {
12284 struct r2link_entry *cur = NULL;
12285 /* Only create a new R2 link if
12286 1. This is the first link requested
12287 2. Configuration changed
12288 3. We got more channels than supported per link */
12289 AST_LIST_LOCK(&r2links);
12290 if (! AST_LIST_EMPTY(&r2links)) {
12291 cur = AST_LIST_LAST(&r2links);
12292 if (memcmp(&conf->mfcr2, &cur->mfcr2.conf, sizeof(conf->mfcr2))) {
12293 ast_debug(3, "Need new R2 link because of: Configuration change\n");
12294 cur = NULL;
12295 } else if (cur->mfcr2.numchans == R2_LINK_CAPACITY) {
12296 ast_debug(3, "Need new R2 link because of: Capacity (%d)\n", R2_LINK_CAPACITY);
12297 cur = NULL;
12298 }
12299 }
12300 if (!cur) {
12301 struct r2link_entry *tmp = NULL;
12302 int new_idx = r2links_count + 1;
12303 int i;
12304 for (i = 1; i <= r2links_count; i++) {
12305 int i_unused = 1;
12306 AST_LIST_TRAVERSE(&r2links, tmp, list) {
12307 if (i == tmp->mfcr2.index) {
12308 i_unused = 0;
12309 break;
12310 }
12311 }
12312 if (i_unused) {
12313 new_idx = i;
12314 break;
12315 }
12316 }
12317 cur = ast_calloc(1, sizeof(*cur));
12318 if (!cur) {
12319 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12320 return NULL;
12321 }
12322 cur->mfcr2.index = new_idx;
12323 cur->mfcr2.r2master = AST_PTHREADT_NULL;
12324 r2links_count++;
12325 ast_debug(3, "Created new R2 link #%d (now have %d)\n", new_idx, r2links_count);
12326 AST_LIST_INSERT_TAIL(&r2links, cur, list);
12327 }
12328 AST_LIST_UNLOCK(&r2links);
12329 return cur;
12330 }
12331
12332 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12333 {
12334 char tmplogdir[] = "/tmp";
12335 char logdir[OR2_MAX_PATH];
12336 int threshold = 0;
12337 int snres = 0;
12338 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12339 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12340 conf->mfcr2.max_dnis);
12341 if (!r2_link->protocol_context) {
12342 return -1;
12343 }
12344 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12345 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12346 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12347 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12348 #endif
12349 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12350 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12351 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12352 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12353 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12354 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12355 openr2_context_set_dtmf_dialing(r2_link->protocol_context, conf->mfcr2.dtmf_dialing, conf->mfcr2.dtmf_time_on, conf->mfcr2.dtmf_time_off);
12356 openr2_context_set_dtmf_detection(r2_link->protocol_context, conf->mfcr2.dtmf_detection);
12357 #endif
12358 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
12359 openr2_context_set_dtmf_detection_end_timeout(r2_link->protocol_context, conf->mfcr2.dtmf_end_timeout);
12360 #endif
12361 if (ast_strlen_zero(conf->mfcr2.logdir)) {
12362 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12363 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12364 }
12365 } else {
12366 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12367 if (snres >= sizeof(logdir)) {
12368 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12369 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12370 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12371 }
12372 } else {
12373 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12374 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12375 }
12376 }
12377 }
12378 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12379 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12380 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12381 }
12382 }
12383 /* Save the configuration used to setup this link */
12384 memcpy(&r2_link->conf, &conf->mfcr2, sizeof(r2_link->conf));
12385 return 0;
12386 }
12387 #endif
12388
12389 /* converts a DAHDI sigtype to signalling as can be configured from
12390 * chan_dahdi.conf.
12391 * While both have basically the same values, this will later be the
12392 * place to add filters and sanity checks
12393 */
12394 static int sigtype_to_signalling(int sigtype)
12395 {
12396 return sigtype;
12397 }
12398
12399 /*!
12400 * \internal
12401 * \brief Initialize/create a channel interface.
12402 *
12403 * \param channel Channel interface number to initialize/create.
12404 * \param conf Configuration parameters to initialize interface with.
12405 * \param reloading What we are doing now:
12406 * 0 - initial module load,
12407 * 1 - module reload,
12408 * 2 - module restart
12409 *
12410 * \retval Interface-pointer initialized/created
12411 * \retval NULL if error
12412 */
12413 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12414 {
12415 /* Make a dahdi_pvt structure for this interface */
12416 struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12417 char fn[80];
12418 struct dahdi_bufferinfo bi;
12419
12420 int res;
12421 #if defined(HAVE_PRI)
12422 int span = 0;
12423 #endif /* defined(HAVE_PRI) */
12424 int here = 0;/*!< TRUE if the channel interface already exists. */
12425 int x;
12426 struct analog_pvt *analog_p = NULL;
12427 struct dahdi_params p;
12428 #if defined(HAVE_PRI)
12429 struct dahdi_spaninfo si;
12430 struct sig_pri_chan *pri_chan = NULL;
12431 #endif /* defined(HAVE_PRI) */
12432 #if defined(HAVE_SS7)
12433 struct sig_ss7_chan *ss7_chan = NULL;
12434 #endif /* defined(HAVE_SS7) */
12435
12436 /* Search channel interface list to see if it already exists. */
12437 for (tmp = iflist; tmp; tmp = tmp->next) {
12438 if (!tmp->destroy) {
12439 if (tmp->channel == channel) {
12440 /* The channel interface already exists. */
12441 here = 1;
12442 break;
12443 }
12444 if (tmp->channel > channel) {
12445 /* No way it can be in the sorted list. */
12446 tmp = NULL;
12447 break;
12448 }
12449 }
12450 }
12451
12452 if (!here && reloading != 1) {
12453 tmp = ast_calloc(1, sizeof(*tmp));
12454 if (!tmp) {
12455 return NULL;
12456 }
12457 tmp->cc_params = ast_cc_config_params_init();
12458 if (!tmp->cc_params) {
12459 ast_free(tmp);
12460 return NULL;
12461 }
12462 ast_mutex_init(&tmp->lock);
12463 ifcount++;
12464 for (x = 0; x < 3; x++)
12465 tmp->subs[x].dfd = -1;
12466 tmp->channel = channel;
12467 tmp->priindication_oob = conf->chan.priindication_oob;
12468 }
12469
12470 if (tmp) {
12471 int chan_sig = conf->chan.sig;
12472
12473 /* If there are variables in tmp before it is updated to match the new config, clear them */
12474 if (reloading && tmp->vars) {
12475 ast_variables_destroy(tmp->vars);
12476 tmp->vars = NULL;
12477 }
12478
12479 if (!here) {
12480 /* Can only get here if this is a new channel interface being created. */
12481 if ((channel != CHAN_PSEUDO)) {
12482 int count = 0;
12483
12484 snprintf(fn, sizeof(fn), "%d", channel);
12485 /* Open non-blocking */
12486 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12487 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) { /* the kernel may not call dahdi_release fast enough for the open flagbit to be cleared in time */
12488 usleep(1);
12489 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12490 count++;
12491 }
12492 /* Allocate a DAHDI structure */
12493 if (tmp->subs[SUB_REAL].dfd < 0) {
12494 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);
12495 destroy_dahdi_pvt(tmp);
12496 return NULL;
12497 }
12498 memset(&p, 0, sizeof(p));
12499 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12500 if (res < 0) {
12501 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12502 destroy_dahdi_pvt(tmp);
12503 return NULL;
12504 }
12505 if (conf->is_sig_auto)
12506 chan_sig = sigtype_to_signalling(p.sigtype);
12507 if (p.sigtype != (chan_sig & 0x3ffff)) {
12508 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));
12509 destroy_dahdi_pvt(tmp);
12510 return NULL;
12511 }
12512 tmp->law_default = p.curlaw;
12513 tmp->law = p.curlaw;
12514 tmp->span = p.spanno;
12515 #if defined(HAVE_PRI)
12516 span = p.spanno - 1;
12517 #endif /* defined(HAVE_PRI) */
12518 } else {
12519 chan_sig = 0;
12520 }
12521 tmp->sig = chan_sig;
12522 tmp->outsigmod = conf->chan.outsigmod;
12523
12524 if (dahdi_analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12525 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), tmp);
12526 if (!analog_p) {
12527 destroy_dahdi_pvt(tmp);
12528 return NULL;
12529 }
12530 tmp->sig_pvt = analog_p;
12531 }
12532 #if defined(HAVE_SS7)
12533 if (chan_sig == SIG_SS7) {
12534 struct dahdi_ss7 *ss7;
12535 int clear = 0;
12536
12537 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12538 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12539 destroy_dahdi_pvt(tmp);
12540 return NULL;
12541 }
12542
12543 ss7 = ss7_resolve_linkset(cur_linkset);
12544 if (!ss7) {
12545 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12546 destroy_dahdi_pvt(tmp);
12547 return NULL;
12548 }
12549 ss7->ss7.span = cur_linkset;
12550 if (cur_cicbeginswith < 0) {
12551 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12552 destroy_dahdi_pvt(tmp);
12553 return NULL;
12554 }
12555 ss7_chan = sig_ss7_chan_new(tmp, &ss7->ss7);
12556 if (!ss7_chan) {
12557 destroy_dahdi_pvt(tmp);
12558 return NULL;
12559 }
12560 tmp->sig_pvt = ss7_chan;
12561 tmp->ss7 = &ss7->ss7;
12562
12563 ss7_chan->channel = tmp->channel;
12564 ss7_chan->cic = cur_cicbeginswith++;
12565
12566 /* DB: Add CIC's DPC information */
12567 ss7_chan->dpc = cur_defaultdpc;
12568
12569 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12570
12571 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12572 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12573 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12574 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12575 ast_copy_string(ss7->ss7.networkroutedprefix, conf->ss7.ss7.networkroutedprefix, sizeof(ss7->ss7.networkroutedprefix));
12576
12577 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12578 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12579 }
12580 #endif /* defined(HAVE_SS7) */
12581 #ifdef HAVE_OPENR2
12582 if (chan_sig == SIG_MFCR2) {
12583 struct dahdi_mfcr2 *r2_link;
12584 struct r2link_entry *r2_le = dahdi_r2_get_link(conf);
12585 r2_link = &r2_le->mfcr2;
12586 if (!r2_link) {
12587 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12588 destroy_dahdi_pvt(tmp);
12589 return NULL;
12590 }
12591 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12592 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12593 destroy_dahdi_pvt(tmp);
12594 return NULL;
12595 }
12596 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12597 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12598 destroy_dahdi_pvt(tmp);
12599 return NULL;
12600 }
12601 r2_link->pvts[r2_link->numchans++] = tmp;
12602 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12603 tmp->subs[SUB_REAL].dfd,
12604 NULL, NULL);
12605 if (!tmp->r2chan) {
12606 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12607 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12608 destroy_dahdi_pvt(tmp);
12609 return NULL;
12610 }
12611 r2_link->live_chans++;
12612 tmp->mfcr2 = r2_link;
12613 if (conf->mfcr2.call_files) {
12614 openr2_chan_enable_call_files(tmp->r2chan);
12615 }
12616 openr2_chan_set_client_data(tmp->r2chan, tmp);
12617 /* cast seems to be needed to get rid of the annoying warning regarding format attribute */
12618 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12619 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12620 tmp->mfcr2_category = conf->mfcr2.category;
12621 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12622 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12623 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12624 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12625 tmp->mfcr2call = 0;
12626 tmp->mfcr2_dnis_index = 0;
12627 tmp->mfcr2_ani_index = 0;
12628 }
12629 #endif
12630 #ifdef HAVE_PRI
12631 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12632 int offset;
12633 int matchesdchan;
12634 int x,y;
12635 int myswitchtype = 0;
12636
12637 offset = 0;
12638 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12639 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12640 destroy_dahdi_pvt(tmp);
12641 return NULL;
12642 }
12643 if (span >= NUM_SPANS) {
12644 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12645 destroy_dahdi_pvt(tmp);
12646 return NULL;
12647 } else {
12648 si.spanno = 0;
12649 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12650 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12651 destroy_dahdi_pvt(tmp);
12652 return NULL;
12653 }
12654 /* Store the logical span first based upon the real span */
12655 tmp->logicalspan = pris[span].prilogicalspan;
12656 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12657 if (span < 0) {
12658 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12659 destroy_dahdi_pvt(tmp);
12660 return NULL;
12661 }
12662 myswitchtype = conf->pri.pri.switchtype;
12663 /* Make sure this isn't a d-channel */
12664 matchesdchan=0;
12665 for (x = 0; x < NUM_SPANS; x++) {
12666 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12667 if (pris[x].dchannels[y] == tmp->channel) {
12668 matchesdchan = 1;
12669 break;
12670 }
12671 }
12672 }
12673 if (!matchesdchan) {
12674 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12675 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12676 destroy_dahdi_pvt(tmp);
12677 return NULL;
12678 }
12679 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12680 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12681 destroy_dahdi_pvt(tmp);
12682 return NULL;
12683 }
12684 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12685 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));
12686 destroy_dahdi_pvt(tmp);
12687 return NULL;
12688 }
12689 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12690 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12691 destroy_dahdi_pvt(tmp);
12692 return NULL;
12693 }
12694 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12695 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12696 destroy_dahdi_pvt(tmp);
12697 return NULL;
12698 }
12699 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12700 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12701 destroy_dahdi_pvt(tmp);
12702 return NULL;
12703 }
12704 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12705 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12706 destroy_dahdi_pvt(tmp);
12707 return NULL;
12708 }
12709 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12710 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12711 pris[span].pri.trunkgroup);
12712 destroy_dahdi_pvt(tmp);
12713 return NULL;
12714 }
12715
12716 pri_chan = sig_pri_chan_new(tmp, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12717 if (!pri_chan) {
12718 destroy_dahdi_pvt(tmp);
12719 return NULL;
12720 }
12721 tmp->sig_pvt = pri_chan;
12722 tmp->pri = &pris[span].pri;
12723
12724 tmp->priexclusive = conf->chan.priexclusive;
12725
12726 if (!tmp->pri->cc_params) {
12727 tmp->pri->cc_params = ast_cc_config_params_init();
12728 if (!tmp->pri->cc_params) {
12729 destroy_dahdi_pvt(tmp);
12730 return NULL;
12731 }
12732 }
12733 ast_cc_copy_config_params(tmp->pri->cc_params,
12734 conf->chan.cc_params);
12735
12736 pris[span].pri.sig = chan_sig;
12737 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12738 pris[span].pri.switchtype = myswitchtype;
12739 pris[span].pri.nsf = conf->pri.pri.nsf;
12740 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12741 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12742 pris[span].pri.cpndialplan = conf->pri.pri.cpndialplan;
12743 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12744 pris[span].pri.minunused = conf->pri.pri.minunused;
12745 pris[span].pri.minidle = conf->pri.pri.minidle;
12746 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12747 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12748 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12749 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12750 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12751 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12752 #ifdef HAVE_PRI_INBANDDISCONNECT
12753 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12754 #endif
12755 #if defined(HAVE_PRI_CALL_HOLD)
12756 pris[span].pri.hold_disconnect_transfer =
12757 conf->pri.pri.hold_disconnect_transfer;
12758 #endif /* defined(HAVE_PRI_CALL_HOLD) */
12759 #if defined(HAVE_PRI_CCSS)
12760 pris[span].pri.cc_ptmp_recall_mode =
12761 conf->pri.pri.cc_ptmp_recall_mode;
12762 pris[span].pri.cc_qsig_signaling_link_req =
12763 conf->pri.pri.cc_qsig_signaling_link_req;
12764 pris[span].pri.cc_qsig_signaling_link_rsp =
12765 conf->pri.pri.cc_qsig_signaling_link_rsp;
12766 #endif /* defined(HAVE_PRI_CCSS) */
12767 #if defined(HAVE_PRI_CALL_WAITING)
12768 pris[span].pri.max_call_waiting_calls =
12769 conf->pri.pri.max_call_waiting_calls;
12770 pris[span].pri.allow_call_waiting_calls =
12771 conf->pri.pri.allow_call_waiting_calls;
12772 #endif /* defined(HAVE_PRI_CALL_WAITING) */
12773 pris[span].pri.transfer = conf->chan.transfer;
12774 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12775 #if defined(HAVE_PRI_L2_PERSISTENCE)
12776 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12777 #endif /* defined(HAVE_PRI_L2_PERSISTENCE) */
12778 pris[span].pri.colp_send = conf->pri.pri.colp_send;
12779 #if defined(HAVE_PRI_AOC_EVENTS)
12780 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12781 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12782 #endif /* defined(HAVE_PRI_AOC_EVENTS) */
12783 if (chan_sig == SIG_BRI_PTMP) {
12784 pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12785 } else {
12786 /* Option does not apply to this line type. */
12787 pris[span].pri.layer1_ignored = 0;
12788 }
12789 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12790 pris[span].pri.inband_on_setup_ack = conf->pri.pri.inband_on_setup_ack;
12791 pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
12792 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12793 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12794 #if defined(HAVE_PRI_MWI)
12795 ast_copy_string(pris[span].pri.mwi_mailboxes,
12796 conf->pri.pri.mwi_mailboxes,
12797 sizeof(pris[span].pri.mwi_mailboxes));
12798 ast_copy_string(pris[span].pri.mwi_vm_boxes,
12799 conf->pri.pri.mwi_vm_boxes,
12800 sizeof(pris[span].pri.mwi_vm_boxes));
12801 ast_copy_string(pris[span].pri.mwi_vm_numbers,
12802 conf->pri.pri.mwi_vm_numbers,
12803 sizeof(pris[span].pri.mwi_vm_numbers));
12804 #endif /* defined(HAVE_PRI_MWI) */
12805 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12806 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12807 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12808 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12809 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12810 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12811 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12812 pris[span].pri.moh_signaling = conf->pri.pri.moh_signaling;
12813 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12814 #if defined(HAVE_PRI_DISPLAY_TEXT)
12815 pris[span].pri.display_flags_send = conf->pri.pri.display_flags_send;
12816 pris[span].pri.display_flags_receive = conf->pri.pri.display_flags_receive;
12817 #endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
12818 #if defined(HAVE_PRI_MCID)
12819 pris[span].pri.mcid_send = conf->pri.pri.mcid_send;
12820 #endif /* defined(HAVE_PRI_MCID) */
12821 pris[span].pri.force_restart_unavailable_chans = conf->pri.pri.force_restart_unavailable_chans;
12822 #if defined(HAVE_PRI_DATETIME_SEND)
12823 pris[span].pri.datetime_send = conf->pri.pri.datetime_send;
12824 #endif /* defined(HAVE_PRI_DATETIME_SEND) */
12825
12826 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12827 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12828 }
12829
12830 #if defined(HAVE_PRI_CALL_WAITING)
12831 /* Channel initial config parameters. */
12832 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12833 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12834 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12835 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12836 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12837 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12838 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12839 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12840 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12841 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12842 #endif /* defined(HAVE_PRI_CALL_WAITING) */
12843 } else {
12844 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12845 destroy_dahdi_pvt(tmp);
12846 return NULL;
12847 }
12848 }
12849 }
12850 #endif
12851 } else {
12852 /* already exists in interface list */
12853 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));
12854 chan_sig = tmp->sig;
12855 if (tmp->subs[SUB_REAL].dfd > -1) {
12856 memset(&p, 0, sizeof(p));
12857 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12858 }
12859 }
12860 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12861 switch (chan_sig) {
12862 case SIG_FXSKS:
12863 case SIG_FXSLS:
12864 case SIG_EM:
12865 case SIG_EM_E1:
12866 case SIG_EMWINK:
12867 case SIG_FEATD:
12868 case SIG_FEATDMF:
12869 case SIG_FEATDMF_TA:
12870 case SIG_FEATB:
12871 case SIG_E911:
12872 case SIG_SF:
12873 case SIG_SFWINK:
12874 case SIG_FGC_CAMA:
12875 case SIG_FGC_CAMAMF:
12876 case SIG_SF_FEATD:
12877 case SIG_SF_FEATDMF:
12878 case SIG_SF_FEATB:
12879 p.starttime = 250;
12880 break;
12881 }
12882
12883 if (tmp->radio) {
12884 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12885 p.channo = channel;
12886 p.rxwinktime = 1;
12887 p.rxflashtime = 1;
12888 p.starttime = 1;
12889 p.debouncetime = 5;
12890 } else {
12891 p.channo = channel;
12892 /* Override timing settings based on config file */
12893 if (conf->timing.prewinktime >= 0)
12894 p.prewinktime = conf->timing.prewinktime;
12895 if (conf->timing.preflashtime >= 0)
12896 p.preflashtime = conf->timing.preflashtime;
12897 if (conf->timing.winktime >= 0)
12898 p.winktime = conf->timing.winktime;
12899 if (conf->timing.flashtime >= 0)
12900 p.flashtime = conf->timing.flashtime;
12901 if (conf->timing.starttime >= 0)
12902 p.starttime = conf->timing.starttime;
12903 if (conf->timing.rxwinktime >= 0)
12904 p.rxwinktime = conf->timing.rxwinktime;
12905 if (conf->timing.rxflashtime >= 0)
12906 p.rxflashtime = conf->timing.rxflashtime;
12907 if (conf->timing.debouncetime >= 0)
12908 p.debouncetime = conf->timing.debouncetime;
12909 }
12910
12911 /* don't set parms on a pseudo-channel */
12912 if (tmp->subs[SUB_REAL].dfd >= 0)
12913 {
12914 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12915 if (res < 0) {
12916 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12917 destroy_dahdi_pvt(tmp);
12918 return NULL;
12919 }
12920 }
12921 #if 1
12922 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12923 memset(&bi, 0, sizeof(bi));
12924 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12925 if (!res) {
12926 bi.txbufpolicy = conf->chan.buf_policy;
12927 bi.rxbufpolicy = conf->chan.buf_policy;
12928 bi.numbufs = conf->chan.buf_no;
12929 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12930 if (res < 0) {
12931 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12932 }
12933 } else {
12934 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12935 }
12936 tmp->buf_policy = conf->chan.buf_policy;
12937 tmp->buf_no = conf->chan.buf_no;
12938 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12939 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12940 tmp->faxbuf_no = conf->chan.faxbuf_no;
12941 /* This is not as gnarly as it may first appear. If the ioctl above failed, we'd be setting
12942 * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
12943 * The reason the ioctl call above failed should to be determined before worrying about the
12944 * faxbuffer-related ioctl calls */
12945 tmp->bufsize = bi.bufsize;
12946 }
12947 #endif
12948 tmp->immediate = conf->chan.immediate;
12949 tmp->immediatering = conf->chan.immediatering;
12950 tmp->transfertobusy = conf->chan.transfertobusy;
12951 tmp->dialmode = conf->chan.dialmode;
12952 if (chan_sig & __DAHDI_SIG_FXS) {
12953 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12954 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12955 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12956 }
12957 tmp->ringt_base = ringt_base;
12958 tmp->firstradio = 0;
12959 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12960 tmp->permcallwaiting = conf->chan.callwaiting;
12961 else
12962 tmp->permcallwaiting = 0;
12963 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
12964 tmp->destroy = 0;
12965 tmp->drings = conf->chan.drings;
12966
12967 /* 10 is a nice default. */
12968 if (tmp->drings.ringnum[0].range == 0)
12969 tmp->drings.ringnum[0].range = 10;
12970 if (tmp->drings.ringnum[1].range == 0)
12971 tmp->drings.ringnum[1].range = 10;
12972 if (tmp->drings.ringnum[2].range == 0)
12973 tmp->drings.ringnum[2].range = 10;
12974
12975 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12976 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12977 tmp->threewaycalling = conf->chan.threewaycalling;
12978 tmp->threewaysilenthold = conf->chan.threewaysilenthold;
12979 tmp->calledsubscriberheld = conf->chan.calledsubscriberheld; /* Not used in chan_dahdi.c, just analog pvt, but must exist on the DAHDI pvt anyways */
12980 tmp->adsi = conf->chan.adsi;
12981 tmp->use_smdi = conf->chan.use_smdi;
12982 tmp->permhidecallerid = conf->chan.hidecallerid;
12983 tmp->hidecalleridname = conf->chan.hidecalleridname;
12984 tmp->callreturn = conf->chan.callreturn;
12985 tmp->echocancel = conf->chan.echocancel;
12986 tmp->echotraining = conf->chan.echotraining;
12987 tmp->pulse = conf->chan.pulse;
12988 if (tmp->echocancel.head.tap_length) {
12989 tmp->echocanbridged = conf->chan.echocanbridged;
12990 } else {
12991 if (conf->chan.echocanbridged)
12992 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12993 tmp->echocanbridged = 0;
12994 }
12995 tmp->busydetect = conf->chan.busydetect;
12996 tmp->busycount = conf->chan.busycount;
12997 tmp->busy_cadence = conf->chan.busy_cadence;
12998 tmp->callprogress = conf->chan.callprogress;
12999 tmp->waitfordialtone = conf->chan.waitfordialtone;
13000 tmp->dialtone_detect = conf->chan.dialtone_detect;
13001 tmp->faxdetect_timeout = conf->chan.faxdetect_timeout;
13002 tmp->firstdigit_timeout = conf->chan.firstdigit_timeout;
13003 tmp->interdigit_timeout = conf->chan.interdigit_timeout;
13004 tmp->matchdigit_timeout = conf->chan.matchdigit_timeout;
13005 tmp->cancallforward = conf->chan.cancallforward;
13006 tmp->dtmfrelax = conf->chan.dtmfrelax;
13007 tmp->callwaiting = tmp->permcallwaiting;
13008 tmp->hidecallerid = tmp->permhidecallerid;
13009 tmp->channel = channel;
13010 tmp->stripmsd = conf->chan.stripmsd;
13011 tmp->use_callerid = conf->chan.use_callerid;
13012 tmp->cid_signalling = conf->chan.cid_signalling;
13013 tmp->cid_start = conf->chan.cid_start;
13014 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
13015 tmp->restrictcid = conf->chan.restrictcid;
13016 tmp->use_callingpres = conf->chan.use_callingpres;
13017 if (tmp->usedistinctiveringdetection) {
13018 if (!tmp->use_callerid) {
13019 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
13020 tmp->use_callerid = 1;
13021 }
13022 }
13023
13024 if (tmp->cid_signalling == CID_SIG_SMDI) {
13025 if (!tmp->use_smdi) {
13026 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
13027 tmp->use_smdi = 1;
13028 }
13029 }
13030 if (tmp->use_smdi) {
13031 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
13032 if (!(tmp->smdi_iface)) {
13033 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
13034 tmp->use_smdi = 0;
13035 }
13036 }
13037
13038 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
13039 tmp->amaflags = conf->chan.amaflags;
13040 if (!here) {
13041 tmp->confno = -1;
13042 tmp->propconfno = -1;
13043 }
13044 tmp->canpark = conf->chan.canpark;
13045 tmp->transfer = conf->chan.transfer;
13046 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
13047 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
13048 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
13049 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
13050 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
13051 ast_copy_string(tmp->description, conf->chan.description, sizeof(tmp->description));
13052 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
13053 tmp->cid_ton = 0;
13054 if (dahdi_analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
13055 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
13056 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
13057 } else {
13058 tmp->cid_num[0] = '\0';
13059 tmp->cid_name[0] = '\0';
13060 }
13061 #if defined(HAVE_PRI)
13062 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
13063 tmp->cid_tag[0] = '\0';
13064 } else
13065 #endif /* defined(HAVE_PRI) */
13066 {
13067 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
13068 }
13069 tmp->cid_subaddr[0] = '\0';
13070 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
13071 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
13072 /* This module does not handle MWI in an event-based manner. However, it
13073 * subscribes to MWI for each mailbox that is configured so that the core
13074 * knows that we care about it. Then, chan_dahdi will get the MWI from the
13075 * event cache instead of checking the mailbox directly. */
13076 tmp->mwi_event_sub = ast_mwi_subscribe_pool(tmp->mailbox, stasis_subscription_cb_noop, NULL);
13077 }
13078 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13079 tmp->mwisend_setting = conf->chan.mwisend_setting;
13080 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
13081 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
13082 #endif
13083
13084 tmp->group = conf->chan.group;
13085 tmp->callgroup = conf->chan.callgroup;
13086 tmp->pickupgroup= conf->chan.pickupgroup;
13087 ast_unref_namedgroups(tmp->named_callgroups);
13088 tmp->named_callgroups = ast_ref_namedgroups(conf->chan.named_callgroups);
13089 ast_unref_namedgroups(tmp->named_pickupgroups);
13090 tmp->named_pickupgroups = ast_ref_namedgroups(conf->chan.named_pickupgroups);
13091 if (conf->chan.vars) {
13092 struct ast_variable *v, *tmpvar;
13093 for (v = conf->chan.vars ; v ; v = v->next) {
13094 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
13095 if (ast_variable_list_replace(&tmp->vars, tmpvar)) {
13096 tmpvar->next = tmp->vars;
13097 tmp->vars = tmpvar;
13098 }
13099 }
13100 }
13101 }
13102 tmp->hwrxgain_enabled = conf->chan.hwrxgain_enabled;
13103 tmp->hwtxgain_enabled = conf->chan.hwtxgain_enabled;
13104 tmp->hwrxgain = conf->chan.hwrxgain;
13105 tmp->hwtxgain = conf->chan.hwtxgain;
13106 tmp->cid_rxgain = conf->chan.cid_rxgain;
13107 tmp->rxgain = conf->chan.rxgain;
13108 tmp->txgain = conf->chan.txgain;
13109 tmp->txdrc = conf->chan.txdrc;
13110 tmp->rxdrc = conf->chan.rxdrc;
13111 tmp->tonezone = conf->chan.tonezone;
13112 if (tmp->subs[SUB_REAL].dfd > -1) {
13113 if (tmp->hwrxgain_enabled) {
13114 tmp->hwrxgain_enabled = !set_hwgain(tmp->subs[SUB_REAL].dfd, tmp->hwrxgain, 0);
13115 }
13116 if (tmp->hwtxgain_enabled) {
13117 tmp->hwtxgain_enabled = !set_hwgain(tmp->subs[SUB_REAL].dfd, tmp->hwtxgain, 1);
13118 }
13119 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
13120 if (tmp->dsp)
13121 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13122 dahdi_conf_update(tmp);
13123 if (!here) {
13124 switch (chan_sig) {
13125 case SIG_PRI_LIB_HANDLE_CASES:
13126 case SIG_SS7:
13127 case SIG_MFCR2:
13128 break;
13129 default:
13130 /* Hang it up to be sure it's good */
13131 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13132 break;
13133 }
13134 }
13135 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13136 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13137 /* the dchannel is down so put the channel in alarm */
13138 switch (tmp->sig) {
13139 #ifdef HAVE_PRI
13140 case SIG_PRI_LIB_HANDLE_CASES:
13141 sig_pri_set_alarm(tmp->sig_pvt, 1);
13142 break;
13143 #endif
13144 #if defined(HAVE_SS7)
13145 case SIG_SS7:
13146 sig_ss7_set_alarm(tmp->sig_pvt, 1);
13147 break;
13148 #endif /* defined(HAVE_SS7) */
13149 default:
13150 /* The only sig submodule left should be sig_analog. */
13151 analog_p = tmp->sig_pvt;
13152 if (analog_p) {
13153 analog_p->inalarm = 1;
13154 }
13155 tmp->inalarm = 1;
13156 break;
13157 }
13158 handle_alarms(tmp, res);
13159 }
13160 }
13161
13162 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13163 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13164 tmp->ani_info_digits = conf->chan.ani_info_digits;
13165 tmp->ani_wink_time = conf->chan.ani_wink_time;
13166 tmp->ani_timeout = conf->chan.ani_timeout;
13167 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13168 tmp->reoriginate = conf->chan.reoriginate;
13169 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13170 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13171
13172 if (!here) {
13173 tmp->locallyblocked = 0;
13174 tmp->remotelyblocked = 0;
13175 switch (tmp->sig) {
13176 #if defined(HAVE_PRI)
13177 case SIG_PRI_LIB_HANDLE_CASES:
13178 tmp->inservice = 1;/* Inservice until actually implemented. */
13179 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13180 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13181 if (chan_sig == SIG_PRI) {
13182 char db_chan_name[20];
13183 char db_answer[5];
13184
13185 /*
13186 * Initialize the active out-of-service status
13187 * and delete any record if the feature is not enabled.
13188 */
13189 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13190 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13191 unsigned *why;
13192
13193 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13194 if (tmp->pri->enable_service_message_support) {
13195 char state;
13196
13197 sscanf(db_answer, "%1c:%30u", &state, why);
13198
13199 /* Ensure that only the implemented bits could be set.*/
13200 *why &= (SRVST_NEAREND | SRVST_FAREND);
13201 }
13202 if (!*why) {
13203 ast_db_del(db_chan_name, SRVST_DBKEY);
13204 }
13205 }
13206 }
13207 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
13208 break;
13209 #endif /* defined(HAVE_PRI) */
13210 #if defined(HAVE_SS7)
13211 case SIG_SS7:
13212 tmp->inservice = 0;
13213 if (tmp->ss7->flags & LINKSET_FLAG_INITIALHWBLO) {
13214 tmp->remotelyblocked |= SS7_BLOCKED_HARDWARE;
13215 }
13216 break;
13217 #endif /* defined(HAVE_SS7) */
13218 default:
13219 /* We default to in service on protocols that don't have a reset */
13220 tmp->inservice = 1;
13221 break;
13222 }
13223 }
13224
13225 switch (tmp->sig) {
13226 #if defined(HAVE_PRI)
13227 case SIG_PRI_LIB_HANDLE_CASES:
13228 if (pri_chan) {
13229 pri_chan->channel = tmp->channel;
13230 pri_chan->hidecallerid = tmp->hidecallerid;
13231 pri_chan->hidecalleridname = tmp->hidecalleridname;
13232 pri_chan->immediate = tmp->immediate;
13233 pri_chan->inalarm = tmp->inalarm;
13234 pri_chan->priexclusive = tmp->priexclusive;
13235 pri_chan->priindication_oob = tmp->priindication_oob;
13236 pri_chan->use_callerid = tmp->use_callerid;
13237 pri_chan->use_callingpres = tmp->use_callingpres;
13238 ast_copy_string(pri_chan->context, tmp->context,
13239 sizeof(pri_chan->context));
13240 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13241 sizeof(pri_chan->mohinterpret));
13242 pri_chan->stripmsd = tmp->stripmsd;
13243 }
13244 break;
13245 #endif /* defined(HAVE_PRI) */
13246 #if defined(HAVE_SS7)
13247 case SIG_SS7:
13248 if (ss7_chan) {
13249 ss7_chan->inalarm = tmp->inalarm;
13250 ss7_chan->inservice = tmp->inservice;
13251
13252 ss7_chan->stripmsd = tmp->stripmsd;
13253 ss7_chan->hidecallerid = tmp->hidecallerid;
13254 ss7_chan->use_callerid = tmp->use_callerid;
13255 ss7_chan->use_callingpres = tmp->use_callingpres;
13256 ss7_chan->immediate = tmp->immediate;
13257 ss7_chan->locallyblocked = tmp->locallyblocked;
13258 ss7_chan->remotelyblocked = tmp->remotelyblocked;
13259 ast_copy_string(ss7_chan->context, tmp->context,
13260 sizeof(ss7_chan->context));
13261 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13262 sizeof(ss7_chan->mohinterpret));
13263 }
13264 break;
13265 #endif /* defined(HAVE_SS7) */
13266 default:
13267 /* The only sig submodule left should be sig_analog. */
13268 analog_p = tmp->sig_pvt;
13269 if (analog_p) {
13270 analog_p->channel = tmp->channel;
13271 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13272 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13273 analog_p->ani_info_digits = conf->chan.ani_info_digits;
13274 analog_p->ani_timeout = conf->chan.ani_timeout;
13275 analog_p->ani_wink_time = conf->chan.ani_wink_time;
13276 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13277 analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13278 analog_p->calledsubscriberheld = conf->chan.calledsubscriberheld; /* Only actually used in analog pvt, not DAHDI pvt */
13279 analog_p->callreturn = conf->chan.callreturn;
13280 analog_p->cancallforward = conf->chan.cancallforward;
13281 analog_p->canpark = conf->chan.canpark;
13282 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13283 analog_p->immediate = conf->chan.immediate;
13284 analog_p->immediatering = conf->chan.immediatering;
13285 analog_p->permhidecallerid = conf->chan.hidecallerid; /* hidecallerid is the config setting, not permhidecallerid (~permcallwaiting above) */
13286 /* It's not necessary to set analog_p->hidecallerid here, sig_analog will set hidecallerid=permhidecaller before each call */
13287 analog_p->pulse = conf->chan.pulse;
13288 analog_p->threewaycalling = conf->chan.threewaycalling;
13289 analog_p->transfer = conf->chan.transfer;
13290 analog_p->transfertobusy = conf->chan.transfertobusy;
13291 analog_p->dialmode = conf->chan.dialmode;
13292 analog_p->use_callerid = tmp->use_callerid;
13293 analog_p->usedistinctiveringdetection = tmp->usedistinctiveringdetection;
13294 analog_p->use_smdi = tmp->use_smdi;
13295 analog_p->smdi_iface = tmp->smdi_iface;
13296 analog_p->outsigmod = ANALOG_SIG_NONE;
13297 analog_p->echotraining = conf->chan.echotraining;
13298 analog_p->cid_signalling = conf->chan.cid_signalling;
13299 analog_p->stripmsd = conf->chan.stripmsd;
13300 switch (conf->chan.cid_start) {
13301 case CID_START_POLARITY:
13302 analog_p->cid_start = ANALOG_CID_START_POLARITY;
13303 break;
13304 case CID_START_POLARITY_IN:
13305 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13306 break;
13307 case CID_START_DTMF_NOALERT:
13308 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13309 break;
13310 default:
13311 analog_p->cid_start = ANALOG_CID_START_RING;
13312 break;
13313 }
13314 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13315 analog_p->ringt = conf->chan.ringt;
13316 analog_p->ringt_base = ringt_base;
13317 analog_p->onhooktime = time(NULL);
13318 if (chan_sig & __DAHDI_SIG_FXO) {
13319 memset(&p, 0, sizeof(p));
13320 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13321 if (!res) {
13322 analog_p->fxsoffhookstate = p.rxisoffhook;
13323 }
13324 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13325 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13326 #endif
13327 }
13328 analog_p->msgstate = -1;
13329
13330 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13331 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13332 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13333
13334 analog_config_complete(analog_p);
13335 }
13336 break;
13337 }
13338 #if defined(HAVE_PRI)
13339 if (tmp->channel == CHAN_PSEUDO) {
13340 /*
13341 * Save off pseudo channel buffer policy values for dynamic creation of
13342 * no B channel interfaces.
13343 */
13344 dahdi_pseudo_parms.buf_no = tmp->buf_no;
13345 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13346 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13347 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13348 }
13349 #endif /* defined(HAVE_PRI) */
13350 }
13351 if (tmp && !here) {
13352 /* Add the new channel interface to the sorted channel interface list. */
13353 dahdi_iflist_insert(tmp);
13354 }
13355 return tmp;
13356 }
13357
13358 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13359 {
13360 #if defined(HAVE_PRI)
13361 if (0 < span) {
13362 /* The channel must be on the specified PRI span. */
13363 if (!p->pri || p->pri->span != span) {
13364 return 0;
13365 }
13366 if (!groupmatch && channelmatch == -1) {
13367 /* Match any group since it only needs to be on the PRI span. */
13368 *groupmatched = 1;
13369 return 1;
13370 }
13371 }
13372 #endif /* defined(HAVE_PRI) */
13373 /* check group matching */
13374 if (groupmatch) {
13375 if ((p->group & groupmatch) != groupmatch)
13376 /* Doesn't match the specified group, try the next one */
13377 return 0;
13378 *groupmatched = 1;
13379 }
13380 /* Check to see if we have a channel match */
13381 if (channelmatch != -1) {
13382 if (p->channel != channelmatch)
13383 /* Doesn't match the specified channel, try the next one */
13384 return 0;
13385 *channelmatched = 1;
13386 }
13387
13388 return 1;
13389 }
13390
13391 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13392 {
13393 struct dahdi_pvt *p = *pvt;
13394
13395 if (p->inalarm)
13396 return 0;
13397
13398 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode))
13399 return analog_available(p->sig_pvt);
13400
13401 switch (p->sig) {
13402 #if defined(HAVE_PRI)
13403 case SIG_PRI_LIB_HANDLE_CASES:
13404 {
13405 struct sig_pri_chan *pvt_chan;
13406 int res;
13407
13408 pvt_chan = p->sig_pvt;
13409 res = sig_pri_available(&pvt_chan, is_specific_channel);
13410 *pvt = pvt_chan->chan_pvt;
13411 return res;
13412 }
13413 #endif /* defined(HAVE_PRI) */
13414 #if defined(HAVE_SS7)
13415 case SIG_SS7:
13416 return sig_ss7_available(p->sig_pvt);
13417 #endif /* defined(HAVE_SS7) */
13418 default:
13419 break;
13420 }
13421
13422 if (p->locallyblocked || p->remotelyblocked) {
13423 return 0;
13424 }
13425
13426 /* If no owner definitely available */
13427 if (!p->owner) {
13428 #ifdef HAVE_OPENR2
13429 /* Trust MFC/R2 */
13430 if (p->mfcr2) {
13431 if (p->mfcr2call) {
13432 return 0;
13433 } else {
13434 return 1;
13435 }
13436 }
13437 #endif
13438 return 1;
13439 }
13440
13441 return 0;
13442 }
13443
13444 #if defined(HAVE_PRI)
13445 #if defined(HAVE_PRI_CALL_WAITING)
13446 /*!
13447 * \internal
13448 * \brief Init the private channel configuration using the span controller.
13449 * \since 1.8
13450 *
13451 * \param priv Channel to init the configuration.
13452 * \param pri sig_pri PRI control structure.
13453 *
13454 * \note Assumes the pri->lock is already obtained.
13455 */
13456 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13457 {
13458 struct dahdi_pvt *pvt = priv;
13459
13460 pvt->stripmsd = pri->ch_cfg.stripmsd;
13461 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13462 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13463 pvt->immediate = pri->ch_cfg.immediate;
13464 pvt->priexclusive = pri->ch_cfg.priexclusive;
13465 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13466 pvt->use_callerid = pri->ch_cfg.use_callerid;
13467 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13468 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13469 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13470 }
13471 #endif /* defined(HAVE_PRI_CALL_WAITING) */
13472 #endif /* defined(HAVE_PRI) */
13473
13474 #if defined(HAVE_PRI)
13475 /*!
13476 * \internal
13477 * \brief Create a no B channel interface.
13478 * \since 1.8
13479 *
13480 * \param pri sig_pri span controller to add interface.
13481 *
13482 * \note Assumes the pri->lock is already obtained.
13483 *
13484 * \retval array-index into private pointer array on success.
13485 * \retval -1 on error.
13486 */
13487 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13488 {
13489 int pvt_idx;
13490 int res;
13491 unsigned idx;
13492 struct dahdi_pvt *pvt;
13493 struct sig_pri_chan *chan;
13494 struct dahdi_bufferinfo bi;
13495
13496 static int nobch_channel = CHAN_PSEUDO;
13497
13498 /* Find spot in the private pointer array for new interface. */
13499 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13500 if (!pri->pvts[pvt_idx]) {
13501 break;
13502 }
13503 }
13504 if (pri->numchans == pvt_idx) {
13505 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13506 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13507 return -1;
13508 }
13509
13510 /* Add new spot to the private pointer array. */
13511 pri->pvts[pvt_idx] = NULL;
13512 ++pri->numchans;
13513 }
13514
13515 pvt = ast_calloc(1, sizeof(*pvt));
13516 if (!pvt) {
13517 return -1;
13518 }
13519 pvt->cc_params = ast_cc_config_params_init();
13520 if (!pvt->cc_params) {
13521 ast_free(pvt);
13522 return -1;
13523 }
13524 ast_mutex_init(&pvt->lock);
13525 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13526 pvt->subs[idx].dfd = -1;
13527 }
13528 pvt->buf_no = dahdi_pseudo_parms.buf_no;
13529 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13530 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13531 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13532
13533 chan = sig_pri_chan_new(pvt, pri, 0, 0, 0);
13534 if (!chan) {
13535 destroy_dahdi_pvt(pvt);
13536 return -1;
13537 }
13538 chan->no_b_channel = 1;
13539
13540 /*
13541 * Pseudo channel companding law.
13542 * Needed for outgoing call waiting calls.
13543 * XXX May need to make this determined by switchtype or user option.
13544 */
13545 pvt->law_default = DAHDI_LAW_ALAW;
13546
13547 pvt->sig = pri->sig;
13548 pvt->outsigmod = -1;
13549 pvt->pri = pri;
13550 pvt->sig_pvt = chan;
13551 pri->pvts[pvt_idx] = chan;
13552
13553 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13554 if (pvt->subs[SUB_REAL].dfd < 0) {
13555 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13556 strerror(errno));
13557 destroy_dahdi_pvt(pvt);
13558 return -1;
13559 }
13560 memset(&bi, 0, sizeof(bi));
13561 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13562 if (!res) {
13563 pvt->bufsize = bi.bufsize;
13564 bi.txbufpolicy = pvt->buf_policy;
13565 bi.rxbufpolicy = pvt->buf_policy;
13566 bi.numbufs = pvt->buf_no;
13567 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13568 if (res < 0) {
13569 ast_log(LOG_WARNING,
13570 "Unable to set buffer policy on no B channel interface: %s\n",
13571 strerror(errno));
13572 }
13573 } else
13574 ast_log(LOG_WARNING,
13575 "Unable to check buffer policy on no B channel interface: %s\n",
13576 strerror(errno));
13577
13578 --nobch_channel;
13579 if (CHAN_PSEUDO < nobch_channel) {
13580 nobch_channel = CHAN_PSEUDO - 1;
13581 }
13582 pvt->channel = nobch_channel;
13583 pvt->span = pri->span;
13584 chan->channel = pvt->channel;
13585
13586 dahdi_nobch_insert(pri, pvt);
13587
13588 return pvt_idx;
13589 }
13590 #endif /* defined(HAVE_PRI) */
13591
13592 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
13593 structures; it makes no attempt to safely copy regular channel private
13594 structures that might contain reference-counted object pointers and other
13595 scary bits
13596 */
13597 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13598 {
13599 struct dahdi_pvt *p;
13600 struct dahdi_bufferinfo bi;
13601 int res;
13602
13603 p = ast_malloc(sizeof(*p));
13604 if (!p) {
13605 return NULL;
13606 }
13607 *p = *src;
13608
13609 /* Must deep copy the cc_params. */
13610 p->cc_params = ast_cc_config_params_init();
13611 if (!p->cc_params) {
13612 ast_free(p);
13613 return NULL;
13614 }
13615 ast_cc_copy_config_params(p->cc_params, src->cc_params);
13616
13617 p->which_iflist = DAHDI_IFLIST_NONE;
13618 p->next = NULL;
13619 p->prev = NULL;
13620 ast_mutex_init(&p->lock);
13621 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13622 if (p->subs[SUB_REAL].dfd < 0) {
13623 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13624 destroy_dahdi_pvt(p);
13625 return NULL;
13626 }
13627 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13628 if (!res) {
13629 bi.txbufpolicy = src->buf_policy;
13630 bi.rxbufpolicy = src->buf_policy;
13631 bi.numbufs = src->buf_no;
13632 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13633 if (res < 0) {
13634 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13635 }
13636 } else
13637 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13638 p->destroy = 1;
13639 dahdi_iflist_insert(p);
13640 return p;
13641 }
13642
13643 struct dahdi_starting_point {
13644 /*! Group matching mask. Zero if not specified. */
13645 ast_group_t groupmatch;
13646 /*! DAHDI channel to match with. -1 if not specified. */
13647 int channelmatch;
13648 /*! Round robin saved search location index. (Valid if roundrobin TRUE) */
13649 int rr_starting_point;
13650 /*! ISDN span where channels can be picked (Zero if not specified) */
13651 int span;
13652 /*! Analog channel distinctive ring cadence index. */
13653 int cadence;
13654 /*! Dialing option. c/r/d if present and valid. */
13655 char opt;
13656 /*! TRUE if to search the channel list backwards. */
13657 char backwards;
13658 /*! TRUE if search is done with round robin sequence. */
13659 char roundrobin;
13660 };
13661 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13662 {
13663 char *dest;
13664 char *s;
13665 int x;
13666 int res = 0;
13667 struct dahdi_pvt *p;
13668 char *subdir = NULL;
13669 AST_DECLARE_APP_ARGS(args,
13670 AST_APP_ARG(group); /* channel/group token */
13671 //AST_APP_ARG(ext); /* extension token */
13672 //AST_APP_ARG(opts); /* options token */
13673 AST_APP_ARG(other); /* Any remining unused arguments */
13674 );
13675
13676 /*
13677 * data is ---v
13678 * Dial(DAHDI/pseudo[/extension[/options]])
13679 * Dial(DAHDI/<channel#>[c|r<cadence#>|d][/extension[/options]])
13680 * Dial(DAHDI/<subdir>!<channel#>[c|r<cadence#>|d][/extension[/options]])
13681 * Dial(DAHDI/i<span>[/extension[/options]])
13682 * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadence#>|d][/extension[/options]])
13683 *
13684 * i - ISDN span channel restriction.
13685 * Used by CC to ensure that the CC recall goes out the same span.
13686 * Also to make ISDN channel names dialable when the sequence number
13687 * is stripped off. (Used by DTMF attended transfer feature.)
13688 *
13689 * g - channel group allocation search forward
13690 * G - channel group allocation search backward
13691 * r - channel group allocation round robin search forward
13692 * R - channel group allocation round robin search backward
13693 *
13694 * c - Wait for DTMF digit to confirm answer
13695 * r<cadence#> - Set distinctive ring cadence number
13696 * d - Force bearer capability for ISDN/SS7 call to digital.
13697 */
13698
13699 if (data) {
13700 dest = ast_strdupa(data);
13701 } else {
13702 ast_log(LOG_WARNING, "Channel requested with no data\n");
13703 return NULL;
13704 }
13705 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13706 if (!args.argc || ast_strlen_zero(args.group)) {
13707 ast_log(LOG_WARNING, "No channel/group specified\n");
13708 return NULL;
13709 }
13710
13711 /* Initialize the output parameters */
13712 memset(param, 0, sizeof(*param));
13713 param->channelmatch = -1;
13714
13715 if (strchr(args.group, '!') != NULL) {
13716 char *prev = args.group;
13717 while ((s = strchr(prev, '!')) != NULL) {
13718 *s++ = '/';
13719 prev = s;
13720 }
13721 *(prev - 1) = '\0';
13722 subdir = args.group;
13723 args.group = prev;
13724 } else if (args.group[0] == 'i') {
13725 /* Extract the ISDN span channel restriction specifier. */
13726 res = sscanf(args.group + 1, "%30d", &x);
13727 if (res < 1) {
13728 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13729 return NULL;
13730 }
13731 param->span = x;
13732
13733 /* Remove the ISDN span channel restriction specifier. */
13734 s = strchr(args.group, '-');
13735 if (!s) {
13736 /* Search all groups since we are ISDN span restricted. */
13737 return iflist;
13738 }
13739 args.group = s + 1;
13740 res = 0;
13741 }
13742 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13743 /* Retrieve the group number */
13744 s = args.group + 1;
13745 res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadence);
13746 if (res < 1) {
13747 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13748 return NULL;
13749 }
13750 param->groupmatch = ((ast_group_t) 1 << x);
13751
13752 if (toupper(args.group[0]) == 'G') {
13753 if (args.group[0] == 'G') {
13754 param->backwards = 1;
13755 p = ifend;
13756 } else
13757 p = iflist;
13758 } else {
13759 if (ARRAY_LEN(round_robin) <= x) {
13760 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13761 x, data);
13762 return NULL;
13763 }
13764 if (args.group[0] == 'R') {
13765 param->backwards = 1;
13766 p = round_robin[x] ? round_robin[x]->prev : ifend;
13767 if (!p)
13768 p = ifend;
13769 } else {
13770 p = round_robin[x] ? round_robin[x]->next : iflist;
13771 if (!p)
13772 p = iflist;
13773 }
13774 param->roundrobin = 1;
13775 param->rr_starting_point = x;
13776 }
13777 } else {
13778 s = args.group;
13779 if (!strcasecmp(s, "pseudo")) {
13780 /* Special case for pseudo */
13781 x = CHAN_PSEUDO;
13782 param->channelmatch = x;
13783 } else {
13784 res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadence);
13785 if (res < 1) {
13786 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13787 return NULL;
13788 } else {
13789 param->channelmatch = x;
13790 }
13791 }
13792 if (subdir) {
13793 char path[PATH_MAX];
13794 struct stat stbuf;
13795
13796 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13797 subdir, param->channelmatch);
13798 if (stat(path, &stbuf) < 0) {
13799 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13800 path, strerror(errno));
13801 return NULL;
13802 }
13803 if (!S_ISCHR(stbuf.st_mode)) {
13804 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13805 path);
13806 return NULL;
13807 }
13808 param->channelmatch = minor(stbuf.st_rdev);
13809 }
13810
13811 p = iflist;
13812 }
13813
13814 if (param->opt == 'r' && res < 3) {
13815 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13816 param->opt = '\0';
13817 }
13818
13819 return p;
13820 }
13821
13822 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap,
13823 const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor,
13824 const char *data, int *cause)
13825 {
13826 int callwait = 0;
13827 struct dahdi_pvt *p;
13828 struct ast_channel *tmp = NULL;
13829 struct dahdi_pvt *exitpvt;
13830 int channelmatched = 0;
13831 int foundowner = 0;
13832 int groupmatched = 0;
13833 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13834 int transcapdigital = 0;
13835 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13836 struct dahdi_starting_point start;
13837 ast_callid callid = 0;
13838 int callid_created = ast_callid_threadstorage_auto(&callid);
13839
13840 ast_mutex_lock(&iflock);
13841 p = determine_starting_point(data, &start);
13842 if (!p) {
13843 /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13844 ast_mutex_unlock(&iflock);
13845 ast_callid_threadstorage_auto_clean(callid, callid_created);
13846 return NULL;
13847 }
13848
13849 /* Search for an unowned channel */
13850 exitpvt = p;
13851 while (p && !tmp) {
13852 if (start.roundrobin)
13853 round_robin[start.rr_starting_point] = p;
13854
13855 if (p->owner) {
13856 foundowner++;
13857 }
13858
13859 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13860 && available(&p, channelmatched)) {
13861 ast_debug(1, "Using channel %d\n", p->channel);
13862
13863 callwait = (p->owner != NULL);
13864 #ifdef HAVE_OPENR2
13865 if (p->mfcr2) {
13866 ast_mutex_lock(&p->lock);
13867 if (p->mfcr2call) {
13868 ast_mutex_unlock(&p->lock);
13869 ast_debug(1, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13870 goto next;
13871 }
13872 p->mfcr2call = 1;
13873 ast_mutex_unlock(&p->lock);
13874 }
13875 #endif
13876 if (p->channel == CHAN_PSEUDO) {
13877 p = duplicate_pseudo(p);
13878 if (!p) {
13879 break;
13880 }
13881 }
13882
13883 p->distinctivering = 0;
13884 /* Make special notes */
13885 switch (start.opt) {
13886 case '\0':
13887 /* No option present. */
13888 break;
13889 case 'c':
13890 /* Confirm answer */
13891 p->confirmanswer = 1;
13892 break;
13893 case 'r':
13894 /* Distinctive ring */
13895 p->distinctivering = start.cadence;
13896 break;
13897 case 'd':
13898 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13899 /* If this is an ISDN call, make it digital */
13900 transcapdigital = AST_TRANS_CAP_DIGITAL;
13901 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13902 break;
13903 default:
13904 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, data);
13905 break;
13906 }
13907
13908 p->outgoing = 1;
13909 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13910 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13911 #ifdef HAVE_PRI
13912 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13913 /*
13914 * We already have the B channel reserved for this call. We
13915 * just need to make sure that dahdi_hangup() has completed
13916 * cleaning up before continuing.
13917 */
13918 ast_mutex_lock(&p->lock);
13919 ast_mutex_unlock(&p->lock);
13920
13921 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13922 sizeof(p->dnid));
13923 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, assignedids, requestor, transcapdigital);
13924 #endif
13925 #if defined(HAVE_SS7)
13926 } else if (p->sig == SIG_SS7) {
13927 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, assignedids, requestor, transcapdigital);
13928 #endif /* defined(HAVE_SS7) */
13929 } else {
13930 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, assignedids, requestor, callid);
13931 }
13932 if (!tmp) {
13933 p->outgoing = 0;
13934 #if defined(HAVE_PRI)
13935 switch (p->sig) {
13936 case SIG_PRI_LIB_HANDLE_CASES:
13937 #if defined(HAVE_PRI_CALL_WAITING)
13938 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13939 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13940 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13941 }
13942 #endif /* defined(HAVE_PRI_CALL_WAITING) */
13943 /*
13944 * This should be the last thing to clear when we are done with
13945 * the channel.
13946 */
13947 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13948 break;
13949 default:
13950 break;
13951 }
13952 #endif /* defined(HAVE_PRI) */
13953 } else {
13954 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", data);
13955 }
13956 break;
13957 }
13958 #ifdef HAVE_OPENR2
13959 next:
13960 #endif
13961 if (start.backwards) {
13962 p = p->prev;
13963 if (!p)
13964 p = ifend;
13965 } else {
13966 p = p->next;
13967 if (!p)
13968 p = iflist;
13969 }
13970 /* stop when you roll to the one that we started from */
13971 if (p == exitpvt)
13972 break;
13973 }
13974 ast_mutex_unlock(&iflock);
13975 restart_monitor();
13976 if (cause && !tmp) {
13977 if (callwait || (channelmatched && foundowner)) {
13978 *cause = AST_CAUSE_BUSY;
13979 } else if (groupmatched) {
13980 *cause = AST_CAUSE_CONGESTION;
13981 } else {
13982 /*
13983 * We did not match any channel requested.
13984 * Dialplan error requesting non-existant channel?
13985 */
13986 }
13987 }
13988
13989 ast_callid_threadstorage_auto_clean(callid, callid_created);
13990 return tmp;
13991 }
13992
13993 /*!
13994 * \internal
13995 * \brief Determine the device state for a given DAHDI device if we can.
13996 * \since 1.8
13997 *
13998 * \param data DAHDI device name after "DAHDI/".
13999 *
14000 * \retval device_state enum ast_device_state value.
14001 * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
14002 */
14003 static int dahdi_devicestate(const char *data)
14004 {
14005 #if defined(HAVE_PRI)
14006 const char *device;
14007 unsigned span;
14008 int res;
14009
14010 device = data;
14011
14012 if (*device != 'I') {
14013 /* The request is not for an ISDN span device. */
14014 return AST_DEVICE_UNKNOWN;
14015 }
14016 res = sscanf(device, "I%30u", &span);
14017 if (res != 1 || !span || NUM_SPANS < span) {
14018 /* Bad format for ISDN span device name. */
14019 return AST_DEVICE_UNKNOWN;
14020 }
14021 device = strchr(device, '/');
14022 if (!device) {
14023 /* Bad format for ISDN span device name. */
14024 return AST_DEVICE_UNKNOWN;
14025 }
14026
14027 /*
14028 * Since there are currently no other span devstate's defined,
14029 * it must be congestion.
14030 */
14031 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14032 ++device;
14033 if (!strcmp(device, "congestion"))
14034 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
14035 {
14036 return pris[span - 1].pri.congestion_devstate;
14037 }
14038 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14039 else if (!strcmp(device, "threshold")) {
14040 return pris[span - 1].pri.threshold_devstate;
14041 }
14042 return AST_DEVICE_UNKNOWN;
14043 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
14044 #else
14045 return AST_DEVICE_UNKNOWN;
14046 #endif /* defined(HAVE_PRI) */
14047 }
14048
14049 /*!
14050 * \brief Callback made when dial failed to get a channel out of dahdi_request().
14051 * \since 1.8
14052 *
14053 * \param inbound Incoming asterisk channel.
14054 * \param dest Same dial string passed to dahdi_request().
14055 * \param callback Callback into CC core to announce a busy channel available for CC.
14056 *
14057 * \details
14058 * This callback acts like a forked dial with all prongs of the fork busy.
14059 * Essentially, for each channel that could have taken the call, indicate that
14060 * it is busy.
14061 *
14062 * \retval 0 on success.
14063 * \retval -1 on error.
14064 */
14065 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
14066 {
14067 struct dahdi_pvt *p;
14068 struct dahdi_pvt *exitpvt;
14069 struct dahdi_starting_point start;
14070 int groupmatched = 0;
14071 int channelmatched = 0;
14072
14073 ast_mutex_lock(&iflock);
14074 p = determine_starting_point(dest, &start);
14075 if (!p) {
14076 ast_mutex_unlock(&iflock);
14077 return -1;
14078 }
14079 exitpvt = p;
14080 for (;;) {
14081 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
14082 /* We found a potential match. call the callback */
14083 struct ast_str *device_name;
14084 char *dash;
14085 const char *monitor_type;
14086 char dialstring[AST_CHANNEL_NAME];
14087 char full_device_name[AST_CHANNEL_NAME];
14088
14089 switch (ast_get_cc_monitor_policy(p->cc_params)) {
14090 case AST_CC_MONITOR_NEVER:
14091 break;
14092 case AST_CC_MONITOR_NATIVE:
14093 case AST_CC_MONITOR_ALWAYS:
14094 case AST_CC_MONITOR_GENERIC:
14095 #if defined(HAVE_PRI)
14096 if (dahdi_sig_pri_lib_handles(p->sig)) {
14097 /*
14098 * ISDN is in a trunk busy condition so we need to monitor
14099 * the span congestion device state.
14100 */
14101 snprintf(full_device_name, sizeof(full_device_name),
14102 "DAHDI/I%d/congestion", p->pri->span);
14103 } else
14104 #endif /* defined(HAVE_PRI) */
14105 {
14106 #if defined(HAVE_PRI)
14107 device_name = create_channel_name(p, 1, "");
14108 #else
14109 device_name = create_channel_name(p);
14110 #endif /* defined(HAVE_PRI) */
14111 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
14112 device_name ? ast_str_buffer(device_name) : "");
14113 ast_free(device_name);
14114 /*
14115 * The portion after the '-' in the channel name is either a random
14116 * number, a sequence number, or a subchannel number. None are
14117 * necessary so strip them off.
14118 */
14119 dash = strrchr(full_device_name, '-');
14120 if (dash) {
14121 *dash = '\0';
14122 }
14123 }
14124 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
14125
14126 /*
14127 * Analog can only do generic monitoring.
14128 * ISDN is in a trunk busy condition and any "device" is going
14129 * to be busy until a B channel becomes available. The generic
14130 * monitor can do this task.
14131 */
14132 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
14133 callback(inbound,
14134 #if defined(HAVE_PRI)
14135 p->pri ? p->pri->cc_params : p->cc_params,
14136 #else
14137 p->cc_params,
14138 #endif /* defined(HAVE_PRI) */
14139 monitor_type, full_device_name, dialstring, NULL);
14140 break;
14141 }
14142 }
14143 p = start.backwards ? p->prev : p->next;
14144 if (!p) {
14145 p = start.backwards ? ifend : iflist;
14146 }
14147 if (p == exitpvt) {
14148 break;
14149 }
14150 }
14151 ast_mutex_unlock(&iflock);
14152 return 0;
14153 }
14154
14155 #if defined(HAVE_SS7)
14156 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
14157 {
14158 int i;
14159
14160 if (ss7) {
14161 for (i = 0; i < NUM_SPANS; i++) {
14162 if (linksets[i].ss7.ss7 == ss7) {
14163 ast_verbose_callid(0, "[%d] %s", i + 1, s);
14164 return;
14165 }
14166 }
14167 }
14168 ast_verbose_callid(0, "%s", s);
14169 }
14170 #endif /* defined(HAVE_SS7) */
14171
14172 #if defined(HAVE_SS7)
14173 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
14174 {
14175 int i;
14176
14177 if (ss7) {
14178 for (i = 0; i < NUM_SPANS; i++) {
14179 if (linksets[i].ss7.ss7 == ss7) {
14180 ast_log_callid(LOG_ERROR, 0, "[%d] %s", i + 1, s);
14181 return;
14182 }
14183 }
14184 }
14185 ast_log_callid(LOG_ERROR, 0, "%s", s);
14186 }
14187 #endif /* defined(HAVE_SS7) */
14188
14189 #if defined(HAVE_OPENR2)
14190 static void *mfcr2_monitor(void *data)
14191 {
14192 struct dahdi_mfcr2 *mfcr2 = data;
14193 struct dahdi_pvt *pvt;
14194
14195 /* we should be using pthread_key_create
14196 and allocate pollers dynamically.
14197 I think do_monitor() could be leaking, since it
14198 could be cancelled at any time and is not
14199 using thread keys, why?, */
14200 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14201 int res = 0;
14202 int i = 0;
14203 int oldstate = 0;
14204 int quit_loop = 0;
14205 int maxsleep = 20;
14206 int was_idle = 0;
14207 int pollsize = 0;
14208 /* now that we're ready to get calls, unblock our side and
14209 get current line state */
14210 for (i = 0; i < mfcr2->numchans; i++) {
14211 pvt = mfcr2->pvts[i];
14212 if (!pvt) {
14213 continue;
14214 }
14215 openr2_chan_set_idle(pvt->r2chan);
14216 openr2_chan_handle_cas(pvt->r2chan);
14217 }
14218 while (1) {
14219 /* we trust here that the mfcr2 channel list will not ever change once
14220 the module is loaded */
14221 pollsize = 0;
14222 for (i = 0; i < mfcr2->numchans; i++) {
14223 pollers[i].revents = 0;
14224 pollers[i].events = 0;
14225 pvt = mfcr2->pvts[i];
14226 if (!pvt) {
14227 continue;
14228 }
14229 if (pvt->owner) {
14230 continue;
14231 }
14232 if (mfcr2->nodev) {
14233 continue;
14234 }
14235 if (!pvt->r2chan) {
14236 ast_debug(1, "Wow, no r2chan on channel %d\n", pvt->channel);
14237 quit_loop = 1;
14238 break;
14239 }
14240 openr2_chan_enable_read(pvt->r2chan);
14241 pollers[i].events = POLLIN | POLLPRI;
14242 pollers[i].fd = pvt->subs[SUB_REAL].dfd;
14243 pollsize++;
14244 }
14245 if (quit_loop) {
14246 break;
14247 }
14248 if (pollsize == 0) {
14249 if (!was_idle) {
14250 ast_debug(1, "Monitor thread going idle since everybody has an owner\n");
14251 was_idle = 1;
14252 }
14253 poll(NULL, 0, maxsleep);
14254 continue;
14255 }
14256 was_idle = 0;
14257 /* probably poll() is a valid cancel point, lets just be on the safe side
14258 by calling pthread_testcancel */
14259 pthread_testcancel();
14260 res = poll(pollers, mfcr2->numchans, maxsleep);
14261 pthread_testcancel();
14262 if ((res < 0) && (errno != EINTR)) {
14263 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14264 break;
14265 }
14266 /* do we want to allow to cancel while processing events? */
14267 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14268 for (i = 0; i < mfcr2->numchans; i++) {
14269 pvt = mfcr2->pvts[i];
14270 if (!pvt) {
14271 continue;
14272 }
14273 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14274 openr2_chan_process_event(pvt->r2chan);
14275 }
14276 }
14277 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14278 }
14279 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14280 return 0;
14281 }
14282 #endif /* HAVE_OPENR2 */
14283
14284 #if defined(HAVE_PRI)
14285 static void dahdi_pri_message(struct pri *pri, char *s)
14286 {
14287 int x;
14288 int y;
14289 int dchan = -1;
14290 int span = -1;
14291 int dchancount = 0;
14292
14293 if (pri) {
14294 for (x = 0; x < NUM_SPANS; x++) {
14295 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14296 if (pris[x].pri.dchans[y]) {
14297 dchancount++;
14298 }
14299
14300 if (pris[x].pri.dchans[y] == pri) {
14301 dchan = y;
14302 }
14303 }
14304 if (dchan >= 0) {
14305 span = x;
14306 break;
14307 }
14308 dchancount = 0;
14309 }
14310 if (-1 < span) {
14311 if (1 < dchancount) {
14312 ast_verbose_callid(0, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14313 } else {
14314 ast_verbose_callid(0, "PRI Span: %d %s", span + 1, s);
14315 }
14316 } else {
14317 ast_verbose_callid(0, "PRI Span: ? %s", s);
14318 }
14319 } else {
14320 ast_verbose_callid(0, "PRI Span: ? %s", s);
14321 }
14322
14323 ast_mutex_lock(&pridebugfdlock);
14324
14325 if (pridebugfd >= 0) {
14326 if (write(pridebugfd, s, strlen(s)) < 0) {
14327 ast_log_callid(LOG_WARNING, 0, "write() failed: %s\n", strerror(errno));
14328 }
14329 }
14330
14331 ast_mutex_unlock(&pridebugfdlock);
14332 }
14333 #endif /* defined(HAVE_PRI) */
14334
14335 #if defined(HAVE_PRI)
14336 static void dahdi_pri_error(struct pri *pri, char *s)
14337 {
14338 int x;
14339 int y;
14340 int dchan = -1;
14341 int span = -1;
14342 int dchancount = 0;
14343
14344 if (pri) {
14345 for (x = 0; x < NUM_SPANS; x++) {
14346 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14347 if (pris[x].pri.dchans[y]) {
14348 dchancount++;
14349 }
14350
14351 if (pris[x].pri.dchans[y] == pri) {
14352 dchan = y;
14353 }
14354 }
14355 if (dchan >= 0) {
14356 span = x;
14357 break;
14358 }
14359 dchancount = 0;
14360 }
14361 if (-1 < span) {
14362 if (1 < dchancount) {
14363 ast_log_callid(LOG_ERROR, 0, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14364 } else {
14365 ast_log_callid(LOG_ERROR, 0, "PRI Span: %d %s", span + 1, s);
14366 }
14367 } else {
14368 ast_log_callid(LOG_ERROR, 0, "PRI Span: ? %s", s);
14369 }
14370 } else {
14371 ast_log_callid(LOG_ERROR, 0, "PRI Span: ? %s", s);
14372 }
14373
14374 ast_mutex_lock(&pridebugfdlock);
14375
14376 if (pridebugfd >= 0) {
14377 if (write(pridebugfd, s, strlen(s)) < 0) {
14378 ast_log_callid(LOG_WARNING, 0, "write() failed: %s\n", strerror(errno));
14379 }
14380 }
14381
14382 ast_mutex_unlock(&pridebugfdlock);
14383 }
14384 #endif /* defined(HAVE_PRI) */
14385
14386 #if defined(HAVE_PRI)
14387 static int prepare_pri(struct dahdi_pri *pri)
14388 {
14389 int i, res, x;
14390 struct dahdi_params p;
14391 struct dahdi_bufferinfo bi;
14392 struct dahdi_spaninfo si;
14393
14394 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14395 if (!pri->dchannels[i])
14396 break;
14397 if (pri->pri.fds[i] >= 0) {
14398 /* A partial range addition. Not a complete setup. */
14399 break;
14400 }
14401 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14402 if ((pri->pri.fds[i] < 0)) {
14403 ast_log(LOG_ERROR, "Unable to open D-channel (fd=%d) (%s)\n",
14404 pri->pri.fds[i], strerror(errno));
14405 return -1;
14406 }
14407 x = pri->dchannels[i];
14408 res = ioctl(pri->pri.fds[i], DAHDI_SPECIFY, &x);
14409 if (res) {
14410 dahdi_close_pri_fd(pri, i);
14411 ast_log(LOG_ERROR, "Unable to SPECIFY channel %d (%s)\n", x, strerror(errno));
14412 return -1;
14413 }
14414 memset(&p, 0, sizeof(p));
14415 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14416 if (res) {
14417 dahdi_close_pri_fd(pri, i);
14418 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14419 return -1;
14420 }
14421 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14422 dahdi_close_pri_fd(pri, i);
14423 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14424 return -1;
14425 }
14426 memset(&si, 0, sizeof(si));
14427 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14428 if (res) {
14429 dahdi_close_pri_fd(pri, i);
14430 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14431 }
14432 if (!si.alarms) {
14433 pri_event_noalarm(&pri->pri, i, 1);
14434 } else {
14435 pri_event_alarm(&pri->pri, i, 1);
14436 }
14437 memset(&bi, 0, sizeof(bi));
14438 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14439 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14440 bi.numbufs = 32;
14441 bi.bufsize = 1024;
14442 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14443 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14444 dahdi_close_pri_fd(pri, i);
14445 return -1;
14446 }
14447 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14448 }
14449 return 0;
14450 }
14451 #endif /* defined(HAVE_PRI) */
14452
14453 #if defined(HAVE_PRI)
14454 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14455 {
14456 int which, span;
14457 char *ret = NULL;
14458
14459 if (pos != rpos)
14460 return ret;
14461
14462 for (which = span = 0; span < NUM_SPANS; span++) {
14463 if (pris[span].pri.pri && ++which > state) {
14464 if (ast_asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
14465 ret = NULL;
14466 }
14467 break;
14468 }
14469 }
14470 return ret;
14471 }
14472 #endif /* defined(HAVE_PRI) */
14473
14474 #if defined(HAVE_PRI)
14475 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14476 {
14477 return complete_span_helper(line,word,pos,state,3);
14478 }
14479 #endif /* defined(HAVE_PRI) */
14480
14481 #if defined(HAVE_PRI)
14482 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14483 {
14484 int myfd;
14485 switch (cmd) {
14486 case CLI_INIT:
14487 e->command = "pri set debug file";
14488 e->usage = "Usage: pri set debug file [output-file]\n"
14489 " Sends PRI debug output to the specified output file\n";
14490 return NULL;
14491 case CLI_GENERATE:
14492 return NULL;
14493 }
14494 if (a->argc < 5)
14495 return CLI_SHOWUSAGE;
14496
14497 if (ast_strlen_zero(a->argv[4]))
14498 return CLI_SHOWUSAGE;
14499
14500 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14501 if (myfd < 0) {
14502 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14503 return CLI_SUCCESS;
14504 }
14505
14506 ast_mutex_lock(&pridebugfdlock);
14507
14508 if (pridebugfd >= 0)
14509 close(pridebugfd);
14510
14511 pridebugfd = myfd;
14512 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14513 ast_mutex_unlock(&pridebugfdlock);
14514 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14515 return CLI_SUCCESS;
14516 }
14517 #endif /* defined(HAVE_PRI) */
14518
14519 #if defined(HAVE_PRI)
14520 static int action_pri_debug_file_set(struct mansession *s, const struct message *m)
14521 {
14522 const char *output_file = astman_get_header(m, "File");
14523 int myfd;
14524
14525 if (ast_strlen_zero(output_file)) {
14526 astman_send_error(s, m, "Action must define a 'File'");
14527 }
14528
14529 myfd = open(output_file, O_CREAT|O_WRONLY, AST_FILE_MODE);
14530 if (myfd < 0) {
14531 astman_send_error(s, m, "Unable to open requested file for writing");
14532 return 0;
14533 }
14534
14535 ast_mutex_lock(&pridebugfdlock);
14536
14537 if (pridebugfd >= 0) {
14538 close(pridebugfd);
14539 }
14540
14541 pridebugfd = myfd;
14542 ast_copy_string(pridebugfilename, output_file, sizeof(pridebugfilename));
14543 ast_mutex_unlock(&pridebugfdlock);
14544 astman_send_ack(s, m, "PRI debug output will now be sent to requested file.");
14545
14546 return 0;
14547 }
14548 #endif /* defined(HAVE_PRI) */
14549
14550 #if defined(HAVE_PRI)
14551 static int action_pri_debug_file_unset(struct mansession *s, const struct message *m)
14552 {
14553 ast_mutex_lock(&pridebugfdlock);
14554
14555 if (pridebugfd >= 0) {
14556 close(pridebugfd);
14557 }
14558
14559 pridebugfd = -1;
14560
14561 ast_mutex_unlock(&pridebugfdlock);
14562
14563 astman_send_ack(s, m, "PRI Debug output to file disabled");
14564 return 0;
14565 }
14566 #endif /* defined(HAVE_PRI) */
14567
14568 #if defined(HAVE_PRI)
14569 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14570 {
14571 int span;
14572 int x;
14573 int debugmask = 0;
14574 int level = 0;
14575 switch (cmd) {
14576 case CLI_INIT:
14577 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";
14578 e->usage =
14579 "Usage: pri set debug {<level>|on|off|hex|intense} span <span>\n"
14580 " Enables debugging on a given PRI span\n"
14581 " Level is a bitmap of the following values:\n"
14582 " 1 General debugging incl. state changes\n"
14583 " 2 Decoded Q.931 messages\n"
14584 " 4 Decoded Q.921 messages\n"
14585 " 8 Raw hex dumps of Q.921 frames\n"
14586 " on - equivalent to 3\n"
14587 " hex - equivalent to 8\n"
14588 " intense - equivalent to 15\n";
14589 return NULL;
14590 case CLI_GENERATE:
14591 return complete_span_4(a->line, a->word, a->pos, a->n);
14592 }
14593 if (a->argc < 6) {
14594 return CLI_SHOWUSAGE;
14595 }
14596
14597 if (!strcasecmp(a->argv[3], "on")) {
14598 level = 3;
14599 } else if (!strcasecmp(a->argv[3], "off")) {
14600 level = 0;
14601 } else if (!strcasecmp(a->argv[3], "intense")) {
14602 level = 15;
14603 } else if (!strcasecmp(a->argv[3], "hex")) {
14604 level = 8;
14605 } else {
14606 level = atoi(a->argv[3]);
14607 }
14608 span = atoi(a->argv[5]);
14609 if ((span < 1) || (span > NUM_SPANS)) {
14610 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14611 return CLI_SUCCESS;
14612 }
14613 if (!pris[span-1].pri.pri) {
14614 ast_cli(a->fd, "No PRI running on span %d\n", span);
14615 return CLI_SUCCESS;
14616 }
14617
14618 if (level & 1) debugmask |= SIG_PRI_DEBUG_NORMAL;
14619 if (level & 2) debugmask |= PRI_DEBUG_Q931_DUMP;
14620 if (level & 4) debugmask |= PRI_DEBUG_Q921_DUMP;
14621 if (level & 8) debugmask |= PRI_DEBUG_Q921_RAW;
14622
14623 /* Set debug level in libpri */
14624 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14625 if (pris[span - 1].pri.dchans[x]) {
14626 pri_set_debug(pris[span - 1].pri.dchans[x], debugmask);
14627 }
14628 }
14629 if (level == 0) {
14630 /* Close the debugging file if it's set */
14631 ast_mutex_lock(&pridebugfdlock);
14632 if (0 <= pridebugfd) {
14633 close(pridebugfd);
14634 pridebugfd = -1;
14635 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14636 pridebugfilename);
14637 }
14638 ast_mutex_unlock(&pridebugfdlock);
14639 }
14640 pris[span - 1].pri.debug = (level) ? 1 : 0;
14641 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14642 return CLI_SUCCESS;
14643 }
14644 #endif /* defined(HAVE_PRI) */
14645
14646 #if defined(HAVE_PRI)
14647 static int action_pri_debug_set(struct mansession *s, const struct message *m)
14648 {
14649 const char *level = astman_get_header(m, "Level");
14650 const char *span = astman_get_header(m, "Span");
14651 int level_val;
14652 int span_val;
14653 int x;
14654 int debugmask = 0;
14655
14656 if (ast_strlen_zero(level)) {
14657 astman_send_error(s, m, "'Level' was not specified");
14658 return 0;
14659 }
14660
14661 if (ast_strlen_zero(span)) {
14662 astman_send_error(s, m, "'Span' was not specified");
14663 return 0;
14664 }
14665
14666 if (!strcasecmp(level, "on")) {
14667 level_val = 3;
14668 } else if (!strcasecmp(level, "off")) {
14669 level_val = 0;
14670 } else if (!strcasecmp(level, "intense")) {
14671 level_val = 15;
14672 } else if (!strcasecmp(level, "hex")) {
14673 level_val = 8;
14674 } else {
14675 if (sscanf(level, "%30d", &level_val) != 1) {
14676 astman_send_error(s, m, "Invalid value for 'Level'");
14677 return 0;
14678 }
14679 }
14680
14681 if (sscanf(span, "%30d", &span_val) != 1) {
14682 astman_send_error(s, m, "Invalid value for 'Span'");
14683 }
14684
14685 if ((span_val < 1) || (span_val > NUM_SPANS)) {
14686 const char *id = astman_get_header(m, "ActionID");
14687 char id_text[256] = "";
14688
14689 if (!ast_strlen_zero(id)) {
14690 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
14691 }
14692
14693 astman_append(s, "Response: Error\r\n"
14694 "%s" /* id_text */
14695 "Message: Invalid span '%s' - Should be a number from 1 to %d\r\n"
14696 "\r\n",
14697 id_text,
14698 span, NUM_SPANS);
14699
14700 return 0;
14701 }
14702
14703 if (!pris[span_val-1].pri.pri) {
14704 astman_send_error(s, m, "No PRI running on requested span");
14705 return 0;
14706 }
14707
14708 if (level_val & 1) {
14709 debugmask |= SIG_PRI_DEBUG_NORMAL;
14710 }
14711 if (level_val & 2) {
14712 debugmask |= PRI_DEBUG_Q931_DUMP;
14713 }
14714 if (level_val & 4) {
14715 debugmask |= PRI_DEBUG_Q921_DUMP;
14716 }
14717 if (level_val & 8) {
14718 debugmask |= PRI_DEBUG_Q921_RAW;
14719 }
14720
14721 /* Set debug level in libpri */
14722 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14723 if (pris[span_val - 1].pri.dchans[x]) {
14724 pri_set_debug(pris[span_val - 1].pri.dchans[x], debugmask);
14725 }
14726 }
14727
14728 pris[span_val - 1].pri.debug = (level_val) ? 1 : 0;
14729 astman_send_ack(s, m, "Debug level set for requested span");
14730
14731 return 0;
14732 }
14733 #endif /* defined(HAVE_PRI) */
14734
14735 #if defined(HAVE_PRI)
14736 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14737 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14738 {
14739 unsigned *why;
14740 int channel;
14741 int trunkgroup;
14742 int x, y, fd = a->fd;
14743 int interfaceid = 0;
14744 char db_chan_name[20], db_answer[15];
14745 struct dahdi_pvt *tmp;
14746 struct dahdi_pri *pri;
14747
14748 if (a->argc < 5 || a->argc > 6)
14749 return CLI_SHOWUSAGE;
14750 if (strchr(a->argv[4], ':')) {
14751 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14752 return CLI_SHOWUSAGE;
14753 if ((trunkgroup < 1) || (channel < 1))
14754 return CLI_SHOWUSAGE;
14755 pri = NULL;
14756 for (x=0;x<NUM_SPANS;x++) {
14757 if (pris[x].pri.trunkgroup == trunkgroup) {
14758 pri = pris + x;
14759 break;
14760 }
14761 }
14762 if (!pri) {
14763 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14764 return CLI_FAILURE;
14765 }
14766 } else
14767 channel = atoi(a->argv[4]);
14768
14769 if (a->argc == 6)
14770 interfaceid = atoi(a->argv[5]);
14771
14772 /* either servicing a D-Channel */
14773 for (x = 0; x < NUM_SPANS; x++) {
14774 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14775 if (pris[x].dchannels[y] == channel) {
14776 pri = pris + x;
14777 if (pri->pri.enable_service_message_support) {
14778 ast_mutex_lock(&pri->pri.lock);
14779 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14780 ast_mutex_unlock(&pri->pri.lock);
14781 } else {
14782 ast_cli(fd,
14783 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14784 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14785 }
14786 return CLI_SUCCESS;
14787 }
14788 }
14789 }
14790
14791 /* or servicing a B-Channel */
14792 ast_mutex_lock(&iflock);
14793 for (tmp = iflist; tmp; tmp = tmp->next) {
14794 if (tmp->pri && tmp->channel == channel) {
14795 ast_mutex_unlock(&iflock);
14796 ast_mutex_lock(&tmp->pri->lock);
14797 if (!tmp->pri->enable_service_message_support) {
14798 ast_mutex_unlock(&tmp->pri->lock);
14799 ast_cli(fd,
14800 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14801 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14802 return CLI_SUCCESS;
14803 }
14804 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14805 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14806 switch(changestatus) {
14807 case 0: /* enable */
14808 /* Near end wants to be in service now. */
14809 ast_db_del(db_chan_name, SRVST_DBKEY);
14810 *why &= ~SRVST_NEAREND;
14811 if (*why) {
14812 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14813 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14814 } else {
14815 dahdi_pri_update_span_devstate(tmp->pri);
14816 }
14817 break;
14818 /* case 1: -- loop */
14819 case 2: /* disable */
14820 /* Near end wants to be out-of-service now. */
14821 ast_db_del(db_chan_name, SRVST_DBKEY);
14822 *why |= SRVST_NEAREND;
14823 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14824 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14825 dahdi_pri_update_span_devstate(tmp->pri);
14826 break;
14827 /* case 3: -- continuity */
14828 /* case 4: -- shutdown */
14829 default:
14830 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14831 break;
14832 }
14833 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14834 ast_mutex_unlock(&tmp->pri->lock);
14835 return CLI_SUCCESS;
14836 }
14837 }
14838 ast_mutex_unlock(&iflock);
14839
14840 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14841 return CLI_FAILURE;
14842 }
14843
14844 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14845 {
14846 switch (cmd) {
14847 case CLI_INIT:
14848 e->command = "pri service enable channel";
14849 e->usage =
14850 "Usage: pri service enable channel <channel> [<interface id>]\n"
14851 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14852 " to restore a channel to service, with optional interface id\n"
14853 " as agreed upon with remote switch operator\n";
14854 return NULL;
14855 case CLI_GENERATE:
14856 return NULL;
14857 }
14858 return handle_pri_service_generic(e, cmd, a, 0);
14859 }
14860
14861 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14862 {
14863 switch (cmd) {
14864 case CLI_INIT:
14865 e->command = "pri service disable channel";
14866 e->usage =
14867 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14868 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14869 " to remove a channel from service, with optional interface id\n"
14870 " as agreed upon with remote switch operator\n";
14871 return NULL;
14872 case CLI_GENERATE:
14873 return NULL;
14874 }
14875 return handle_pri_service_generic(e, cmd, a, 2);
14876 }
14877 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14878 #endif /* defined(HAVE_PRI) */
14879
14880 #if defined(HAVE_PRI)
14881 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14882 {
14883 int span;
14884
14885 switch (cmd) {
14886 case CLI_INIT:
14887 e->command = "pri show channels";
14888 e->usage =
14889 "Usage: pri show channels\n"
14890 " Displays PRI channel information such as the current mapping\n"
14891 " of DAHDI B channels to Asterisk channel names and which calls\n"
14892 " are on hold or call-waiting. Calls on hold or call-waiting\n"
14893 " are not associated with any B channel.\n";
14894 return NULL;
14895 case CLI_GENERATE:
14896 return NULL;
14897 }
14898
14899 if (a->argc != 3)
14900 return CLI_SHOWUSAGE;
14901
14902 sig_pri_cli_show_channels_header(a->fd);
14903 for (span = 0; span < NUM_SPANS; ++span) {
14904 if (pris[span].pri.pri) {
14905 sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14906 }
14907 }
14908 return CLI_SUCCESS;
14909 }
14910 #endif /* defined(HAVE_PRI) */
14911
14912 #if defined(HAVE_PRI)
14913 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14914 {
14915 int span;
14916
14917 switch (cmd) {
14918 case CLI_INIT:
14919 e->command = "pri show spans";
14920 e->usage =
14921 "Usage: pri show spans\n"
14922 " Displays PRI span information\n";
14923 return NULL;
14924 case CLI_GENERATE:
14925 return NULL;
14926 }
14927
14928 if (a->argc != 3)
14929 return CLI_SHOWUSAGE;
14930
14931 for (span = 0; span < NUM_SPANS; span++) {
14932 if (pris[span].pri.pri) {
14933 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14934 }
14935 }
14936 return CLI_SUCCESS;
14937 }
14938 #endif /* defined(HAVE_PRI) */
14939
14940 #if defined(HAVE_PRI)
14941 #define container_of(ptr, type, member) \
14942 ((type *)((char *)(ptr) - offsetof(type, member)))
14943 /*!
14944 * \internal
14945 * \brief Destroy a D-Channel of a PRI span
14946 * \since 12
14947 *
14948 * \param pri the pri span
14949 *
14950 * Shuts down a span and destroys its D-Channel. Further destruction
14951 * of the B-channels using dahdi_destroy_channel() would probably be required
14952 * for the B-Channels.
14953 */
14954 static void pri_destroy_span(struct sig_pri_span *pri)
14955 {
14956 int i;
14957 int res;
14958 int cancel_code;
14959 struct dahdi_pri* dahdi_pri;
14960 pthread_t master = pri->master;
14961
14962 if (!master || (master == AST_PTHREADT_NULL)) {
14963 return;
14964 }
14965 ast_debug(2, "About to destroy DAHDI channels of span %d.\n", pri->span);
14966 for (i = 0; i < pri->numchans; i++) {
14967 int channel;
14968 struct sig_pri_chan *pvt = pri->pvts[i];
14969
14970 if (!pvt) {
14971 continue;
14972 }
14973 channel = pvt->channel;
14974 ast_debug(2, "About to destroy B-channel %d.\n", channel);
14975 dahdi_destroy_channel_range(channel, channel);
14976 }
14977
14978 cancel_code = pthread_cancel(master);
14979 pthread_kill(master, SIGURG);
14980 ast_debug(4,
14981 "Waiting to join thread of span %d "
14982 "with pid=%p cancel_code=%d\n",
14983 pri->span, (void *)master, cancel_code);
14984 res = pthread_join(master, NULL);
14985 if (res != 0) {
14986 ast_log(LOG_NOTICE, "pthread_join failed: %d\n", res);
14987 }
14988 pri->master = AST_PTHREADT_NULL;
14989
14990 /* The 'struct dahdi_pri' that contains our 'struct sig_pri_span' */
14991 dahdi_pri = container_of(pri, struct dahdi_pri, pri);
14992 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14993 ast_debug(4, "closing pri_fd %d\n", i);
14994 dahdi_close_pri_fd(dahdi_pri, i);
14995 dahdi_pri->dchannels[i] = 0;
14996 }
14997 sig_pri_init_pri(pri);
14998 ast_debug(1, "PRI span %d destroyed\n", pri->span);
14999 }
15000
15001 static char *handle_pri_destroy_span(struct ast_cli_entry *e, int cmd,
15002 struct ast_cli_args *a)
15003 {
15004 int span;
15005 int res;
15006 struct sig_pri_span *pri;
15007
15008 switch (cmd) {
15009 case CLI_INIT:
15010 e->command = "pri destroy span";
15011 e->usage =
15012 "Usage: pri destroy span <span>\n"
15013 " Destorys D-channel of span and its B-channels.\n"
15014 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
15015 return NULL;
15016 case CLI_GENERATE:
15017 return complete_span_4(a->line, a->word, a->pos, a->n);
15018 }
15019
15020 if (a->argc < 4) {
15021 return CLI_SHOWUSAGE;
15022 }
15023 res = sscanf(a->argv[3], "%30d", &span);
15024 if ((res != 1) || span < 1 || span > NUM_SPANS) {
15025 ast_cli(a->fd,
15026 "Invalid span '%s'. Should be a number from %d to %d\n",
15027 a->argv[3], 1, NUM_SPANS);
15028 return CLI_SUCCESS;
15029 }
15030 pri = &pris[span - 1].pri;
15031 if (!pri->pri) {
15032 ast_cli(a->fd, "No PRI running on span %d\n", span);
15033 return CLI_SUCCESS;
15034 }
15035
15036 pri_destroy_span(pri);
15037 return CLI_SUCCESS;
15038 }
15039
15040 #endif /* defined(HAVE_PRI) */
15041
15042 #if defined(HAVE_PRI)
15043 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15044 {
15045 int span;
15046
15047 switch (cmd) {
15048 case CLI_INIT:
15049 e->command = "pri show span";
15050 e->usage =
15051 "Usage: pri show span <span>\n"
15052 " Displays PRI Information on a given PRI span\n";
15053 return NULL;
15054 case CLI_GENERATE:
15055 return complete_span_4(a->line, a->word, a->pos, a->n);
15056 }
15057
15058 if (a->argc < 4)
15059 return CLI_SHOWUSAGE;
15060 span = atoi(a->argv[3]);
15061 if ((span < 1) || (span > NUM_SPANS)) {
15062 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
15063 return CLI_SUCCESS;
15064 }
15065 if (!pris[span-1].pri.pri) {
15066 ast_cli(a->fd, "No PRI running on span %d\n", span);
15067 return CLI_SUCCESS;
15068 }
15069
15070 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
15071
15072 return CLI_SUCCESS;
15073 }
15074 #endif /* defined(HAVE_PRI) */
15075
15076 #if defined(HAVE_PRI)
15077 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15078 {
15079 int x;
15080 int span;
15081 int count=0;
15082 int debug;
15083
15084 switch (cmd) {
15085 case CLI_INIT:
15086 e->command = "pri show debug";
15087 e->usage =
15088 "Usage: pri show debug\n"
15089 " Show the debug state of pri spans\n";
15090 return NULL;
15091 case CLI_GENERATE:
15092 return NULL;
15093 }
15094
15095 for (span = 0; span < NUM_SPANS; span++) {
15096 if (pris[span].pri.pri) {
15097 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
15098 if (pris[span].pri.dchans[x]) {
15099 debug = pri_get_debug(pris[span].pri.dchans[x]);
15100 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" );
15101 count++;
15102 }
15103 }
15104 }
15105
15106 }
15107 ast_mutex_lock(&pridebugfdlock);
15108 if (pridebugfd >= 0)
15109 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
15110 ast_mutex_unlock(&pridebugfdlock);
15111
15112 if (!count)
15113 ast_cli(a->fd, "No PRI running\n");
15114 return CLI_SUCCESS;
15115 }
15116 #endif /* defined(HAVE_PRI) */
15117
15118 #if defined(HAVE_PRI)
15119 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15120 {
15121 switch (cmd) {
15122 case CLI_INIT:
15123 e->command = "pri show version";
15124 e->usage =
15125 "Usage: pri show version\n"
15126 "Show libpri version information\n";
15127 return NULL;
15128 case CLI_GENERATE:
15129 return NULL;
15130 }
15131
15132 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
15133
15134 return CLI_SUCCESS;
15135 }
15136 #endif /* defined(HAVE_PRI) */
15137
15138 #if defined(HAVE_PRI)
15139 static struct ast_cli_entry dahdi_pri_cli[] = {
15140 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
15141 #if defined(HAVE_PRI_SERVICE_MESSAGES)
15142 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
15143 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
15144 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
15145 AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
15146 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
15147 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
15148 AST_CLI_DEFINE(handle_pri_destroy_span, "Destroy a PRI span"),
15149 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
15150 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
15151 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
15152 };
15153 #endif /* defined(HAVE_PRI) */
15154
15155 #ifdef HAVE_OPENR2
15156
15157 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15158 {
15159 switch (cmd) {
15160 case CLI_INIT:
15161 e->command = "mfcr2 show version";
15162 e->usage =
15163 "Usage: mfcr2 show version\n"
15164 " Shows the version of the OpenR2 library being used.\n";
15165 return NULL;
15166 case CLI_GENERATE:
15167 return NULL;
15168 }
15169 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
15170 return CLI_SUCCESS;
15171 }
15172
15173 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15174 {
15175 #define FORMAT "%4s %40s\n"
15176 int i = 0;
15177 int numvariants = 0;
15178 const openr2_variant_entry_t *variants;
15179 switch (cmd) {
15180 case CLI_INIT:
15181 e->command = "mfcr2 show variants";
15182 e->usage =
15183 "Usage: mfcr2 show variants\n"
15184 " Shows the list of MFC/R2 variants supported.\n";
15185 return NULL;
15186 case CLI_GENERATE:
15187 return NULL;
15188 }
15189 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
15190 ast_cli(a->fd, "Failed to get list of variants.\n");
15191 return CLI_FAILURE;
15192 }
15193 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
15194 for (i = 0; i < numvariants; i++) {
15195 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
15196 }
15197 return CLI_SUCCESS;
15198 #undef FORMAT
15199 }
15200
15201 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15202 {
15203 #define FORMAT "%4s %4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
15204 int filtertype = 0;
15205 int targetnum = 0;
15206 char channo[5];
15207 char linkno[5];
15208 char anino[5];
15209 char dnisno[5];
15210 struct dahdi_pvt *p;
15211 openr2_context_t *r2context;
15212 openr2_variant_t r2variant;
15213 switch (cmd) {
15214 case CLI_INIT:
15215 e->command = "mfcr2 show channels [group|context]";
15216 e->usage =
15217 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
15218 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
15219 return NULL;
15220 case CLI_GENERATE:
15221 return NULL;
15222 }
15223 if (!((a->argc == 3) || (a->argc == 5))) {
15224 return CLI_SHOWUSAGE;
15225 }
15226 if (a->argc == 5) {
15227 if (!strcasecmp(a->argv[3], "group")) {
15228 targetnum = atoi(a->argv[4]);
15229 if ((targetnum < 0) || (targetnum > 63))
15230 return CLI_SHOWUSAGE;
15231 targetnum = 1 << targetnum;
15232 filtertype = 1;
15233 } else if (!strcasecmp(a->argv[3], "context")) {
15234 filtertype = 2;
15235 } else {
15236 return CLI_SHOWUSAGE;
15237 }
15238 }
15239 ast_cli(a->fd, FORMAT, "Chan", "Link#", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
15240 ast_mutex_lock(&iflock);
15241 for (p = iflist; p; p = p->next) {
15242 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15243 continue;
15244 }
15245 if (filtertype) {
15246 switch(filtertype) {
15247 case 1: /* mfcr2 show channels group <group> */
15248 if (p->group != targetnum) {
15249 continue;
15250 }
15251 break;
15252 case 2: /* mfcr2 show channels context <context> */
15253 if (strcasecmp(p->context, a->argv[4])) {
15254 continue;
15255 }
15256 break;
15257 default:
15258 ;
15259 }
15260 }
15261 r2context = openr2_chan_get_context(p->r2chan);
15262 r2variant = openr2_context_get_variant(r2context);
15263 snprintf(channo, sizeof(channo), "%d", p->channel);
15264 snprintf(linkno, sizeof(linkno), "%d", p->mfcr2->index);
15265 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
15266 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
15267 ast_cli(a->fd, FORMAT, channo, linkno, openr2_proto_get_variant_string(r2variant),
15268 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
15269 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
15270 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
15271 }
15272 ast_mutex_unlock(&iflock);
15273 return CLI_SUCCESS;
15274 #undef FORMAT
15275 }
15276
15277 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15278 {
15279 struct dahdi_pvt *p = NULL;
15280 int channo = 0;
15281 char *toklevel = NULL;
15282 char *saveptr = NULL;
15283 char *logval = NULL;
15284 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
15285 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
15286 switch (cmd) {
15287 case CLI_INIT:
15288 e->command = "mfcr2 set debug";
15289 e->usage =
15290 "Usage: mfcr2 set debug <loglevel> <channel>\n"
15291 " Set a new logging level for the specified channel.\n"
15292 " If no channel is specified the logging level will be applied to all channels.\n";
15293 return NULL;
15294 case CLI_GENERATE:
15295 return NULL;
15296 }
15297 if (a->argc < 4) {
15298 return CLI_SHOWUSAGE;
15299 }
15300 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15301 logval = ast_strdupa(a->argv[3]);
15302 toklevel = strtok_r(logval, ",", &saveptr);
15303 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15304 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
15305 return CLI_FAILURE;
15306 } else if (OR2_LOG_NOTHING == tmplevel) {
15307 loglevel = tmplevel;
15308 } else {
15309 loglevel |= tmplevel;
15310 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
15311 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15312 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
15313 continue;
15314 }
15315 loglevel |= tmplevel;
15316 }
15317 }
15318 ast_mutex_lock(&iflock);
15319 for (p = iflist; p; p = p->next) {
15320 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15321 continue;
15322 }
15323 if ((channo != -1) && (p->channel != channo )) {
15324 continue;
15325 }
15326 openr2_chan_set_log_level(p->r2chan, loglevel);
15327 if (channo != -1) {
15328 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
15329 break;
15330 }
15331 }
15332 if ((channo != -1) && !p) {
15333 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15334 }
15335 if (channo == -1) {
15336 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
15337 }
15338 ast_mutex_unlock(&iflock);
15339 return CLI_SUCCESS;
15340 }
15341
15342 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15343 {
15344 struct dahdi_pvt *p = NULL;
15345 int channo = 0;
15346 switch (cmd) {
15347 case CLI_INIT:
15348 e->command = "mfcr2 call files [on|off]";
15349 e->usage =
15350 "Usage: mfcr2 call files [on|off] <channel>\n"
15351 " Enable call files creation on the specified channel.\n"
15352 " If no channel is specified call files creation policy will be applied to all channels.\n";
15353 return NULL;
15354 case CLI_GENERATE:
15355 return NULL;
15356 }
15357 if (a->argc < 4) {
15358 return CLI_SHOWUSAGE;
15359 }
15360 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15361 ast_mutex_lock(&iflock);
15362 for (p = iflist; p; p = p->next) {
15363 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15364 continue;
15365 }
15366 if ((channo != -1) && (p->channel != channo )) {
15367 continue;
15368 }
15369 if (ast_true(a->argv[3])) {
15370 openr2_chan_enable_call_files(p->r2chan);
15371 } else {
15372 openr2_chan_disable_call_files(p->r2chan);
15373 }
15374 if (channo != -1) {
15375 if (ast_true(a->argv[3])) {
15376 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
15377 } else {
15378 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
15379 }
15380 break;
15381 }
15382 }
15383 if ((channo != -1) && !p) {
15384 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15385 }
15386 if (channo == -1) {
15387 if (ast_true(a->argv[3])) {
15388 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
15389 } else {
15390 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
15391 }
15392 }
15393 ast_mutex_unlock(&iflock);
15394 return CLI_SUCCESS;
15395 }
15396
15397 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15398 {
15399 struct dahdi_pvt *p = NULL;
15400 int channo = 0;
15401 switch (cmd) {
15402 case CLI_INIT:
15403 e->command = "mfcr2 set idle";
15404 e->usage =
15405 "Usage: mfcr2 set idle <channel>\n"
15406 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15407 " Force the given channel into IDLE state.\n"
15408 " If no channel is specified, all channels will be set to IDLE.\n";
15409 return NULL;
15410 case CLI_GENERATE:
15411 return NULL;
15412 }
15413 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15414 ast_mutex_lock(&iflock);
15415 for (p = iflist; p; p = p->next) {
15416 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15417 continue;
15418 }
15419 if ((channo != -1) && (p->channel != channo )) {
15420 continue;
15421 }
15422 openr2_chan_set_idle(p->r2chan);
15423 ast_mutex_lock(&p->lock);
15424 p->locallyblocked = 0;
15425 p->mfcr2call = 0;
15426 ast_mutex_unlock(&p->lock);
15427 if (channo != -1) {
15428 break;
15429 }
15430 }
15431 if ((channo != -1) && !p) {
15432 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15433 }
15434 ast_mutex_unlock(&iflock);
15435 return CLI_SUCCESS;
15436 }
15437
15438 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15439 {
15440 struct dahdi_pvt *p = NULL;
15441 int channo = 0;
15442 switch (cmd) {
15443 case CLI_INIT:
15444 e->command = "mfcr2 set blocked";
15445 e->usage =
15446 "Usage: mfcr2 set blocked <channel>\n"
15447 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15448 " Force the given channel into BLOCKED state.\n"
15449 " If no channel is specified, all channels will be set to BLOCKED.\n";
15450 return NULL;
15451 case CLI_GENERATE:
15452 return NULL;
15453 }
15454 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15455 ast_mutex_lock(&iflock);
15456 for (p = iflist; p; p = p->next) {
15457 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15458 continue;
15459 }
15460 if ((channo != -1) && (p->channel != channo )) {
15461 continue;
15462 }
15463 openr2_chan_set_blocked(p->r2chan);
15464 ast_mutex_lock(&p->lock);
15465 p->locallyblocked = 1;
15466 ast_mutex_unlock(&p->lock);
15467 if (channo != -1) {
15468 break;
15469 }
15470 }
15471 if ((channo != -1) && !p) {
15472 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15473 }
15474 ast_mutex_unlock(&iflock);
15475 return CLI_SUCCESS;
15476 }
15477
15478 static void mfcr2_show_links_of(struct ast_cli_args *a, struct r2links *list_head, const char *title)
15479 {
15480 #define FORMAT "%-5s %-10s %-15s %-10s %s\n"
15481 AST_LIST_LOCK(list_head);
15482 if (! AST_LIST_EMPTY(list_head)) {
15483 int x = 0;
15484 char index[5];
15485 char live_chans_str[5];
15486 char channel_list[R2_LINK_CAPACITY * 4];
15487 struct r2link_entry *cur;
15488 ast_cli(a->fd, "%s\n", title);
15489 ast_cli(a->fd, FORMAT, "Index", "Thread", "Dahdi-Device", "Channels", "Channel-List");
15490 AST_LIST_TRAVERSE(list_head, cur, list) {
15491 struct dahdi_mfcr2 *mfcr2 = &cur->mfcr2;
15492 const char *thread_status = NULL;
15493 int i;
15494 int len;
15495 int inside_range;
15496 int channo;
15497 int prev_channo;
15498 x++;
15499 if (mfcr2->r2master == 0L) {
15500 thread_status = "zero";
15501 } else if (mfcr2->r2master == AST_PTHREADT_NULL) {
15502 thread_status = "none";
15503 } else {
15504 thread_status = "created";
15505 }
15506 snprintf(index, sizeof(index), "%d", mfcr2->index);
15507 snprintf(live_chans_str, sizeof(live_chans_str), "%d", mfcr2->live_chans);
15508 channo = 0;
15509 prev_channo = 0;
15510 inside_range = 0;
15511 len = 0;
15512 /* Prepare nice string in channel_list[] */
15513 for (i = 0; i < mfcr2->numchans && len < sizeof(channel_list) - 1; i++) {
15514 struct dahdi_pvt *p = mfcr2->pvts[i];
15515 if (!p) {
15516 continue;
15517 }
15518 channo = p->channel;
15519 /* Don't show a range until we know the last channel number */
15520 if (prev_channo && prev_channo == channo - 1) {
15521 prev_channo = channo;
15522 inside_range = 1;
15523 continue;
15524 }
15525 if (inside_range) {
15526 /* Close range */
15527 len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, "-%d,%d", prev_channo, channo);
15528 inside_range = 0;
15529 } else if (prev_channo) {
15530 /* Non-sequential channel numbers */
15531 len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, ",%d", channo);
15532 } else {
15533 /* First channel number */
15534 len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, "%d", channo);
15535 }
15536 prev_channo = channo;
15537 }
15538 /* Handle leftover channels */
15539 if (inside_range) {
15540 /* Close range */
15541 len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, "-%d", channo);
15542 inside_range = 0;
15543 } else if (prev_channo) {
15544 /* Non-sequential channel numbers */
15545 len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, ",%d", channo);
15546 }
15547 // channel_list[len] = '\0';
15548 ast_cli(a->fd, FORMAT,
15549 index,
15550 thread_status,
15551 (mfcr2->nodev) ? "MISSING" : "OK",
15552 live_chans_str,
15553 channel_list);
15554 }
15555 }
15556 AST_LIST_UNLOCK(list_head);
15557 #undef FORMAT
15558 }
15559
15560 static char *handle_mfcr2_show_links(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15561 {
15562 switch (cmd) {
15563 case CLI_INIT:
15564 e->command = "mfcr2 show links";
15565 e->usage =
15566 "Usage: mfcr2 show links\n"
15567 " Shows the DAHDI MFC/R2 links.\n";
15568 return NULL;
15569 case CLI_GENERATE:
15570 return NULL;
15571 }
15572 if (a->argc != 3) {
15573 return CLI_SHOWUSAGE;
15574 }
15575 mfcr2_show_links_of(a, &r2links, "Live links\n");
15576 mfcr2_show_links_of(a, &nodev_r2links, "Links to be removed (device missing)\n");
15577 return CLI_SUCCESS;
15578 }
15579
15580 static char *handle_mfcr2_destroy_link(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15581 {
15582 int res;
15583 int wanted_link_index;
15584 int found_link = 0;
15585 struct r2link_entry *cur = NULL;
15586
15587 switch (cmd) {
15588 case CLI_INIT:
15589 e->command = "mfcr2 destroy link";
15590 e->usage =
15591 "Usage: mfcr2 destroy link <index-number>\n"
15592 " Destorys D-channel of link and its B-channels.\n"
15593 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
15594 return NULL;
15595 case CLI_GENERATE:
15596 return NULL;
15597 }
15598 if (a->argc < 4) {
15599 return CLI_SHOWUSAGE;
15600 }
15601 res = sscanf(a->argv[3], "%30d", &wanted_link_index);
15602 if ((res != 1) || wanted_link_index < 1) {
15603 ast_cli(a->fd,
15604 "Invalid link index '%s'. Should be a positive number\n", a->argv[3]);
15605 return CLI_SUCCESS;
15606 }
15607 AST_LIST_LOCK(&r2links);
15608 AST_LIST_TRAVERSE_SAFE_BEGIN(&r2links, cur, list) {
15609 struct dahdi_mfcr2 *mfcr2 = &cur->mfcr2;
15610 if (wanted_link_index == mfcr2->index) {
15611 AST_LIST_MOVE_CURRENT(&nodev_r2links, list);
15612 r2links_count--;
15613 break;
15614 }
15615 }
15616 AST_LIST_TRAVERSE_SAFE_END;
15617 AST_LIST_UNLOCK(&r2links);
15618 if (! found_link) {
15619 ast_cli(a->fd, "No link found with index %d.\n", wanted_link_index);
15620 return CLI_FAILURE;
15621 }
15622 return CLI_SUCCESS;
15623 }
15624
15625 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15626 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15627 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15628 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15629 AST_CLI_DEFINE(handle_mfcr2_show_links, "Show MFC/R2 links"),
15630 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15631 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15632 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15633 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15634 AST_CLI_DEFINE(handle_mfcr2_destroy_link, "Destroy given MFC/R2 link"),
15635 };
15636
15637 #endif /* HAVE_OPENR2 */
15638
15639 static char *dahdi_destroy_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15640 {
15641 int start;
15642 int end;
15643 switch (cmd) {
15644 case CLI_INIT:
15645 e->command = "dahdi destroy channels";
15646 e->usage =
15647 "Usage: dahdi destroy channels <from_channel> [<to_channel>]\n"
15648 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
15649 return NULL;
15650 case CLI_GENERATE:
15651 return NULL;
15652 }
15653 if ((a->argc < 4) || a->argc > 5) {
15654 return CLI_SHOWUSAGE;
15655 }
15656 start = atoi(a->argv[3]);
15657 if (start < 1) {
15658 ast_cli(a->fd, "Invalid starting channel number %s.\n",
15659 a->argv[4]);
15660 return CLI_FAILURE;
15661 }
15662 if (a->argc == 5) {
15663 end = atoi(a->argv[4]);
15664 if (end < 1) {
15665 ast_cli(a->fd, "Invalid ending channel number %s.\n",
15666 a->argv[4]);
15667 return CLI_FAILURE;
15668 }
15669 } else {
15670 end = start;
15671 }
15672
15673 if (end < start) {
15674 ast_cli(a->fd,
15675 "range end (%d) is smaller than range start (%d)\n",
15676 end, start);
15677 return CLI_FAILURE;
15678 }
15679 dahdi_destroy_channel_range(start, end);
15680 return CLI_SUCCESS;
15681 }
15682
15683 static char *dahdi_create_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15684 {
15685 int start;
15686 int end;
15687 int ret;
15688
15689 switch (cmd) {
15690 case CLI_INIT:
15691 e->command = "dahdi create channels";
15692 e->usage = "Usage: dahdi create channels <from> [<to>] - a range of channels\n"
15693 " dahdi create channels new - add channels not yet created\n"
15694 "For ISDN and SS7 the range should include complete spans.\n";
15695 return NULL;
15696 case CLI_GENERATE:
15697 return NULL;
15698 }
15699 if ((a->argc < 4) || a->argc > 5) {
15700 return CLI_SHOWUSAGE;
15701 }
15702 if (a->argc == 4 && !strcmp(a->argv[3], "new")) {
15703 ret = dahdi_create_channel_range(0, 0);
15704 return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
15705 }
15706 start = atoi(a->argv[3]);
15707 if (start <= 0) {
15708 ast_cli(a->fd, "Invalid starting channel number '%s'.\n",
15709 a->argv[3]);
15710 return CLI_FAILURE;
15711 }
15712 if (a->argc == 5) {
15713 end = atoi(a->argv[4]);
15714 if (end <= 0) {
15715 ast_cli(a->fd, "Invalid ending channel number '%s'.\n",
15716 a->argv[4]);
15717 return CLI_FAILURE;
15718 }
15719 } else {
15720 end = start;
15721 }
15722 if (end < start) {
15723 ast_cli(a->fd,
15724 "range end (%d) is smaller than range start (%d)\n",
15725 end, start);
15726 return CLI_FAILURE;
15727 }
15728 ret = dahdi_create_channel_range(start, end);
15729 return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
15730 }
15731
15732 static void dahdi_softhangup_all(void)
15733 {
15734 struct dahdi_pvt *p;
15735 retry:
15736 ast_mutex_lock(&iflock);
15737 for (p = iflist; p; p = p->next) {
15738 ast_mutex_lock(&p->lock);
15739 if (p->owner && !p->restartpending) {
15740 if (ast_channel_trylock(p->owner)) {
15741 if (DEBUG_ATLEAST(3))
15742 ast_verbose("Avoiding deadlock\n");
15743 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15744 ast_mutex_unlock(&p->lock);
15745 ast_mutex_unlock(&iflock);
15746 goto retry;
15747 }
15748 if (DEBUG_ATLEAST(3))
15749 ast_verbose("Softhanging up on %s\n", ast_channel_name(p->owner));
15750 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15751 p->restartpending = 1;
15752 num_restart_pending++;
15753 ast_channel_unlock(p->owner);
15754 }
15755 ast_mutex_unlock(&p->lock);
15756 }
15757 ast_mutex_unlock(&iflock);
15758 }
15759
15760 static int dahdi_restart(void)
15761 {
15762 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15763 int i, j;
15764 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15765 int cancel_code;
15766 struct dahdi_pvt *p;
15767
15768 ast_mutex_lock(&restart_lock);
15769 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15770 dahdi_softhangup_all();
15771 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15772 #ifdef HAVE_OPENR2
15773 dahdi_r2_destroy_links();
15774 #endif
15775
15776 #if defined(HAVE_PRI)
15777 for (i = 0; i < NUM_SPANS; i++) {
15778 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15779 cancel_code = pthread_cancel(pris[i].pri.master);
15780 pthread_kill(pris[i].pri.master, SIGURG);
15781 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);
15782 pthread_join(pris[i].pri.master, NULL);
15783 ast_debug(4, "Joined thread of span %d\n", i);
15784 }
15785 }
15786 #endif
15787
15788 #if defined(HAVE_SS7)
15789 for (i = 0; i < NUM_SPANS; i++) {
15790 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15791 cancel_code = pthread_cancel(linksets[i].ss7.master);
15792 pthread_kill(linksets[i].ss7.master, SIGURG);
15793 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);
15794 pthread_join(linksets[i].ss7.master, NULL);
15795 ast_debug(4, "Joined thread of span %d\n", i);
15796 }
15797 }
15798 #endif /* defined(HAVE_SS7) */
15799
15800 ast_mutex_lock(&monlock);
15801 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15802 cancel_code = pthread_cancel(monitor_thread);
15803 pthread_kill(monitor_thread, SIGURG);
15804 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15805 pthread_join(monitor_thread, NULL);
15806 ast_debug(4, "Joined monitor thread\n");
15807 }
15808 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15809
15810 ast_mutex_lock(&ss_thread_lock);
15811 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15812 int x = DAHDI_FLASH;
15813 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15814
15815 ast_mutex_lock(&iflock);
15816 for (p = iflist; p; p = p->next) {
15817 if (p->owner) {
15818 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15819 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15820 }
15821 }
15822 ast_mutex_unlock(&iflock);
15823 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15824 }
15825
15826 /* ensure any created channels before monitor threads were stopped are hungup */
15827 dahdi_softhangup_all();
15828 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15829 destroy_all_channels();
15830 memset(round_robin, 0, sizeof(round_robin));
15831 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15832
15833 ast_mutex_unlock(&monlock);
15834
15835 #ifdef HAVE_PRI
15836 for (i = 0; i < NUM_SPANS; i++) {
15837 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15838 dahdi_close_pri_fd(&(pris[i]), j);
15839 }
15840
15841 memset(pris, 0, sizeof(pris));
15842 for (i = 0; i < NUM_SPANS; i++) {
15843 sig_pri_init_pri(&pris[i].pri);
15844 }
15845 pri_set_error(dahdi_pri_error);
15846 pri_set_message(dahdi_pri_message);
15847 #endif
15848 #if defined(HAVE_SS7)
15849 for (i = 0; i < NUM_SPANS; i++) {
15850 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15851 dahdi_close_ss7_fd(&(linksets[i]), j);
15852 }
15853
15854 memset(linksets, 0, sizeof(linksets));
15855 for (i = 0; i < NUM_SPANS; i++) {
15856 sig_ss7_init_linkset(&linksets[i].ss7);
15857 }
15858 ss7_set_error(dahdi_ss7_error);
15859 ss7_set_message(dahdi_ss7_message);
15860 ss7_set_hangup(sig_ss7_cb_hangup);
15861 ss7_set_notinservice(sig_ss7_cb_notinservice);
15862 ss7_set_call_null(sig_ss7_cb_call_null);
15863 #endif /* defined(HAVE_SS7) */
15864
15865 if (setup_dahdi(2) != 0) {
15866 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15867 ast_mutex_unlock(&ss_thread_lock);
15868 return 1;
15869 }
15870 ast_mutex_unlock(&ss_thread_lock);
15871 ast_mutex_unlock(&restart_lock);
15872 return 0;
15873 }
15874
15875 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15876 {
15877 switch (cmd) {
15878 case CLI_INIT:
15879 e->command = "dahdi restart";
15880 e->usage =
15881 "Usage: dahdi restart\n"
15882 " Restarts the DAHDI channels: destroys them all and then\n"
15883 " re-reads them from chan_dahdi.conf.\n"
15884 " Note that this will STOP any running CALL on DAHDI channels.\n"
15885 "";
15886 return NULL;
15887 case CLI_GENERATE:
15888 return NULL;
15889 }
15890 if (a->argc != 2)
15891 return CLI_SHOWUSAGE;
15892
15893 if (dahdi_restart() != 0)
15894 return CLI_FAILURE;
15895 return CLI_SUCCESS;
15896 }
15897
15898 static int action_dahdirestart(struct mansession *s, const struct message *m)
15899 {
15900 if (dahdi_restart() != 0) {
15901 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15902 return 1;
15903 }
15904 astman_send_ack(s, m, "DAHDIRestart: Success");
15905 return 0;
15906 }
15907
15908 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15909 {
15910 #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
15911 #define FORMAT2 "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
15912 ast_group_t targetnum = 0;
15913 int filtertype = 0;
15914 struct dahdi_pvt *tmp = NULL;
15915 char tmps[20];
15916 char blockstr[20];
15917
15918 switch (cmd) {
15919 case CLI_INIT:
15920 e->command = "dahdi show channels [group|context]";
15921 e->usage =
15922 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15923 " Shows a list of available channels with optional filtering\n"
15924 " <group> must be a number between 0 and 63\n";
15925 return NULL;
15926 case CLI_GENERATE:
15927 return NULL;
15928 }
15929
15930 /* syntax: dahdi show channels [ group <group> | context <context> ] */
15931
15932 if (!((a->argc == 3) || (a->argc == 5))) {
15933 return CLI_SHOWUSAGE;
15934 }
15935
15936 if (a->argc == 5) {
15937 if (!strcasecmp(a->argv[3], "group")) {
15938 targetnum = atoi(a->argv[4]);
15939 if (63 < targetnum) {
15940 return CLI_SHOWUSAGE;
15941 }
15942 targetnum = ((ast_group_t) 1) << targetnum;
15943 filtertype = 1;
15944 } else if (!strcasecmp(a->argv[3], "context")) {
15945 filtertype = 2;
15946 }
15947 }
15948
15949 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "In Service", "Description");
15950 ast_mutex_lock(&iflock);
15951 for (tmp = iflist; tmp; tmp = tmp->next) {
15952 if (filtertype) {
15953 switch(filtertype) {
15954 case 1: /* dahdi show channels group <group> */
15955 if (!(tmp->group & targetnum)) {
15956 continue;
15957 }
15958 break;
15959 case 2: /* dahdi show channels context <context> */
15960 if (strcasecmp(tmp->context, a->argv[4])) {
15961 continue;
15962 }
15963 break;
15964 default:
15965 break;
15966 }
15967 }
15968 if (tmp->channel > 0) {
15969 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15970 } else {
15971 ast_copy_string(tmps, "pseudo", sizeof(tmps));
15972 }
15973
15974 blockstr[0] = tmp->locallyblocked ? 'L' : ' ';
15975 blockstr[1] = tmp->remotelyblocked ? 'R' : ' ';
15976 blockstr[2] = '\0';
15977
15978 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, tmp->inservice ? "Yes" : "No", tmp->description);
15979 }
15980 ast_mutex_unlock(&iflock);
15981 return CLI_SUCCESS;
15982 #undef FORMAT
15983 #undef FORMAT2
15984 }
15985
15986 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15987 {
15988 int channel;
15989 struct dahdi_pvt *tmp = NULL;
15990 struct dahdi_confinfo ci;
15991 struct dahdi_params ps;
15992 int x;
15993 char hwrxgain[15];
15994 char hwtxgain[15];
15995
15996 switch (cmd) {
15997 case CLI_INIT:
15998 e->command = "dahdi show channel";
15999 e->usage =
16000 "Usage: dahdi show channel <chan num>\n"
16001 " Detailed information about a given channel\n";
16002 return NULL;
16003 case CLI_GENERATE:
16004 return NULL;
16005 }
16006
16007 if (a->argc != 4)
16008 return CLI_SHOWUSAGE;
16009
16010 channel = atoi(a->argv[3]);
16011
16012 ast_mutex_lock(&iflock);
16013 for (tmp = iflist; tmp; tmp = tmp->next) {
16014 if (tmp->channel == channel) {
16015 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
16016 ast_cli(a->fd, "Description: %s\n", tmp->description);
16017 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
16018 ast_cli(a->fd, "Span: %d\n", tmp->span);
16019 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
16020 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
16021 ast_cli(a->fd, "Context: %s\n", tmp->context);
16022 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
16023 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
16024 #if defined(HAVE_PRI)
16025 #if defined(HAVE_PRI_SUBADDR)
16026 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
16027 #endif /* defined(HAVE_PRI_SUBADDR) */
16028 #endif /* defined(HAVE_PRI) */
16029 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
16030 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
16031 if (tmp->vars) {
16032 struct ast_variable *v;
16033 ast_cli(a->fd, "Variables:\n");
16034 for (v = tmp->vars ; v ; v = v->next)
16035 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
16036 }
16037 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
16038 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
16039 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
16040 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
16041 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? ast_channel_name(tmp->owner) : "<None>");
16042 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)" : "");
16043 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)" : "");
16044 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)" : "");
16045 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
16046 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
16047 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
16048 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
16049 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
16050 if (tmp->busydetect) {
16051 #if defined(BUSYDETECT_TONEONLY)
16052 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
16053 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
16054 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
16055 #endif
16056 #ifdef BUSYDETECT_DEBUG
16057 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
16058 #endif
16059 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
16060 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);
16061 }
16062 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
16063 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
16064 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
16065 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
16066 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
16067 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
16068 if (tmp->hwrxgain_enabled) {
16069 snprintf(hwrxgain, sizeof(hwrxgain), "%.1f", tmp->hwrxgain);
16070 } else {
16071 ast_copy_string(hwrxgain, "Disabled", sizeof(hwrxgain));
16072 }
16073 if (tmp->hwtxgain_enabled) {
16074 snprintf(hwtxgain, sizeof(hwtxgain), "%.1f", tmp->hwtxgain);
16075 } else {
16076 ast_copy_string(hwtxgain, "Disabled", sizeof(hwtxgain));
16077 }
16078 ast_cli(a->fd, "HW Gains (RX/TX): %s/%s\n", hwrxgain, hwtxgain);
16079 ast_cli(a->fd, "SW Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
16080 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
16081 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
16082 ast_cli(a->fd, "Echo Cancellation:\n");
16083
16084 if (tmp->echocancel.head.tap_length) {
16085 ast_cli(a->fd, "\t%u taps\n", tmp->echocancel.head.tap_length);
16086 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
16087 ast_cli(a->fd, "\t\t%s: %dd\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
16088 }
16089 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
16090 } else {
16091 ast_cli(a->fd, "\tnone\n");
16092 }
16093 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
16094 if (tmp->master)
16095 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
16096 for (x = 0; x < MAX_SLAVES; x++) {
16097 if (tmp->slaves[x])
16098 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
16099 }
16100 #ifdef HAVE_OPENR2
16101 if (tmp->mfcr2) {
16102 char calldir[OR2_MAX_PATH];
16103 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
16104 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
16105 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
16106 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
16107 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
16108 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
16109 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
16110 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
16111 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
16112 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
16113 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
16114 ast_cli(a->fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
16115 ast_cli(a->fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
16116 #endif
16117 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
16118 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
16119 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
16120 #endif
16121 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
16122 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
16123 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
16124 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
16125 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
16126 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
16127 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
16128 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
16129 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
16130 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
16131 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
16132 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
16133 }
16134 #endif
16135 #if defined(HAVE_SS7)
16136 if (tmp->ss7) {
16137 struct sig_ss7_chan *chan = tmp->sig_pvt;
16138
16139 ast_cli(a->fd, "CIC: %d\n", chan->cic);
16140 }
16141 #endif /* defined(HAVE_SS7) */
16142 #ifdef HAVE_PRI
16143 if (tmp->pri) {
16144 struct sig_pri_chan *chan = tmp->sig_pvt;
16145
16146 ast_cli(a->fd, "PRI Flags: ");
16147 if (chan->resetting != SIG_PRI_RESET_IDLE) {
16148 ast_cli(a->fd, "Resetting=%u ", chan->resetting);
16149 }
16150 if (chan->call)
16151 ast_cli(a->fd, "Call ");
16152 if (chan->allocated) {
16153 ast_cli(a->fd, "Allocated ");
16154 }
16155 ast_cli(a->fd, "\n");
16156 if (tmp->logicalspan)
16157 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
16158 else
16159 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
16160 }
16161 #endif
16162 memset(&ci, 0, sizeof(ci));
16163 ps.channo = tmp->channel;
16164 if (tmp->subs[SUB_REAL].dfd > -1) {
16165 memset(&ci, 0, sizeof(ci));
16166 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
16167 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, (unsigned)ci.confmode);
16168 }
16169 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
16170 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
16171 }
16172 memset(&ps, 0, sizeof(ps));
16173 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
16174 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
16175 } else {
16176 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
16177 }
16178 }
16179 ast_mutex_unlock(&iflock);
16180 return CLI_SUCCESS;
16181 }
16182 }
16183 ast_mutex_unlock(&iflock);
16184
16185 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16186 return CLI_FAILURE;
16187 }
16188
16189 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16190 {
16191 int i, j;
16192 switch (cmd) {
16193 case CLI_INIT:
16194 e->command = "dahdi show cadences";
16195 e->usage =
16196 "Usage: dahdi show cadences\n"
16197 " Shows all cadences currently defined\n";
16198 return NULL;
16199 case CLI_GENERATE:
16200 return NULL;
16201 }
16202 for (i = 0; i < num_cadence; i++) {
16203 char output[1024];
16204 char tmp[16], tmp2[64];
16205 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
16206 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
16207
16208 for (j = 0; j < 16; j++) {
16209 if (cadences[i].ringcadence[j] == 0)
16210 break;
16211 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
16212 if (cidrings[i] * 2 - 1 == j)
16213 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
16214 else
16215 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
16216 if (j != 0)
16217 strncat(output, ",", sizeof(output) - strlen(output) - 1);
16218 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
16219 }
16220 ast_cli(a->fd,"%s\n",output);
16221 }
16222 return CLI_SUCCESS;
16223 }
16224
16225 /* Based on irqmiss.c */
16226 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16227 {
16228 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
16229 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
16230 int span;
16231 int res;
16232 char alarmstr[50];
16233
16234 int ctl;
16235 struct dahdi_spaninfo s;
16236
16237 switch (cmd) {
16238 case CLI_INIT:
16239 e->command = "dahdi show status";
16240 e->usage =
16241 "Usage: dahdi show status\n"
16242 " Shows a list of DAHDI cards with status\n";
16243 return NULL;
16244 case CLI_GENERATE:
16245 return NULL;
16246 }
16247 ctl = open("/dev/dahdi/ctl", O_RDWR);
16248 if (ctl < 0) {
16249 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
16250 return CLI_FAILURE;
16251 }
16252 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
16253
16254 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
16255 s.spanno = span;
16256 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
16257 if (res) {
16258 continue;
16259 }
16260 alarmstr[0] = '\0';
16261 if (s.alarms > 0) {
16262 if (s.alarms & DAHDI_ALARM_BLUE)
16263 strcat(alarmstr, "BLU/");
16264 if (s.alarms & DAHDI_ALARM_YELLOW)
16265 strcat(alarmstr, "YEL/");
16266 if (s.alarms & DAHDI_ALARM_RED)
16267 strcat(alarmstr, "RED/");
16268 if (s.alarms & DAHDI_ALARM_LOOPBACK)
16269 strcat(alarmstr, "LB/");
16270 if (s.alarms & DAHDI_ALARM_RECOVER)
16271 strcat(alarmstr, "REC/");
16272 if (s.alarms & DAHDI_ALARM_NOTOPEN)
16273 strcat(alarmstr, "NOP/");
16274 if (!strlen(alarmstr))
16275 strcat(alarmstr, "UUU/");
16276 if (strlen(alarmstr)) {
16277 /* Strip trailing / */
16278 alarmstr[strlen(alarmstr) - 1] = '\0';
16279 }
16280 } else {
16281 if (s.numchans)
16282 strcpy(alarmstr, "OK");
16283 else
16284 strcpy(alarmstr, "UNCONFIGURED");
16285 }
16286
16287 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
16288 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
16289 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
16290 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
16291 "CAS",
16292 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
16293 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
16294 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
16295 "Unk",
16296 s.lineconfig & DAHDI_CONFIG_CRC4 ?
16297 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
16298 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
16299 lbostr[s.lbo]
16300 );
16301 }
16302 close(ctl);
16303
16304 return CLI_SUCCESS;
16305 #undef FORMAT
16306 #undef FORMAT2
16307 }
16308
16309 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16310 {
16311 int pseudo_fd = -1;
16312 struct dahdi_versioninfo vi;
16313
16314 switch (cmd) {
16315 case CLI_INIT:
16316 e->command = "dahdi show version";
16317 e->usage =
16318 "Usage: dahdi show version\n"
16319 " Shows the DAHDI version in use\n";
16320 return NULL;
16321 case CLI_GENERATE:
16322 return NULL;
16323 }
16324 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
16325 ast_cli(a->fd, "Failed to open control file to get version.\n");
16326 return CLI_SUCCESS;
16327 }
16328
16329 strcpy(vi.version, "Unknown");
16330 strcpy(vi.echo_canceller, "Unknown");
16331
16332 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
16333 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
16334 else
16335 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
16336
16337 close(pseudo_fd);
16338
16339 return CLI_SUCCESS;
16340 }
16341
16342 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16343 {
16344 int channel;
16345 float gain;
16346 int tx;
16347 struct dahdi_pvt *tmp = NULL;
16348
16349 switch (cmd) {
16350 case CLI_INIT:
16351 e->command = "dahdi set hwgain {rx|tx}";
16352 e->usage =
16353 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
16354 " Sets the hardware gain on a given channel and overrides the\n"
16355 " value provided at module loadtime. Changes take effect\n"
16356 " immediately whether the channel is in use or not.\n"
16357 "\n"
16358 " <rx|tx> which direction do you want to change (relative to our module)\n"
16359 " <chan num> is the channel number relative to the device\n"
16360 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
16361 "\n"
16362 " Please note:\n"
16363 " * hwgain is only supportable by hardware with analog ports because\n"
16364 " hwgain works on the analog side of an analog-digital conversion.\n";
16365 return NULL;
16366 case CLI_GENERATE:
16367 return NULL;
16368 }
16369
16370 if (a->argc != 6)
16371 return CLI_SHOWUSAGE;
16372
16373 if (!strcasecmp("rx", a->argv[3]))
16374 tx = 0; /* rx */
16375 else if (!strcasecmp("tx", a->argv[3]))
16376 tx = 1; /* tx */
16377 else
16378 return CLI_SHOWUSAGE;
16379
16380 channel = atoi(a->argv[4]);
16381 gain = atof(a->argv[5]);
16382
16383 ast_mutex_lock(&iflock);
16384
16385 for (tmp = iflist; tmp; tmp = tmp->next) {
16386
16387 if (tmp->channel != channel)
16388 continue;
16389
16390 if (tmp->subs[SUB_REAL].dfd == -1)
16391 break;
16392
16393 if (set_hwgain(tmp->subs[SUB_REAL].dfd, gain, tx)) {
16394 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
16395 ast_mutex_unlock(&iflock);
16396 return CLI_FAILURE;
16397 }
16398 ast_cli(a->fd, "Hardware %s gain set to %.1f dB on channel %d.\n",
16399 tx ? "tx" : "rx", gain, channel);
16400
16401 if (tx) {
16402 tmp->hwtxgain_enabled = 1;
16403 tmp->hwtxgain = gain;
16404 } else {
16405 tmp->hwrxgain_enabled = 1;
16406 tmp->hwrxgain = gain;
16407 }
16408 break;
16409 }
16410
16411 ast_mutex_unlock(&iflock);
16412
16413 if (tmp)
16414 return CLI_SUCCESS;
16415
16416 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16417 return CLI_FAILURE;
16418
16419 }
16420
16421 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16422 {
16423 int channel;
16424 float gain;
16425 int tx;
16426 int res;
16427 struct dahdi_pvt *tmp = NULL;
16428
16429 switch (cmd) {
16430 case CLI_INIT:
16431 e->command = "dahdi set swgain {rx|tx}";
16432 e->usage =
16433 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
16434 " Sets the software gain on a given channel and overrides the\n"
16435 " value provided at module loadtime. Changes take effect\n"
16436 " immediately whether the channel is in use or not.\n"
16437 "\n"
16438 " <rx|tx> which direction do you want to change (relative to our module)\n"
16439 " <chan num> is the channel number relative to the device\n"
16440 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
16441 return NULL;
16442 case CLI_GENERATE:
16443 return NULL;
16444 }
16445
16446 if (a->argc != 6)
16447 return CLI_SHOWUSAGE;
16448
16449 if (!strcasecmp("rx", a->argv[3]))
16450 tx = 0; /* rx */
16451 else if (!strcasecmp("tx", a->argv[3]))
16452 tx = 1; /* tx */
16453 else
16454 return CLI_SHOWUSAGE;
16455
16456 channel = atoi(a->argv[4]);
16457 gain = atof(a->argv[5]);
16458
16459 ast_mutex_lock(&iflock);
16460 for (tmp = iflist; tmp; tmp = tmp->next) {
16461
16462 if (tmp->channel != channel)
16463 continue;
16464
16465 if (tmp->subs[SUB_REAL].dfd == -1)
16466 break;
16467
16468 if (tx)
16469 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
16470 else
16471 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
16472
16473 if (res) {
16474 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
16475 ast_mutex_unlock(&iflock);
16476 return CLI_FAILURE;
16477 }
16478
16479 ast_cli(a->fd, "Software %s gain set to %.2f dB on channel %d.\n",
16480 tx ? "tx" : "rx", gain, channel);
16481
16482 if (tx) {
16483 tmp->txgain = gain;
16484 } else {
16485 tmp->rxgain = gain;
16486 }
16487 break;
16488 }
16489 ast_mutex_unlock(&iflock);
16490
16491 if (tmp)
16492 return CLI_SUCCESS;
16493
16494 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16495 return CLI_FAILURE;
16496
16497 }
16498
16499 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16500 {
16501 int channel;
16502 int on;
16503 struct dahdi_pvt *dahdi_chan = NULL;
16504
16505 switch (cmd) {
16506 case CLI_INIT:
16507 e->command = "dahdi set dnd";
16508 e->usage =
16509 "Usage: dahdi set dnd <chan#> <on|off>\n"
16510 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
16511 " Changes take effect immediately.\n"
16512 " <chan num> is the channel number\n"
16513 " <on|off> Enable or disable DND mode?\n"
16514 ;
16515 return NULL;
16516 case CLI_GENERATE:
16517 return NULL;
16518 }
16519
16520 if (a->argc != 5)
16521 return CLI_SHOWUSAGE;
16522
16523 if ((channel = atoi(a->argv[3])) <= 0) {
16524 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16525 return CLI_SHOWUSAGE;
16526 }
16527
16528 if (ast_true(a->argv[4]))
16529 on = 1;
16530 else if (ast_false(a->argv[4]))
16531 on = 0;
16532 else {
16533 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
16534 return CLI_SHOWUSAGE;
16535 }
16536
16537 ast_mutex_lock(&iflock);
16538 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16539 if (dahdi_chan->channel != channel)
16540 continue;
16541
16542 /* Found the channel. Actually set it */
16543 dahdi_dnd(dahdi_chan, on);
16544 break;
16545 }
16546 ast_mutex_unlock(&iflock);
16547
16548 if (!dahdi_chan) {
16549 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16550 return CLI_FAILURE;
16551 }
16552
16553 return CLI_SUCCESS;
16554 }
16555
16556 static char *dahdi_set_mwi(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16557 {
16558 int channel;
16559 int on;
16560 int override = 1;
16561 struct dahdi_pvt *dahdi_chan = NULL;
16562
16563 switch (cmd) {
16564 case CLI_INIT:
16565 e->command = "dahdi set mwi";
16566 e->usage =
16567 "Usage: dahdi set mwi <chan#> <on|off|reset>\n"
16568 " Sets/unsets MWI (Message Waiting Indicator) manually on a channel.\n"
16569 " This may be used regardless of whether the channel is assigned any mailboxes.\n"
16570 " When active, this setting will override the voicemail status to set MWI.\n"
16571 " Once cleared, the voicemail status will resume control of MWI.\n"
16572 " Changes are queued for when the channel is idle and persist until cleared.\n"
16573 " <chan num> is the channel number\n"
16574 " <on|off|reset> Enable, disable, or reset Message Waiting Indicator override?\n"
16575 ;
16576 return NULL;
16577 case CLI_GENERATE:
16578 return NULL;
16579 }
16580
16581 if (a->argc != 5)
16582 return CLI_SHOWUSAGE;
16583
16584 if ((channel = atoi(a->argv[3])) <= 0) {
16585 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16586 return CLI_SHOWUSAGE;
16587 }
16588
16589 if (ast_true(a->argv[4])) {
16590 on = 1;
16591 } else if (ast_false(a->argv[4])) {
16592 on = 0;
16593 } else if (!strcmp(a->argv[4], "reset")) {
16594 override = 0;
16595 } else {
16596 ast_cli(a->fd, "Expected 'on' or 'off' or 'reset', got '%s'\n", a->argv[4]);
16597 return CLI_SHOWUSAGE;
16598 }
16599
16600 ast_mutex_lock(&iflock);
16601 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16602 if (dahdi_chan->channel != channel)
16603 continue;
16604
16605 /* Found the channel. Actually set it */
16606 if (override) {
16607 dahdi_chan->mwioverride_disposition = on;
16608 ast_cli(a->fd, "MWI '%s' queued for channel %d\n", on ? "enable" : "disable", channel);
16609 }
16610 dahdi_chan->mwioverride_active = override;
16611 /* The do_monitor thread will take care of actually sending the MWI
16612 * at an appropriate time for the channel. */
16613 break;
16614 }
16615 ast_mutex_unlock(&iflock);
16616
16617 if (!dahdi_chan) {
16618 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16619 return CLI_FAILURE;
16620 }
16621
16622 return CLI_SUCCESS;
16623 }
16624
16625 static struct ast_cli_entry dahdi_cli[] = {
16626 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
16627 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
16628 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
16629 AST_CLI_DEFINE(dahdi_destroy_channels, "Destroy channels"),
16630 AST_CLI_DEFINE(dahdi_create_channels, "Create channels"),
16631 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
16632 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
16633 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
16634 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
16635 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
16636 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
16637 AST_CLI_DEFINE(dahdi_set_mwi, "Sets/unsets MWI (Message Waiting Indicator) manually on a channel"),
16638 };
16639
16640 #define TRANSFER 0
16641 #define HANGUP 1
16642
16643 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
16644 {
16645 if (p) {
16646 switch (mode) {
16647 case TRANSFER:
16648 p->fake_event = DAHDI_EVENT_WINKFLASH;
16649 break;
16650 case HANGUP:
16651 p->fake_event = DAHDI_EVENT_ONHOOK;
16652 break;
16653 default:
16654 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));
16655 }
16656 }
16657 return 0;
16658 }
16659 static struct dahdi_pvt *find_channel(int channel)
16660 {
16661 struct dahdi_pvt *p;
16662
16663 ast_mutex_lock(&iflock);
16664 for (p = iflist; p; p = p->next) {
16665 if (p->channel == channel) {
16666 break;
16667 }
16668 }
16669 ast_mutex_unlock(&iflock);
16670 return p;
16671 }
16672
16673 /*!
16674 * \internal
16675 * \brief Get private struct using given numeric channel string.
16676 *
16677 * \param channel Numeric channel number string get private struct.
16678 *
16679 * \retval pvt on success.
16680 * \retval NULL on error.
16681 */
16682 static struct dahdi_pvt *find_channel_from_str(const char *channel)
16683 {
16684 int chan_num;
16685
16686 if (sscanf(channel, "%30d", &chan_num) != 1) {
16687 /* Not numeric string. */
16688 return NULL;
16689 }
16690
16691 return find_channel(chan_num);
16692 }
16693
16694 static int action_dahdidndon(struct mansession *s, const struct message *m)
16695 {
16696 struct dahdi_pvt *p;
16697 const char *channel = astman_get_header(m, "DAHDIChannel");
16698
16699 if (ast_strlen_zero(channel)) {
16700 astman_send_error(s, m, "No channel specified");
16701 return 0;
16702 }
16703 p = find_channel_from_str(channel);
16704 if (!p) {
16705 astman_send_error(s, m, "No such channel");
16706 return 0;
16707 }
16708 dahdi_dnd(p, 1);
16709 astman_send_ack(s, m, "DND Enabled");
16710 return 0;
16711 }
16712
16713 static int action_dahdidndoff(struct mansession *s, const struct message *m)
16714 {
16715 struct dahdi_pvt *p;
16716 const char *channel = astman_get_header(m, "DAHDIChannel");
16717
16718 if (ast_strlen_zero(channel)) {
16719 astman_send_error(s, m, "No channel specified");
16720 return 0;
16721 }
16722 p = find_channel_from_str(channel);
16723 if (!p) {
16724 astman_send_error(s, m, "No such channel");
16725 return 0;
16726 }
16727 dahdi_dnd(p, 0);
16728 astman_send_ack(s, m, "DND Disabled");
16729 return 0;
16730 }
16731
16732 static int action_transfer(struct mansession *s, const struct message *m)
16733 {
16734 struct dahdi_pvt *p;
16735 const char *channel = astman_get_header(m, "DAHDIChannel");
16736
16737 if (ast_strlen_zero(channel)) {
16738 astman_send_error(s, m, "No channel specified");
16739 return 0;
16740 }
16741 p = find_channel_from_str(channel);
16742 if (!p) {
16743 astman_send_error(s, m, "No such channel");
16744 return 0;
16745 }
16746 if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16747 astman_send_error(s, m, "Channel signaling is not analog");
16748 return 0;
16749 }
16750 dahdi_fake_event(p,TRANSFER);
16751 astman_send_ack(s, m, "DAHDITransfer");
16752 return 0;
16753 }
16754
16755 static int action_transferhangup(struct mansession *s, const struct message *m)
16756 {
16757 struct dahdi_pvt *p;
16758 const char *channel = astman_get_header(m, "DAHDIChannel");
16759
16760 if (ast_strlen_zero(channel)) {
16761 astman_send_error(s, m, "No channel specified");
16762 return 0;
16763 }
16764 p = find_channel_from_str(channel);
16765 if (!p) {
16766 astman_send_error(s, m, "No such channel");
16767 return 0;
16768 }
16769 if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16770 astman_send_error(s, m, "Channel signaling is not analog");
16771 return 0;
16772 }
16773 dahdi_fake_event(p,HANGUP);
16774 astman_send_ack(s, m, "DAHDIHangup");
16775 return 0;
16776 }
16777
16778 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16779 {
16780 struct dahdi_pvt *p;
16781 const char *channel = astman_get_header(m, "DAHDIChannel");
16782 const char *number = astman_get_header(m, "Number");
16783 int i;
16784
16785 if (ast_strlen_zero(channel)) {
16786 astman_send_error(s, m, "No channel specified");
16787 return 0;
16788 }
16789 if (ast_strlen_zero(number)) {
16790 astman_send_error(s, m, "No number specified");
16791 return 0;
16792 }
16793 p = find_channel_from_str(channel);
16794 if (!p) {
16795 astman_send_error(s, m, "No such channel");
16796 return 0;
16797 }
16798 if (!p->owner) {
16799 astman_send_error(s, m, "Channel does not have it's owner");
16800 return 0;
16801 }
16802 for (i = 0; i < strlen(number); i++) {
16803 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16804 dahdi_queue_frame(p, &f);
16805 }
16806 astman_send_ack(s, m, "DAHDIDialOffhook");
16807 return 0;
16808 }
16809
16810 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16811 {
16812 struct dahdi_pvt *tmp = NULL;
16813 const char *id = astman_get_header(m, "ActionID");
16814 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16815 char idText[256];
16816 int channels = 0;
16817 int dahdichanquery;
16818
16819 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16820 /* Not numeric string. */
16821 dahdichanquery = -1;
16822 }
16823
16824 idText[0] = '\0';
16825 if (!ast_strlen_zero(id)) {
16826 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16827 }
16828
16829 astman_send_listack(s, m, "DAHDI channel status will follow", "start");
16830
16831 ast_mutex_lock(&iflock);
16832
16833 for (tmp = iflist; tmp; tmp = tmp->next) {
16834 if (tmp->channel > 0) {
16835 int alm;
16836
16837 /* If a specific channel is queried for, only deliver status for that channel */
16838 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16839 continue;
16840
16841 alm = get_alarms(tmp);
16842 channels++;
16843 if (tmp->owner) {
16844 /* Add data if we have a current call */
16845 astman_append(s,
16846 "Event: DAHDIShowChannels\r\n"
16847 "DAHDIChannel: %d\r\n"
16848 "Channel: %s\r\n"
16849 "Uniqueid: %s\r\n"
16850 "AccountCode: %s\r\n"
16851 "Signalling: %s\r\n"
16852 "SignallingCode: %d\r\n"
16853 "Context: %s\r\n"
16854 "DND: %s\r\n"
16855 "Alarm: %s\r\n"
16856 "Description: %s\r\n"
16857 "%s"
16858 "\r\n",
16859 tmp->channel,
16860 ast_channel_name(tmp->owner),
16861 ast_channel_uniqueid(tmp->owner),
16862 ast_channel_accountcode(tmp->owner),
16863 sig2str(tmp->sig),
16864 tmp->sig,
16865 tmp->context,
16866 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16867 alarm2str(alm),
16868 tmp->description, idText);
16869 } else {
16870 astman_append(s,
16871 "Event: DAHDIShowChannels\r\n"
16872 "DAHDIChannel: %d\r\n"
16873 "Signalling: %s\r\n"
16874 "SignallingCode: %d\r\n"
16875 "Context: %s\r\n"
16876 "DND: %s\r\n"
16877 "Alarm: %s\r\n"
16878 "Description: %s\r\n"
16879 "%s"
16880 "\r\n",
16881 tmp->channel, sig2str(tmp->sig), tmp->sig,
16882 tmp->context,
16883 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16884 alarm2str(alm),
16885 tmp->description, idText);
16886 }
16887 }
16888 }
16889
16890 ast_mutex_unlock(&iflock);
16891
16892 astman_send_list_complete_start(s, m, "DAHDIShowChannelsComplete", channels);
16893 astman_append(s, "Items: %d\r\n", channels);
16894 astman_send_list_complete_end(s);
16895 return 0;
16896 }
16897
16898 #if defined(HAVE_PRI)
16899 static int action_prishowspans(struct mansession *s, const struct message *m)
16900 {
16901 int count;
16902 int idx;
16903 int span_query;
16904 struct dahdi_pri *dspan;
16905 const char *id = astman_get_header(m, "ActionID");
16906 const char *span_str = astman_get_header(m, "Span");
16907 char action_id[256];
16908 const char *show_cmd = "PRIShowSpans";
16909
16910 /* NOTE: Asking for span 0 gets all spans. */
16911 if (!ast_strlen_zero(span_str)) {
16912 span_query = atoi(span_str);
16913 } else {
16914 span_query = 0;
16915 }
16916
16917 if (!ast_strlen_zero(id)) {
16918 snprintf(action_id, sizeof(action_id), "ActionID: %s\r\n", id);
16919 } else {
16920 action_id[0] = '\0';
16921 }
16922
16923 astman_send_listack(s, m, "Span status will follow", "start");
16924
16925 count = 0;
16926 for (idx = 0; idx < ARRAY_LEN(pris); ++idx) {
16927 dspan = &pris[idx];
16928
16929 /* If a specific span is asked for, only deliver status for that span. */
16930 if (0 < span_query && dspan->pri.span != span_query) {
16931 continue;
16932 }
16933
16934 if (dspan->pri.pri) {
16935 count += sig_pri_ami_show_spans(s, show_cmd, &dspan->pri, dspan->dchannels,
16936 action_id);
16937 }
16938 }
16939
16940 astman_send_list_complete_start(s, m, "PRIShowSpansComplete", count);
16941 astman_append(s, "Items: %d\r\n", count);
16942 astman_send_list_complete_end(s);
16943 return 0;
16944 }
16945 #endif /* defined(HAVE_PRI) */
16946
16947 #if defined(HAVE_SS7)
16948 static int linkset_addsigchan(int sigchan)
16949 {
16950 struct dahdi_ss7 *link;
16951 int res;
16952 int curfd;
16953 struct dahdi_params params;
16954 struct dahdi_bufferinfo bi;
16955 struct dahdi_spaninfo si;
16956
16957 if (sigchan < 0) {
16958 ast_log(LOG_ERROR, "Invalid sigchan!\n");
16959 return -1;
16960 }
16961 if (cur_ss7type < 0) {
16962 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16963 return -1;
16964 }
16965 if (cur_pointcode < 0) {
16966 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16967 return -1;
16968 }
16969 if (cur_adjpointcode < 0) {
16970 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16971 return -1;
16972 }
16973 if (cur_defaultdpc < 0) {
16974 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16975 return -1;
16976 }
16977 if (cur_networkindicator < 0) {
16978 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16979 return -1;
16980 }
16981 link = ss7_resolve_linkset(cur_linkset);
16982 if (!link) {
16983 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16984 return -1;
16985 }
16986 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16987 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16988 return -1;
16989 }
16990
16991 curfd = link->ss7.numsigchans;
16992
16993 /* Open signaling channel */
16994 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16995 if (link->ss7.fds[curfd] < 0) {
16996 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16997 strerror(errno));
16998 return -1;
16999 }
17000 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
17001 dahdi_close_ss7_fd(link, curfd);
17002 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
17003 strerror(errno));
17004 return -1;
17005 }
17006
17007 /* Get signaling channel parameters */
17008 memset(&params, 0, sizeof(params));
17009 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
17010 if (res) {
17011 dahdi_close_ss7_fd(link, curfd);
17012 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
17013 strerror(errno));
17014 return -1;
17015 }
17016 if (params.sigtype != DAHDI_SIG_HDLCFCS
17017 && params.sigtype != DAHDI_SIG_HARDHDLC
17018 && params.sigtype != DAHDI_SIG_MTP2) {
17019 dahdi_close_ss7_fd(link, curfd);
17020 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
17021 return -1;
17022 }
17023
17024 /* Set signaling channel buffer policy. */
17025 memset(&bi, 0, sizeof(bi));
17026 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
17027 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
17028 bi.numbufs = 32;
17029 bi.bufsize = 512;
17030 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
17031 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
17032 sigchan, strerror(errno));
17033 dahdi_close_ss7_fd(link, curfd);
17034 return -1;
17035 }
17036
17037 /* Get current signaling channel alarm status. */
17038 memset(&si, 0, sizeof(si));
17039 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
17040 if (res) {
17041 dahdi_close_ss7_fd(link, curfd);
17042 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
17043 strerror(errno));
17044 }
17045
17046 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
17047 (params.sigtype == DAHDI_SIG_MTP2)
17048 ? SS7_TRANSPORT_DAHDIMTP2
17049 : SS7_TRANSPORT_DAHDIDCHAN,
17050 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode, cur_slc);
17051 if (res) {
17052 dahdi_close_ss7_fd(link, curfd);
17053 return -1;
17054 }
17055
17056 ++link->ss7.numsigchans;
17057
17058 return 0;
17059 }
17060 #endif /* defined(HAVE_SS7) */
17061
17062 #if defined(HAVE_SS7)
17063 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17064 {
17065 int span;
17066 switch (cmd) {
17067 case CLI_INIT:
17068 e->command = "ss7 set debug {on|off} linkset";
17069 e->usage =
17070 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
17071 " Enables debugging on a given SS7 linkset\n";
17072 return NULL;
17073 case CLI_GENERATE:
17074 return NULL;
17075 }
17076
17077 if (a->argc < 6) {
17078 return CLI_SHOWUSAGE;
17079 }
17080
17081 span = atoi(a->argv[5]);
17082 if ((span < 1) || (span > NUM_SPANS)) {
17083 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
17084 return CLI_SUCCESS;
17085 }
17086 if (!linksets[span-1].ss7.ss7) {
17087 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
17088 } else {
17089 if (!strcasecmp(a->argv[3], "on")) {
17090 linksets[span - 1].ss7.debug = 1;
17091 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
17092 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
17093 } else {
17094 linksets[span - 1].ss7.debug = 0;
17095 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
17096 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
17097 }
17098 }
17099
17100 return CLI_SUCCESS;
17101 }
17102 #endif /* defined(HAVE_SS7) */
17103
17104 #if defined(HAVE_SS7)
17105 static char *handle_ss7_cic_blocking(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17106 {
17107 int linkset, cic;
17108 int blocked, i;
17109 int do_block = 0;
17110 unsigned int dpc;
17111
17112 switch (cmd) {
17113 case CLI_INIT:
17114 e->command = "ss7 {block|unblock} cic";
17115 e->usage =
17116 "Usage: ss7 {block|unblock} cic <linkset> <dpc> <CIC>\n"
17117 " Sends a remote {blocking|unblocking} request for the given CIC on the specified linkset\n";
17118 return NULL;
17119 case CLI_GENERATE:
17120 return NULL;
17121 }
17122
17123 if (a->argc == 6) {
17124 linkset = atoi(a->argv[3]);
17125 } else {
17126 return CLI_SHOWUSAGE;
17127 }
17128
17129 if (!strcasecmp(a->argv[1], "block")) {
17130 do_block = 1;
17131 } else if (strcasecmp(a->argv[1], "unblock")) {
17132 return CLI_SHOWUSAGE;
17133 }
17134
17135 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17136 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17137 return CLI_SUCCESS;
17138 }
17139
17140 if (!linksets[linkset-1].ss7.ss7) {
17141 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17142 return CLI_SUCCESS;
17143 }
17144
17145 cic = atoi(a->argv[5]);
17146 if (cic < 1) {
17147 ast_cli(a->fd, "Invalid CIC specified!\n");
17148 return CLI_SUCCESS;
17149 }
17150
17151 dpc = atoi(a->argv[4]);
17152 if (dpc < 1) {
17153 ast_cli(a->fd, "Invalid DPC specified!\n");
17154 return CLI_SUCCESS;
17155 }
17156
17157 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
17158 if (linksets[linkset-1].ss7.pvts[i] && linksets[linkset-1].ss7.pvts[i]->cic == cic && linksets[linkset-1].ss7.pvts[i]->dpc == dpc) {
17159 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
17160 if (!do_block ^ !(blocked & SS7_BLOCKED_MAINTENANCE)) {
17161 if (sig_ss7_cic_blocking(&linksets[linkset-1].ss7, do_block, i) < 0) {
17162 ast_cli(a->fd, "Unable to allocate new ss7call\n");
17163 } else {
17164 ast_cli(a->fd, "Sent %sblocking request for linkset %d on CIC %d DPC %d\n", (do_block) ? "" : "un", linkset, cic, dpc);
17165 }
17166 } else if (!do_block && blocked) {
17167 ast_cli(a->fd, "CIC %d is hardware locally blocked!\n", cic);
17168 } else {
17169 ast_cli(a->fd, "CIC %d %s locally blocked\n", cic, do_block ? "already" : "is not");
17170 }
17171 return CLI_SUCCESS;
17172 }
17173 }
17174
17175 ast_cli(a->fd, "Invalid CIC specified!\n");
17176 return CLI_SUCCESS;
17177 }
17178 #endif /* defined(HAVE_SS7) */
17179
17180 #if defined(HAVE_SS7)
17181 static char *handle_ss7_linkset_mng(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17182 {
17183 int linkset, i;
17184 enum {
17185 DO_BLOCK,
17186 DO_UNBLOCK,
17187 DO_RESET,
17188 } do_what;
17189
17190 switch (cmd) {
17191 case CLI_INIT:
17192 e->command = "ss7 {reset|block|unblock} linkset";
17193 e->usage =
17194 "Usage: ss7 {reset|block|unblock} linkset <linkset number>\n"
17195 " Sends a remote {reset|blocking|unblocking} request for all CICs on the given linkset\n";
17196 return NULL;
17197 case CLI_GENERATE:
17198 return NULL;
17199 }
17200
17201 if (a->argc == 4) {
17202 linkset = atoi(a->argv[3]);
17203 } else {
17204 return CLI_SHOWUSAGE;
17205 }
17206
17207 if (!strcasecmp(a->argv[1], "block")) {
17208 do_what = DO_BLOCK;
17209 } else if (!strcasecmp(a->argv[1], "unblock")) {
17210 do_what = DO_UNBLOCK;
17211 } else if (!strcasecmp(a->argv[1], "reset")) {
17212 do_what = DO_RESET;
17213 } else {
17214 return CLI_SHOWUSAGE;
17215 }
17216
17217 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17218 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17219 return CLI_SUCCESS;
17220 }
17221
17222 if (!linksets[linkset - 1].ss7.ss7) {
17223 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17224 return CLI_SUCCESS;
17225 }
17226
17227 for (i = 0; i < linksets[linkset - 1].ss7.numchans; i++) {
17228 /* XXX Should be done with GRS/CGB/CGU instead - see ss7_reset_linkset() */
17229 if (linksets[linkset - 1].ss7.pvts[i]) {
17230 switch (do_what) {
17231 case DO_BLOCK:
17232 case DO_UNBLOCK:
17233 if (sig_ss7_cic_blocking(&linksets[linkset - 1].ss7, do_what == DO_BLOCK, i)) {
17234 ast_cli(a->fd, "Sent remote %s request on CIC %d\n",
17235 (do_what == DO_BLOCK) ? "blocking" : "unblocking",
17236 linksets[linkset - 1].ss7.pvts[i]->cic);
17237 }
17238 break;
17239 case DO_RESET:
17240 if (sig_ss7_reset_cic(&linksets[linkset - 1].ss7,
17241 linksets[linkset - 1].ss7.pvts[i]->cic,
17242 linksets[linkset - 1].ss7.pvts[i]->dpc)) {
17243 ast_cli(a->fd, "Sent reset request on CIC %d\n",
17244 linksets[linkset - 1].ss7.pvts[i]->cic);
17245 }
17246 break;
17247 }
17248 }
17249 }
17250
17251 return CLI_SUCCESS;
17252 }
17253 #endif /* defined(HAVE_SS7) */
17254
17255 #if defined(HAVE_SS7)
17256 static char *handle_ss7_group_blocking(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17257 {
17258 int linkset, cic, range, chanpos;
17259 int i, dpc, orient = 0;
17260 int do_block = 0;
17261 unsigned char state[255];
17262
17263 switch (cmd) {
17264 case CLI_INIT:
17265 e->command = "ss7 {block|unblock} group";
17266 e->usage =
17267 "Usage: ss7 {block|unblock} group <linkset> <dpc> <1st. CIC> <range> [H]\n"
17268 " Sends a remote {blocking|unblocking} request for CIC range on the specified linkset\n";
17269 return NULL;
17270 case CLI_GENERATE:
17271 return NULL;
17272 }
17273
17274 if (a->argc == 7 || a->argc == 8) {
17275 linkset = atoi(a->argv[3]);
17276 } else {
17277 return CLI_SHOWUSAGE;
17278 }
17279
17280 if (!strcasecmp(a->argv[1], "block")) {
17281 do_block = 1;
17282 } else if (strcasecmp(a->argv[1], "unblock")) {
17283 return CLI_SHOWUSAGE;
17284 }
17285
17286 if (a->argc == 8) {
17287 if (!strcasecmp(a->argv[7], "H")) {
17288 orient = 1;
17289 } else {
17290 return CLI_SHOWUSAGE;
17291 }
17292 }
17293
17294 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17295 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
17296 return CLI_SUCCESS;
17297 }
17298
17299 if (!linksets[linkset-1].ss7.ss7) {
17300 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17301 return CLI_SUCCESS;
17302 }
17303
17304 cic = atoi(a->argv[5]);
17305 if (cic < 1) {
17306 ast_cli(a->fd, "Invalid CIC specified!\n");
17307 return CLI_SUCCESS;
17308 }
17309
17310 range = atoi(a->argv[6]);
17311 /* ITU-T Q.763 3.43 - range 0 is reserved, which makes a range of 2 CICs a minimum group */
17312 if (range < 1 || range > (linksets[linkset - 1].ss7.type == SS7_ANSI ? 24 : 31)) {
17313 ast_cli(a->fd, "Invalid range specified!\n");
17314 return CLI_SUCCESS;
17315 }
17316
17317 dpc = atoi(a->argv[4]);
17318 if (dpc < 1) {
17319 ast_cli(a->fd, "Invalid DPC specified!\n");
17320 return CLI_SUCCESS;
17321 }
17322
17323 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17324 if (!sig_ss7_find_cic_range(&linksets[linkset-1].ss7, cic, cic + range, dpc)) {
17325 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17326 ast_cli(a->fd, "Invalid CIC/RANGE\n");
17327 return CLI_SHOWUSAGE;
17328 }
17329
17330 memset(state, 0, sizeof(state));
17331 for (i = 0; i <= range; ++i) {
17332 state[i] = 1;
17333 }
17334
17335 /* We are guaranteed to find chanpos because of sig_ss7_find_cic_range() includes it. */
17336 chanpos = sig_ss7_find_cic(&linksets[linkset-1].ss7, cic, dpc);
17337 if (sig_ss7_group_blocking(&linksets[linkset-1].ss7, do_block, chanpos, cic + range, state, orient)) {
17338 ast_cli(a->fd, "Unable allocate new ss7call\n");
17339 } else {
17340 ast_cli(a->fd, "Sending remote%s %sblocking request linkset %d on CIC %d range %d\n",
17341 orient ? " hardware" : "", do_block ? "" : "un", linkset, cic, range);
17342 }
17343
17344 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17345
17346 /* Break poll on the linkset so it sends our messages */
17347 if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17348 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17349 }
17350 return CLI_SUCCESS;
17351 }
17352 #endif /* defined(HAVE_SS7) */
17353
17354 #if defined(HAVE_SS7)
17355 static char *handle_ss7_group_reset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17356 {
17357 int linkset, cic, range;
17358 unsigned int dpc;
17359
17360 switch (cmd) {
17361 case CLI_INIT:
17362 e->command = "ss7 reset group";
17363 e->usage =
17364 "Usage: ss7 reset group <linkset> <dpc> <1st CIC> <range>\n"
17365 " Send a GRS for the given CIC range on the specified linkset\n";
17366 return NULL;
17367 case CLI_GENERATE:
17368 return NULL;
17369 }
17370
17371 if (a->argc == 7) {
17372 linkset = atoi(a->argv[3]);
17373 } else {
17374 return CLI_SHOWUSAGE;
17375 }
17376
17377 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17378 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
17379 return CLI_SUCCESS;
17380 }
17381
17382 if (!linksets[linkset-1].ss7.ss7) {
17383 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17384 return CLI_SUCCESS;
17385 }
17386
17387 cic = atoi(a->argv[5]);
17388
17389 if (cic < 1) {
17390 ast_cli(a->fd, "Invalid CIC specified!\n");
17391 return CLI_SUCCESS;
17392 }
17393
17394 range = atoi(a->argv[6]);
17395 if (range < 1 || range > (linksets[linkset - 1].ss7.type == SS7_ANSI ? 24 : 31)) {
17396 ast_cli(a->fd, "Invalid range specified!\n");
17397 return CLI_SUCCESS;
17398 }
17399
17400 dpc = atoi(a->argv[4]);
17401 if (dpc < 1) {
17402 ast_cli(a->fd, "Invalid DPC specified!\n");
17403 return CLI_SUCCESS;
17404 }
17405
17406 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17407 if (!sig_ss7_find_cic_range(&linksets[linkset-1].ss7, cic, cic + range, dpc)) {
17408 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17409 ast_cli(a->fd, "Invalid CIC/RANGE\n");
17410 return CLI_SHOWUSAGE;
17411 }
17412
17413 if (sig_ss7_reset_group(&linksets[linkset-1].ss7, cic, dpc, range)) {
17414 ast_cli(a->fd, "Unable to allocate new ss7call\n");
17415 } else {
17416 ast_cli(a->fd, "GRS sent ... \n");
17417 }
17418
17419 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17420
17421 /* Break poll on the linkset so it sends our messages */
17422 if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17423 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17424 }
17425 return CLI_SUCCESS;
17426 }
17427 #endif /* defined(HAVE_SS7) */
17428
17429 #if defined(HAVE_SS7)
17430 static char *handle_ss7_show_calls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17431 {
17432 int linkset;
17433
17434 switch (cmd) {
17435 case CLI_INIT:
17436 e->command = "ss7 show calls";
17437 e->usage =
17438 "Usage: ss7 show calls <linkset>\n"
17439 " Show SS7 calls on the specified linkset\n";
17440 return NULL;
17441 case CLI_GENERATE:
17442 return NULL;
17443 }
17444
17445 if (a->argc == 4) {
17446 linkset = atoi(a->argv[3]);
17447 } else {
17448 return CLI_SHOWUSAGE;
17449 }
17450
17451 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17452 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17453 return CLI_SUCCESS;
17454 }
17455
17456 if (!linksets[linkset-1].ss7.ss7) {
17457 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17458 return CLI_SUCCESS;
17459 }
17460
17461 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17462 isup_show_calls(linksets[linkset-1].ss7.ss7, &ast_cli, a->fd);
17463 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17464
17465 return CLI_SUCCESS;
17466 }
17467 #endif /* defined(HAVE_SS7) */
17468
17469 #if defined(HAVE_SS7)
17470 static char *handle_ss7_reset_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17471 {
17472 int linkset, cic, res;
17473 unsigned int dpc;
17474
17475 switch (cmd) {
17476 case CLI_INIT:
17477 e->command = "ss7 reset cic";
17478 e->usage =
17479 "Usage: ss7 reset cic <linkset> <dpc> <CIC>\n"
17480 " Send a RSC for the given CIC on the specified linkset\n";
17481 return NULL;
17482 case CLI_GENERATE:
17483 return NULL;
17484 }
17485
17486 if (a->argc == 6) {
17487 linkset = atoi(a->argv[3]);
17488 } else {
17489 return CLI_SHOWUSAGE;
17490 }
17491
17492 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17493 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17494 return CLI_SUCCESS;
17495 }
17496
17497 if (!linksets[linkset-1].ss7.ss7) {
17498 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17499 return CLI_SUCCESS;
17500 }
17501
17502 cic = atoi(a->argv[5]);
17503
17504 if (cic < 1) {
17505 ast_cli(a->fd, "Invalid CIC specified!\n");
17506 return CLI_SUCCESS;
17507 }
17508
17509 dpc = atoi(a->argv[4]);
17510 if (dpc < 1) {
17511 ast_cli(a->fd, "Invalid DPC specified!\n");
17512 return CLI_SUCCESS;
17513 }
17514
17515 res = sig_ss7_reset_cic(&linksets[linkset-1].ss7, cic, dpc);
17516
17517 ast_cli(a->fd, "%s RSC for linkset %d on CIC %d DPC %d\n", res ? "Sent" : "Failed", linkset, cic, dpc);
17518
17519 return CLI_SUCCESS;
17520 }
17521 #endif /* defined(HAVE_SS7) */
17522
17523 #if defined(HAVE_SS7)
17524 static char *handle_ss7_net_mng(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17525 {
17526 int linkset;
17527 unsigned int slc;
17528 unsigned int arg = 0;
17529 const char *res;
17530
17531 switch (cmd) {
17532 case CLI_INIT:
17533 e->command = "ss7 mtp3";
17534 e->usage =
17535 "Usage: ss7 mtp3 <linkset> <slc> coo|coa|cbd|cba|eco|eca|tfp|tfa|lin|lun|lia|lua|lid|lfu <arg>\n"
17536 " Send a NET MNG message\n"
17537 " WARNING!!! WARNING!!! We are not a STP, just for testing/development purposes\n";
17538 return NULL;
17539 case CLI_GENERATE:
17540 return NULL;
17541 }
17542
17543 if (a->argc < 5) {
17544 return CLI_SHOWUSAGE;
17545 }
17546
17547 linkset = atoi(a->argv[2]);
17548 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17549 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[2], 1, NUM_SPANS);
17550 return CLI_SUCCESS;
17551 }
17552 if (!linksets[linkset-1].ss7.ss7) {
17553 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17554 return CLI_SUCCESS;
17555 }
17556
17557 slc = atoi(a->argv[3]);
17558
17559 if (a->argc == 6) {
17560 arg = atoi(a->argv[5]);
17561 }
17562
17563 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17564 res = mtp3_net_mng(linksets[linkset-1].ss7.ss7, slc, a->argv[4], arg);
17565 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17566
17567 /* Break poll on the linkset so it sends our messages */
17568 if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17569 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17570 }
17571
17572 ast_cli(a->fd, "%s", res);
17573
17574 return CLI_SUCCESS;
17575 }
17576 #endif /* defined(HAVE_SS7) */
17577
17578 #if defined(HAVE_SS7)
17579 static char *handle_ss7_mtp3_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17580 {
17581 int linkset;
17582 unsigned int slc = 0;
17583
17584 switch (cmd) {
17585 case CLI_INIT:
17586 e->command = "ss7 restart mtp3";
17587 e->usage =
17588 "Usage: ss7 restart mtp3 <linkset> <slc>\n"
17589 " Restart link\n";
17590 return NULL;
17591 case CLI_GENERATE:
17592 return NULL;
17593 }
17594
17595 if (a->argc < 5) {
17596 return CLI_SHOWUSAGE;
17597 }
17598
17599 linkset = atoi(a->argv[3]);
17600 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17601 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[2], 1, NUM_SPANS);
17602 return CLI_SUCCESS;
17603 }
17604 if (!linksets[linkset-1].ss7.ss7) {
17605 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17606 return CLI_SUCCESS;
17607 }
17608
17609 slc = atoi(a->argv[4]);
17610
17611 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17612 mtp3_init_restart(linksets[linkset-1].ss7.ss7, slc);
17613 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17614
17615 /* Break poll on the linkset so it sends our messages */
17616 if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17617 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17618 }
17619
17620 return CLI_SUCCESS;
17621 }
17622 #endif /* defined(HAVE_SS7) */
17623
17624 #if defined(HAVE_SS7)
17625 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17626 {
17627 int linkset;
17628 struct sig_ss7_linkset *ss7;
17629 switch (cmd) {
17630 case CLI_INIT:
17631 e->command = "ss7 show linkset";
17632 e->usage =
17633 "Usage: ss7 show linkset <span>\n"
17634 " Shows the status of an SS7 linkset.\n";
17635 return NULL;
17636 case CLI_GENERATE:
17637 return NULL;
17638 }
17639
17640 if (a->argc < 4) {
17641 return CLI_SHOWUSAGE;
17642 }
17643
17644 linkset = atoi(a->argv[3]);
17645 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17646 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17647 return CLI_SUCCESS;
17648 }
17649 ss7 = &linksets[linkset - 1].ss7;
17650 if (!ss7->ss7) {
17651 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17652 return CLI_SUCCESS;
17653 }
17654
17655 ast_cli(a->fd, "SS7 flags: 0x%x\n", ss7->flags);
17656 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
17657 ast_cli(a->fd, "SS7 calling nai: %i\n", ss7->calling_nai);
17658 ast_cli(a->fd, "SS7 called nai: %i\n", ss7->called_nai);
17659 ast_cli(a->fd, "SS7 nationalprefix: %s\n", ss7->nationalprefix);
17660 ast_cli(a->fd, "SS7 internationalprefix: %s\n", ss7->internationalprefix);
17661 ast_cli(a->fd, "SS7 unknownprefix: %s\n", ss7->unknownprefix);
17662 ast_cli(a->fd, "SS7 networkroutedprefix: %s\n", ss7->networkroutedprefix);
17663 ast_cli(a->fd, "SS7 subscriberprefix: %s\n", ss7->subscriberprefix);
17664 ss7_show_linkset(ss7->ss7, &ast_cli, a->fd);
17665
17666 return CLI_SUCCESS;
17667 }
17668 #endif /* defined(HAVE_SS7) */
17669
17670 #if defined(HAVE_SS7)
17671 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17672 {
17673 int linkset;
17674
17675 switch (cmd) {
17676 case CLI_INIT:
17677 e->command = "ss7 show channels";
17678 e->usage =
17679 "Usage: ss7 show channels\n"
17680 " Displays SS7 channel information at a glance.\n";
17681 return NULL;
17682 case CLI_GENERATE:
17683 return NULL;
17684 }
17685
17686 if (a->argc != 3) {
17687 return CLI_SHOWUSAGE;
17688 }
17689
17690 sig_ss7_cli_show_channels_header(a->fd);
17691 for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
17692 if (linksets[linkset].ss7.ss7) {
17693 sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
17694 }
17695 }
17696 return CLI_SUCCESS;
17697 }
17698 #endif /* defined(HAVE_SS7) */
17699
17700 #if defined(HAVE_SS7)
17701 static char *handle_ss7_show_cics(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17702 {
17703 #define FORMAT "%5s %5s %6s %12s %-12s\n"
17704 #define FORMAT2 "%5i %5i %6i %12s %-12s\n"
17705 int i, linkset, dpc = 0;
17706 struct sig_ss7_linkset *ss7;
17707 char *state;
17708 char blocking[12];
17709
17710 switch (cmd) {
17711 case CLI_INIT:
17712 e->command = "ss7 show cics";
17713 e->usage =
17714 "Usage: ss7 show cics <linkset> [dpc]\n"
17715 " Shows the cics of an SS7 linkset.\n";
17716 return NULL;
17717 case CLI_GENERATE:
17718 return NULL;
17719 }
17720
17721 if (a->argc < 4 || a->argc > 5) {
17722 return CLI_SHOWUSAGE;
17723 }
17724
17725 linkset = atoi(a->argv[3]);
17726
17727 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17728 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17729 return CLI_SUCCESS;
17730 }
17731
17732 if (!linksets[linkset-1].ss7.ss7) {
17733 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17734 return CLI_SUCCESS;
17735 }
17736 ss7 = &linksets[linkset-1].ss7;
17737
17738 if (a->argc == 5) {
17739 dpc = atoi(a->argv[4]);
17740 if (dpc < 1) {
17741 ast_cli(a->fd, "Invalid DPC specified!\n");
17742 return CLI_SUCCESS;
17743 }
17744 }
17745
17746 ast_cli(a->fd, FORMAT, "CIC", "DPC", "DAHDI", "STATE", "BLOCKING");
17747
17748 for (i = 0; i < ss7->numchans; i++) {
17749 if (!dpc || (ss7->pvts[i] && ss7->pvts[i]->dpc == dpc)) {
17750 struct dahdi_pvt *p = ss7->pvts[i]->chan_pvt;
17751
17752 if (ss7->pvts[i]->owner) {
17753 state = "Used";
17754 } else if (ss7->pvts[i]->ss7call) {
17755 state = "Pending";
17756 } else if (!p->inservice) {
17757 state = "NotInServ";
17758 } else {
17759 state = "Idle";
17760 }
17761
17762 if (p->locallyblocked) {
17763 strcpy(blocking, "L:");
17764 if (p->locallyblocked & SS7_BLOCKED_MAINTENANCE) {
17765 strcat(blocking, "M");
17766 } else {
17767 strcat(blocking, " ");
17768 }
17769
17770 if (p->locallyblocked & SS7_BLOCKED_HARDWARE) {
17771 strcat(blocking, "H");
17772 } else {
17773 strcat(blocking, " ");
17774 }
17775 } else {
17776 strcpy(blocking, " ");
17777 }
17778
17779 if (p->remotelyblocked) {
17780 strcat(blocking, " R:");
17781 if (p->remotelyblocked & SS7_BLOCKED_MAINTENANCE) {
17782 strcat(blocking, "M");
17783 } else {
17784 strcat(blocking, " ");
17785 }
17786
17787 if (p->remotelyblocked & SS7_BLOCKED_HARDWARE) {
17788 strcat(blocking, "H");
17789 } else {
17790 strcat(blocking, " ");
17791 }
17792 }
17793
17794 ast_cli(a->fd, FORMAT2, ss7->pvts[i]->cic, ss7->pvts[i]->dpc, ss7->pvts[i]->channel, state, blocking);
17795 }
17796 }
17797
17798 return CLI_SUCCESS;
17799 #undef FORMAT
17800 #undef FORMAT2
17801 }
17802 #endif /* defined(HAVE_SS7) */
17803
17804 #if defined(HAVE_SS7)
17805 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17806 {
17807 switch (cmd) {
17808 case CLI_INIT:
17809 e->command = "ss7 show version";
17810 e->usage =
17811 "Usage: ss7 show version\n"
17812 " Show the libss7 version\n";
17813 return NULL;
17814 case CLI_GENERATE:
17815 return NULL;
17816 }
17817
17818 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
17819
17820 return CLI_SUCCESS;
17821 }
17822 #endif /* defined(HAVE_SS7) */
17823
17824 #if defined(HAVE_SS7)
17825 static struct ast_cli_entry dahdi_ss7_cli[] = {
17826 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
17827 AST_CLI_DEFINE(handle_ss7_cic_blocking, "Blocks/Unblocks the given CIC"),
17828 AST_CLI_DEFINE(handle_ss7_linkset_mng, "Resets/Blocks/Unblocks all CICs on a linkset"),
17829 AST_CLI_DEFINE(handle_ss7_group_blocking, "Blocks/Unblocks the given CIC range"),
17830 AST_CLI_DEFINE(handle_ss7_reset_cic, "Resets the given CIC"),
17831 AST_CLI_DEFINE(handle_ss7_group_reset, "Resets the given CIC range"),
17832 AST_CLI_DEFINE(handle_ss7_mtp3_restart, "Restart a link"),
17833 AST_CLI_DEFINE(handle_ss7_net_mng, "Send an NET MNG message"),
17834 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
17835 AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
17836 AST_CLI_DEFINE(handle_ss7_show_calls, "Show ss7 calls"),
17837 AST_CLI_DEFINE(handle_ss7_show_cics, "Show cics on a linkset"),
17838 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
17839 };
17840 #endif /* defined(HAVE_SS7) */
17841
17842 #if defined(HAVE_PRI)
17843 #if defined(HAVE_PRI_CCSS)
17844 /*!
17845 * \internal
17846 * \brief CC agent initialization.
17847 * \since 1.8
17848 *
17849 * \param agent CC core agent control.
17850 * \param chan Original channel the agent will attempt to recall.
17851 *
17852 * \details
17853 * This callback is called when the CC core is initialized. Agents should allocate
17854 * any private data necessary for the call and assign it to the private_data
17855 * on the agent. Additionally, if any ast_cc_agent_flags are pertinent to the
17856 * specific agent type, they should be set in this function as well.
17857 *
17858 * \retval 0 on success.
17859 * \retval -1 on error.
17860 */
17861 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
17862 {
17863 struct dahdi_pvt *pvt;
17864 struct sig_pri_chan *pvt_chan;
17865 int res;
17866
17867 ast_assert(!strcmp(ast_channel_tech(chan)->type, "DAHDI"));
17868
17869 pvt = ast_channel_tech_pvt(chan);
17870 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
17871 pvt_chan = pvt->sig_pvt;
17872 } else {
17873 pvt_chan = NULL;
17874 }
17875 if (!pvt_chan) {
17876 return -1;
17877 }
17878
17879 ast_module_ref(ast_module_info->self);
17880
17881 res = sig_pri_cc_agent_init(agent, pvt_chan);
17882 if (res) {
17883 ast_module_unref(ast_module_info->self);
17884 }
17885 return res;
17886 }
17887 #endif /* defined(HAVE_PRI_CCSS) */
17888 #endif /* defined(HAVE_PRI) */
17889
17890 #if defined(HAVE_PRI)
17891 #if defined(HAVE_PRI_CCSS)
17892 /*!
17893 * \internal
17894 * \brief Destroy private data on the agent.
17895 * \since 1.8
17896 *
17897 * \param agent CC core agent control.
17898 *
17899 * \details
17900 * The core will call this function upon completion
17901 * or failure of CC.
17902 */
17903 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
17904 {
17905 sig_pri_cc_agent_destructor(agent);
17906
17907 ast_module_unref(ast_module_info->self);
17908 }
17909 #endif /* defined(HAVE_PRI_CCSS) */
17910 #endif /* defined(HAVE_PRI) */
17911
17912 #if defined(HAVE_PRI)
17913 #if defined(HAVE_PRI_CCSS)
17914 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
17915 .type = dahdi_pri_cc_type,
17916 .init = dahdi_pri_cc_agent_init,
17917 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
17918 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
17919 .respond = sig_pri_cc_agent_req_rsp,
17920 .status_request = sig_pri_cc_agent_status_req,
17921 .stop_ringing = sig_pri_cc_agent_stop_ringing,
17922 .party_b_free = sig_pri_cc_agent_party_b_free,
17923 .start_monitoring = sig_pri_cc_agent_start_monitoring,
17924 .callee_available = sig_pri_cc_agent_callee_available,
17925 .destructor = dahdi_pri_cc_agent_destructor,
17926 };
17927 #endif /* defined(HAVE_PRI_CCSS) */
17928 #endif /* defined(HAVE_PRI) */
17929
17930 #if defined(HAVE_PRI)
17931 #if defined(HAVE_PRI_CCSS)
17932 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
17933 .type = dahdi_pri_cc_type,
17934 .request_cc = sig_pri_cc_monitor_req_cc,
17935 .suspend = sig_pri_cc_monitor_suspend,
17936 .unsuspend = sig_pri_cc_monitor_unsuspend,
17937 .status_response = sig_pri_cc_monitor_status_rsp,
17938 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
17939 .destructor = sig_pri_cc_monitor_destructor,
17940 };
17941 #endif /* defined(HAVE_PRI_CCSS) */
17942 #endif /* defined(HAVE_PRI) */
17943
17944 static int __unload_module(void)
17945 {
17946 struct dahdi_pvt *p;
17947 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17948 int i, j;
17949 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
17950
17951 #ifdef HAVE_PRI
17952 for (i = 0; i < NUM_SPANS; i++) {
17953 if (pris[i].pri.master != AST_PTHREADT_NULL) {
17954 pthread_cancel(pris[i].pri.master);
17955 pthread_kill(pris[i].pri.master, SIGURG);
17956 }
17957 }
17958 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17959 ast_unregister_application(dahdi_send_keypad_facility_app);
17960 #ifdef HAVE_PRI_PROG_W_CAUSE
17961 ast_unregister_application(dahdi_send_callrerouting_facility_app);
17962 #endif
17963 #endif
17964 #if defined(HAVE_SS7)
17965 for (i = 0; i < NUM_SPANS; i++) {
17966 if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
17967 pthread_cancel(linksets[i].ss7.master);
17968 pthread_kill(linksets[i].ss7.master, SIGURG);
17969 }
17970 }
17971 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17972 #endif /* defined(HAVE_SS7) */
17973 #if defined(HAVE_OPENR2)
17974 dahdi_r2_destroy_links();
17975 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
17976 ast_unregister_application(dahdi_accept_r2_call_app);
17977 #endif
17978
17979 ast_custom_function_unregister(&polarity_function);
17980
17981 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
17982 ast_manager_unregister("DAHDIDialOffhook");
17983 ast_manager_unregister("DAHDIHangup");
17984 ast_manager_unregister("DAHDITransfer");
17985 ast_manager_unregister("DAHDIDNDoff");
17986 ast_manager_unregister("DAHDIDNDon");
17987 ast_manager_unregister("DAHDIShowChannels");
17988 ast_manager_unregister("DAHDIRestart");
17989 #if defined(HAVE_PRI)
17990 ast_manager_unregister("PRIShowSpans");
17991 ast_manager_unregister("PRIDebugSet");
17992 ast_manager_unregister("PRIDebugFileSet");
17993 ast_manager_unregister("PRIDebugFileUnset");
17994 #endif /* defined(HAVE_PRI) */
17995 ast_channel_unregister(&dahdi_tech);
17996
17997 /* Hangup all interfaces if they have an owner */
17998 ast_mutex_lock(&iflock);
17999 for (p = iflist; p; p = p->next) {
18000 if (p->owner)
18001 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
18002 }
18003 ast_mutex_unlock(&iflock);
18004
18005 ast_mutex_lock(&monlock);
18006 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
18007 pthread_cancel(monitor_thread);
18008 pthread_kill(monitor_thread, SIGURG);
18009 pthread_join(monitor_thread, NULL);
18010 }
18011 monitor_thread = AST_PTHREADT_STOP;
18012 ast_mutex_unlock(&monlock);
18013
18014 destroy_all_channels();
18015
18016 #if defined(HAVE_PRI)
18017 for (i = 0; i < NUM_SPANS; i++) {
18018 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
18019 pthread_join(pris[i].pri.master, NULL);
18020 }
18021 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
18022 dahdi_close_pri_fd(&(pris[i]), j);
18023 }
18024 sig_pri_stop_pri(&pris[i].pri);
18025 }
18026 #if defined(HAVE_PRI_CCSS)
18027 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
18028 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
18029 #endif /* defined(HAVE_PRI_CCSS) */
18030 sig_pri_unload();
18031 #endif
18032
18033 #if defined(HAVE_SS7)
18034 for (i = 0; i < NUM_SPANS; i++) {
18035 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
18036 pthread_join(linksets[i].ss7.master, NULL);
18037 }
18038 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
18039 dahdi_close_ss7_fd(&(linksets[i]), j);
18040 }
18041 if (linksets[i].ss7.ss7) {
18042 ss7_destroy(linksets[i].ss7.ss7);
18043 linksets[i].ss7.ss7 = NULL;
18044 }
18045 }
18046 #endif /* defined(HAVE_SS7) */
18047 ast_cond_destroy(&ss_thread_complete);
18048
18049 dahdi_native_unload();
18050
18051 ao2_cleanup(dahdi_tech.capabilities);
18052 dahdi_tech.capabilities = NULL;
18053 STASIS_MESSAGE_TYPE_CLEANUP(dahdichannel_type);
18054 return 0;
18055 }
18056
18057 static int unload_module(void)
18058 {
18059 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18060 int y;
18061 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18062 #ifdef HAVE_PRI
18063 for (y = 0; y < NUM_SPANS; y++)
18064 ast_mutex_destroy(&pris[y].pri.lock);
18065 #endif
18066 #if defined(HAVE_SS7)
18067 for (y = 0; y < NUM_SPANS; y++)
18068 ast_mutex_destroy(&linksets[y].ss7.lock);
18069 #endif /* defined(HAVE_SS7) */
18070 return __unload_module();
18071 }
18072
18073 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno)
18074 {
18075 char *c, *chan;
18076 int x, start, finish;
18077 struct dahdi_pvt *tmp;
18078
18079 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
18080 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
18081 return -1;
18082 }
18083
18084 c = ast_strdupa(value);
18085
18086 while ((chan = strsep(&c, ","))) {
18087 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
18088 /* Range */
18089 } else if (sscanf(chan, "%30d", &start)) {
18090 /* Just one */
18091 finish = start;
18092 } else if (!strcasecmp(chan, "pseudo")) {
18093 finish = start = CHAN_PSEUDO;
18094 } else {
18095 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
18096 return -1;
18097 }
18098 if (finish < start) {
18099 ast_log(LOG_WARNING, "Silliness: %d < %d\n", start, finish);
18100 x = finish;
18101 finish = start;
18102 start = x;
18103 }
18104
18105 for (x = start; x <= finish; x++) {
18106 if (conf->wanted_channels_start &&
18107 (x < conf->wanted_channels_start ||
18108 x > conf->wanted_channels_end)
18109 ) {
18110 continue;
18111 }
18112 tmp = mkintf(x, conf, reload);
18113
18114 if (tmp) {
18115 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
18116 } else {
18117 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
18118 (reload == 1) ? "reconfigure" : "register", value);
18119 return -1;
18120 }
18121 if (x == CHAN_PSEUDO) {
18122 has_pseudo = 1;
18123 }
18124 }
18125 }
18126
18127 return 0;
18128 }
18129
18130 /** The length of the parameters list of 'dahdichan'.
18131 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
18132 #define MAX_CHANLIST_LEN 80
18133
18134 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
18135 {
18136 char *parse = ast_strdupa(data);
18137 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
18138 unsigned int param_count;
18139 unsigned int x;
18140
18141 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
18142 return;
18143
18144 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
18145
18146 /* first parameter is tap length, process it here */
18147
18148 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
18149
18150 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
18151 confp->chan.echocancel.head.tap_length = x;
18152 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
18153 confp->chan.echocancel.head.tap_length = 128;
18154
18155 /* now process any remaining parameters */
18156
18157 for (x = 1; x < param_count; x++) {
18158 struct {
18159 char *name;
18160 char *value;
18161 } param;
18162
18163 if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
18164 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]);
18165 continue;
18166 }
18167
18168 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
18169 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name);
18170 continue;
18171 }
18172
18173 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
18174
18175 if (param.value) {
18176 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
18177 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value);
18178 continue;
18179 }
18180 }
18181 confp->chan.echocancel.head.param_count++;
18182 }
18183 }
18184
18185 #if defined(HAVE_PRI)
18186 #if defined(HAVE_PRI_DISPLAY_TEXT)
18187 /*!
18188 * \internal
18189 * \brief Determine the configured display text options.
18190 * \since 10.0
18191 *
18192 * \param value Configuration value string.
18193 *
18194 * \return Configured display text option flags.
18195 */
18196 static unsigned long dahdi_display_text_option(const char *value)
18197 {
18198 char *val_str;
18199 char *opt_str;
18200 unsigned long options;
18201
18202 options = 0;
18203 val_str = ast_strdupa(value);
18204
18205 for (;;) {
18206 opt_str = strsep(&val_str, ",");
18207 if (!opt_str) {
18208 break;
18209 }
18210 opt_str = ast_strip(opt_str);
18211 if (!*opt_str) {
18212 continue;
18213 }
18214
18215 if (!strcasecmp(opt_str, "block")) {
18216 options |= PRI_DISPLAY_OPTION_BLOCK;
18217 } else if (!strcasecmp(opt_str, "name_initial")) {
18218 options |= PRI_DISPLAY_OPTION_NAME_INITIAL;
18219 } else if (!strcasecmp(opt_str, "name_update")) {
18220 options |= PRI_DISPLAY_OPTION_NAME_UPDATE;
18221 } else if (!strcasecmp(opt_str, "name")) {
18222 options |= (PRI_DISPLAY_OPTION_NAME_INITIAL | PRI_DISPLAY_OPTION_NAME_UPDATE);
18223 } else if (!strcasecmp(opt_str, "text")) {
18224 options |= PRI_DISPLAY_OPTION_TEXT;
18225 }
18226 }
18227 return options;
18228 }
18229 #endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
18230 #endif /* defined(HAVE_PRI) */
18231
18232 #if defined(HAVE_PRI)
18233 #if defined(HAVE_PRI_DATETIME_SEND)
18234 /*!
18235 * \internal
18236 * \brief Determine the configured date/time send policy option.
18237 * \since 10.0
18238 *
18239 * \param value Configuration value string.
18240 *
18241 * \return Configured date/time send policy option.
18242 */
18243 static int dahdi_datetime_send_option(const char *value)
18244 {
18245 int option;
18246
18247 option = PRI_DATE_TIME_SEND_DEFAULT;
18248
18249 if (ast_false(value)) {
18250 option = PRI_DATE_TIME_SEND_NO;
18251 } else if (!strcasecmp(value, "date")) {
18252 option = PRI_DATE_TIME_SEND_DATE;
18253 } else if (!strcasecmp(value, "date_hh")) {
18254 option = PRI_DATE_TIME_SEND_DATE_HH;
18255 } else if (!strcasecmp(value, "date_hhmm")) {
18256 option = PRI_DATE_TIME_SEND_DATE_HHMM;
18257 } else if (!strcasecmp(value, "date_hhmmss")) {
18258 option = PRI_DATE_TIME_SEND_DATE_HHMMSS;
18259 }
18260
18261 return option;
18262 }
18263 #endif /* defined(HAVE_PRI_DATETIME_SEND) */
18264 #endif /* defined(HAVE_PRI) */
18265
18266 /*! process_dahdi() - ignore keyword 'channel' and similar */
18267 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
18268 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
18269 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
18270
18271 static void parse_busy_pattern(struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
18272 {
18273 int count_pattern = 0;
18274 int norval = 0;
18275 char *temp = NULL;
18276
18277 for (; ;) {
18278 /* Scans the string for the next value in the pattern. If none, it checks to see if any have been entered so far. */
18279 if (!sscanf(v->value, "%30d", &norval) && count_pattern == 0) {
18280 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
18281 break;
18282 }
18283
18284 busy_cadence->pattern[count_pattern] = norval;
18285
18286 count_pattern++;
18287 if (count_pattern == 4) {
18288 break;
18289 }
18290
18291 temp = strchr(v->value, ',');
18292 if (temp == NULL) {
18293 break;
18294 }
18295 v->value = temp + 1;
18296 }
18297 busy_cadence->length = count_pattern;
18298
18299 if (count_pattern % 2 != 0) {
18300 /* The pattern length must be divisible by two */
18301 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
18302 }
18303
18304 }
18305
18306 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
18307 {
18308 struct dahdi_pvt *tmp;
18309 int y;
18310 struct ast_variable *dahdichan = NULL;
18311
18312 /* Re-parse any cadences from beginning, rather than appending until we run out of room */
18313 user_has_defined_cadences = 0;
18314
18315 for (; v; v = v->next) {
18316 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
18317 continue;
18318
18319 /* Create the interface list */
18320 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
18321 if (options & PROC_DAHDI_OPT_NOCHAN) {
18322 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
18323 continue;
18324 }
18325 if (build_channels(confp, v->value, reload, v->lineno)) {
18326 if (confp->ignore_failed_channels) {
18327 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
18328 continue;
18329 } else {
18330 return -1;
18331 }
18332 }
18333 ast_debug(1, "Channel '%s' configured.\n", v->value);
18334 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
18335 confp->ignore_failed_channels = ast_true(v->value);
18336 } else if (!strcasecmp(v->name, "buffers")) {
18337 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
18338 ast_log(LOG_WARNING, "Using default buffer policy.\n");
18339 confp->chan.buf_no = numbufs;
18340 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
18341 }
18342 } else if (!strcasecmp(v->name, "faxbuffers")) {
18343 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
18344 confp->chan.usefaxbuffers = 1;
18345 }
18346 } else if (!strcasecmp(v->name, "dahdichan")) {
18347 /* Only process the last dahdichan value. */
18348 dahdichan = v;
18349 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
18350 usedistinctiveringdetection = ast_true(v->value);
18351 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
18352 distinctiveringaftercid = ast_true(v->value);
18353 } else if (!strcasecmp(v->name, "dring1context")) {
18354 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
18355 } else if (!strcasecmp(v->name, "dring2context")) {
18356 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
18357 } else if (!strcasecmp(v->name, "dring3context")) {
18358 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
18359 } else if (!strcasecmp(v->name, "dring1range")) {
18360 confp->chan.drings.ringnum[0].range = atoi(v->value);
18361 } else if (!strcasecmp(v->name, "dring2range")) {
18362 confp->chan.drings.ringnum[1].range = atoi(v->value);
18363 } else if (!strcasecmp(v->name, "dring3range")) {
18364 confp->chan.drings.ringnum[2].range = atoi(v->value);
18365 } else if (!strcasecmp(v->name, "dring1")) {
18366 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]);
18367 } else if (!strcasecmp(v->name, "dring2")) {
18368 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]);
18369 } else if (!strcasecmp(v->name, "dring3")) {
18370 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]);
18371 } else if (!strcasecmp(v->name, "usecallerid")) {
18372 confp->chan.use_callerid = ast_true(v->value);
18373 } else if (!strcasecmp(v->name, "cidsignalling")) {
18374 if (!strcasecmp(v->value, "bell"))
18375 confp->chan.cid_signalling = CID_SIG_BELL;
18376 else if (!strcasecmp(v->value, "v23"))
18377 confp->chan.cid_signalling = CID_SIG_V23;
18378 else if (!strcasecmp(v->value, "dtmf"))
18379 confp->chan.cid_signalling = CID_SIG_DTMF;
18380 else if (!strcasecmp(v->value, "smdi"))
18381 confp->chan.cid_signalling = CID_SIG_SMDI;
18382 else if (!strcasecmp(v->value, "v23_jp"))
18383 confp->chan.cid_signalling = CID_SIG_V23_JP;
18384 else if (ast_true(v->value))
18385 confp->chan.cid_signalling = CID_SIG_BELL;
18386 } else if (!strcasecmp(v->name, "cidstart")) {
18387 if (!strcasecmp(v->value, "ring"))
18388 confp->chan.cid_start = CID_START_RING;
18389 else if (!strcasecmp(v->value, "polarity_in"))
18390 confp->chan.cid_start = CID_START_POLARITY_IN;
18391 else if (!strcasecmp(v->value, "polarity"))
18392 confp->chan.cid_start = CID_START_POLARITY;
18393 else if (!strcasecmp(v->value, "dtmf"))
18394 confp->chan.cid_start = CID_START_DTMF_NOALERT;
18395 else if (ast_true(v->value))
18396 confp->chan.cid_start = CID_START_RING;
18397 } else if (!strcasecmp(v->name, "threewaycalling")) {
18398 confp->chan.threewaycalling = ast_true(v->value);
18399 } else if (!strcasecmp(v->name, "threewaysilenthold")) {
18400 confp->chan.threewaysilenthold = ast_true(v->value);
18401 } else if (!strcasecmp(v->name, "cancallforward")) {
18402 confp->chan.cancallforward = ast_true(v->value);
18403 } else if (!strcasecmp(v->name, "relaxdtmf")) {
18404 if (ast_true(v->value))
18405 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
18406 else
18407 confp->chan.dtmfrelax = 0;
18408 } else if (!strcasecmp(v->name, "mailbox")) {
18409 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
18410 } else if (!strcasecmp(v->name, "description")) {
18411 ast_copy_string(confp->chan.description, v->value, sizeof(confp->chan.description));
18412 } else if (!strcasecmp(v->name, "hasvoicemail")) {
18413 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
18414 /*
18415 * hasvoicemail is a users.conf legacy voicemail enable method.
18416 * hasvoicemail is only going to work for app_voicemail mailboxes.
18417 */
18418 if (strchr(cat, '@')) {
18419 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
18420 } else {
18421 snprintf(confp->chan.mailbox, sizeof(confp->chan.mailbox),
18422 "%s@default", cat);
18423 }
18424 }
18425 } else if (!strcasecmp(v->name, "adsi")) {
18426 confp->chan.adsi = ast_true(v->value);
18427 } else if (!strcasecmp(v->name, "usesmdi")) {
18428 confp->chan.use_smdi = ast_true(v->value);
18429 } else if (!strcasecmp(v->name, "smdiport")) {
18430 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
18431 } else if (!strcasecmp(v->name, "transfer")) {
18432 confp->chan.transfer = ast_true(v->value);
18433 } else if (!strcasecmp(v->name, "canpark")) {
18434 confp->chan.canpark = ast_true(v->value);
18435 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
18436 confp->chan.echocanbridged = ast_true(v->value);
18437 } else if (!strcasecmp(v->name, "busydetect")) {
18438 confp->chan.busydetect = ast_true(v->value);
18439 } else if (!strcasecmp(v->name, "busycount")) {
18440 confp->chan.busycount = atoi(v->value);
18441 } else if (!strcasecmp(v->name, "busypattern")) {
18442 parse_busy_pattern(v, &confp->chan.busy_cadence);
18443 } else if (!strcasecmp(v->name, "calledsubscriberheld")) {
18444 confp->chan.calledsubscriberheld = ast_true(v->value);
18445 } else if (!strcasecmp(v->name, "callprogress")) {
18446 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
18447 if (ast_true(v->value))
18448 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
18449 } else if (!strcasecmp(v->name, "waitfordialtone")) {
18450 confp->chan.waitfordialtone = atoi(v->value);
18451 } else if (!strcasecmp(v->name, "dialtone_detect")) {
18452 if (!strcasecmp(v->value, "always")) {
18453 confp->chan.dialtone_detect = -1;
18454 } else if (ast_true(v->value)) {
18455 confp->chan.dialtone_detect = DEFAULT_DIALTONE_DETECT_TIMEOUT;
18456 } else if (ast_false(v->value)) {
18457 confp->chan.dialtone_detect = 0;
18458 } else {
18459 confp->chan.dialtone_detect = ast_strlen_zero(v->value) ? 0 : (8 * atoi(v->value)) / READ_SIZE;
18460 }
18461 } else if (!strcasecmp(v->name, "faxdetect")) {
18462 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
18463 if (!strcasecmp(v->value, "incoming")) {
18464 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
18465 } else if (!strcasecmp(v->value, "outgoing")) {
18466 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
18467 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
18468 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
18469 } else if (!strcasecmp(v->name, "faxdetect_timeout")) {
18470 if (sscanf(v->value, "%30u", &confp->chan.faxdetect_timeout) != 1) {
18471 confp->chan.faxdetect_timeout = 0;
18472 }
18473 } else if (!strcasecmp(v->name, "firstdigit_timeout")) {
18474 if (sscanf(v->value, "%30d", &confp->chan.firstdigit_timeout) != 1
18475 || confp->chan.firstdigit_timeout <= 0) {
18476 confp->chan.firstdigit_timeout = ANALOG_FIRST_DIGIT_TIMEOUT;
18477 }
18478 } else if (!strcasecmp(v->name, "interdigit_timeout")) {
18479 if (sscanf(v->value, "%30d", &confp->chan.interdigit_timeout) != 1
18480 || confp->chan.interdigit_timeout <= 0) {
18481 confp->chan.interdigit_timeout = ANALOG_INTER_DIGIT_TIMEOUT;
18482 }
18483 } else if (!strcasecmp(v->name, "matchdigit_timeout")) {
18484 if (sscanf(v->value, "%30d", &confp->chan.matchdigit_timeout) != 1
18485 || confp->chan.matchdigit_timeout <= 0) {
18486 confp->chan.matchdigit_timeout = ANALOG_MATCH_DIGIT_TIMEOUT;
18487 }
18488 } else if (!strcasecmp(v->name, "echocancel")) {
18489 process_echocancel(confp, v->value, v->lineno);
18490 } else if (!strcasecmp(v->name, "echotraining")) {
18491 if (sscanf(v->value, "%30d", &y) == 1) {
18492 if ((y < 10) || (y > 4000)) {
18493 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
18494 } else {
18495 confp->chan.echotraining = y;
18496 }
18497 } else if (ast_true(v->value)) {
18498 confp->chan.echotraining = 400;
18499 } else
18500 confp->chan.echotraining = 0;
18501 } else if (!strcasecmp(v->name, "hidecallerid")) {
18502 confp->chan.hidecallerid = ast_true(v->value);
18503 } else if (!strcasecmp(v->name, "hidecalleridname")) {
18504 confp->chan.hidecalleridname = ast_true(v->value);
18505 } else if (!strcasecmp(v->name, "pulsedial")) {
18506 confp->chan.pulse = ast_true(v->value);
18507 } else if (!strcasecmp(v->name, "callreturn")) {
18508 confp->chan.callreturn = ast_true(v->value);
18509 } else if (!strcasecmp(v->name, "callwaiting")) {
18510 confp->chan.callwaiting = ast_true(v->value);
18511 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
18512 confp->chan.callwaitingcallerid = ast_true(v->value);
18513 } else if (!strcasecmp(v->name, "context")) {
18514 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
18515 } else if (!strcasecmp(v->name, "language")) {
18516 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
18517 } else if (!strcasecmp(v->name, "progzone")) {
18518 ast_copy_string(progzone, v->value, sizeof(progzone));
18519 } else if (!strcasecmp(v->name, "mohinterpret")
18520 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
18521 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
18522 } else if (!strcasecmp(v->name, "mohsuggest")) {
18523 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
18524 } else if (!strcasecmp(v->name, "parkinglot")) {
18525 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
18526 } else if (!strcasecmp(v->name, "stripmsd")) {
18527 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
18528 confp->chan.stripmsd = atoi(v->value);
18529 } else if (!strcasecmp(v->name, "jitterbuffers")) {
18530 numbufs = atoi(v->value);
18531 } else if (!strcasecmp(v->name, "group")) {
18532 confp->chan.group = ast_get_group(v->value);
18533 } else if (!strcasecmp(v->name, "callgroup")) {
18534 if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18535 ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a call group\n");
18536 }
18537 if (!strcasecmp(v->value, "none"))
18538 confp->chan.callgroup = 0;
18539 else
18540 confp->chan.callgroup = ast_get_group(v->value);
18541 } else if (!strcasecmp(v->name, "pickupgroup")) {
18542 if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18543 ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a pickup group\n");
18544 }
18545 if (!strcasecmp(v->value, "none"))
18546 confp->chan.pickupgroup = 0;
18547 else
18548 confp->chan.pickupgroup = ast_get_group(v->value);
18549 } else if (!strcasecmp(v->name, "namedcallgroup")) {
18550 if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18551 ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a named call group\n");
18552 }
18553 confp->chan.named_callgroups = ast_get_namedgroups(v->value);
18554 } else if (!strcasecmp(v->name, "namedpickupgroup")) {
18555 if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18556 ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a named pickup group\n");
18557 }
18558 confp->chan.named_pickupgroups = ast_get_namedgroups(v->value);
18559 } else if (!strcasecmp(v->name, "setvar")) {
18560 if (v->value) {
18561 char *varval = NULL;
18562 struct ast_variable *tmpvar;
18563 char varname[strlen(v->value) + 1];
18564 strcpy(varname, v->value); /* safe */
18565 if ((varval = strchr(varname, '='))) {
18566 *varval++ = '\0';
18567 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
18568 if (ast_variable_list_replace(&confp->chan.vars, tmpvar)) {
18569 tmpvar->next = confp->chan.vars;
18570 confp->chan.vars = tmpvar;
18571 }
18572 }
18573 }
18574 }
18575 } else if (!strcasecmp(v->name, "immediate")) {
18576 confp->chan.immediate = ast_true(v->value);
18577 } else if (!strcasecmp(v->name, "immediatering")) {
18578 confp->chan.immediatering = ast_true(v->value);
18579 } else if (!strcasecmp(v->name, "transfertobusy")) {
18580 confp->chan.transfertobusy = ast_true(v->value);
18581 } else if (!strcasecmp(v->name, "dialmode")) {
18582 if (!strcasecmp(v->value, "pulse")) {
18583 confp->chan.dialmode = ANALOG_DIALMODE_PULSE;
18584 } else if (!strcasecmp(v->value, "dtmf") || !strcasecmp(v->value, "tone")) {
18585 confp->chan.dialmode = ANALOG_DIALMODE_DTMF;
18586 } else if (!strcasecmp(v->value, "none")) {
18587 confp->chan.dialmode = ANALOG_DIALMODE_NONE;
18588 } else {
18589 confp->chan.dialmode = ANALOG_DIALMODE_BOTH;
18590 }
18591 } else if (!strcasecmp(v->name, "mwimonitor")) {
18592 confp->chan.mwimonitor_neon = 0;
18593 confp->chan.mwimonitor_fsk = 0;
18594 confp->chan.mwimonitor_rpas = 0;
18595 if (strcasestr(v->value, "fsk")) {
18596 confp->chan.mwimonitor_fsk = 1;
18597 }
18598 if (strcasestr(v->value, "rpas")) {
18599 confp->chan.mwimonitor_rpas = 1;
18600 }
18601 if (strcasestr(v->value, "neon")) {
18602 confp->chan.mwimonitor_neon = 1;
18603 }
18604 /* If set to true or yes, assume that simple fsk is desired */
18605 if (ast_true(v->value)) {
18606 confp->chan.mwimonitor_fsk = 1;
18607 }
18608 } else if (!strcasecmp(v->name, "hwrxgain")) {
18609 confp->chan.hwrxgain_enabled = 0;
18610 if (strcasecmp(v->value, "disabled")) {
18611 if (sscanf(v->value, "%30f", &confp->chan.hwrxgain) == 1) {
18612 confp->chan.hwrxgain_enabled = 1;
18613 } else {
18614 ast_log(LOG_WARNING, "Invalid hwrxgain: %s at line %d.\n", v->value, v->lineno);
18615 }
18616 }
18617 } else if (!strcasecmp(v->name, "hwtxgain")) {
18618 confp->chan.hwtxgain_enabled = 0;
18619 if (strcasecmp(v->value, "disabled")) {
18620 if (sscanf(v->value, "%30f", &confp->chan.hwtxgain) == 1) {
18621 confp->chan.hwtxgain_enabled = 1;
18622 } else {
18623 ast_log(LOG_WARNING, "Invalid hwtxgain: %s at line %d.\n", v->value, v->lineno);
18624 }
18625 }
18626 } else if (!strcasecmp(v->name, "cid_rxgain")) {
18627 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
18628 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
18629 }
18630 } else if (!strcasecmp(v->name, "rxgain")) {
18631 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
18632 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
18633 }
18634 } else if (!strcasecmp(v->name, "txgain")) {
18635 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
18636 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
18637 }
18638 } else if (!strcasecmp(v->name, "txdrc")) {
18639 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
18640 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
18641 }
18642 } else if (!strcasecmp(v->name, "rxdrc")) {
18643 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
18644 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
18645 }
18646 } else if (!strcasecmp(v->name, "tonezone")) {
18647 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
18648 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
18649 }
18650 } else if (!strcasecmp(v->name, "callerid")) {
18651 if (!strcasecmp(v->value, "asreceived")) {
18652 confp->chan.cid_num[0] = '\0';
18653 confp->chan.cid_name[0] = '\0';
18654 } else {
18655 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
18656 }
18657 } else if (!strcasecmp(v->name, "fullname")) {
18658 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
18659 } else if (!strcasecmp(v->name, "cid_number")) {
18660 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
18661 } else if (!strcasecmp(v->name, "cid_tag")) {
18662 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
18663 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
18664 confp->chan.dahditrcallerid = ast_true(v->value);
18665 } else if (!strcasecmp(v->name, "restrictcid")) {
18666 confp->chan.restrictcid = ast_true(v->value);
18667 } else if (!strcasecmp(v->name, "usecallingpres")) {
18668 confp->chan.use_callingpres = ast_true(v->value);
18669 } else if (!strcasecmp(v->name, "accountcode")) {
18670 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
18671 } else if (!strcasecmp(v->name, "amaflags")) {
18672 y = ast_channel_string2amaflag(v->value);
18673 if (y < 0)
18674 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
18675 else
18676 confp->chan.amaflags = y;
18677 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
18678 confp->chan.polarityonanswerdelay = atoi(v->value);
18679 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
18680 confp->chan.answeronpolarityswitch = ast_true(v->value);
18681 } else if (!strcasecmp(v->name, "ani_info_digits")) {
18682 confp->chan.ani_info_digits = atoi(v->value);
18683 } else if (!strcasecmp(v->name, "ani_wink_time")) {
18684 confp->chan.ani_wink_time = atoi(v->value);
18685 } else if (!strcasecmp(v->name, "ani_timeout")) {
18686 confp->chan.ani_timeout = atoi(v->value);
18687 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
18688 confp->chan.hanguponpolarityswitch = ast_true(v->value);
18689 } else if (!strcasecmp(v->name, "autoreoriginate")) {
18690 confp->chan.reoriginate = ast_true(v->value);
18691 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
18692 confp->chan.sendcalleridafter = atoi(v->value);
18693 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
18694 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
18695 } else if (ast_cc_is_config_param(v->name)) {
18696 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
18697 } else if (!strcasecmp(v->name, "mwisendtype")) {
18698 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI /* backward compatibility for older dahdi VMWI implementation */
18699 if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
18700 mwisend_rpas = 1;
18701 } else {
18702 mwisend_rpas = 0;
18703 }
18704 #else
18705 /* Default is fsk, to turn it off you must specify nofsk */
18706 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
18707 if (strcasestr(v->value, "nofsk")) { /* NoFSK */
18708 confp->chan.mwisend_fsk = 0;
18709 } else { /* Default FSK */
18710 confp->chan.mwisend_fsk = 1;
18711 }
18712 if (strcasestr(v->value, "rpas")) { /* Ring Pulse Alert Signal, normally followed by FSK */
18713 confp->chan.mwisend_rpas = 1;
18714 } else {
18715 confp->chan.mwisend_rpas = 0;
18716 }
18717 if (strcasestr(v->value, "lrev")) { /* Line Reversal */
18718 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
18719 }
18720 if (strcasestr(v->value, "hvdc")) { /* HV 90VDC */
18721 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
18722 }
18723 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ) { /* 90V DC pulses */
18724 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
18725 }
18726 #endif
18727 } else if (reload != 1) {
18728 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
18729 int orig_radio = confp->chan.radio;
18730 int orig_outsigmod = confp->chan.outsigmod;
18731 int orig_auto = confp->is_sig_auto;
18732
18733 confp->chan.radio = 0;
18734 confp->chan.outsigmod = -1;
18735 confp->is_sig_auto = 0;
18736 if (!strcasecmp(v->value, "em")) {
18737 confp->chan.sig = SIG_EM;
18738 } else if (!strcasecmp(v->value, "em_e1")) {
18739 confp->chan.sig = SIG_EM_E1;
18740 } else if (!strcasecmp(v->value, "em_w")) {
18741 confp->chan.sig = SIG_EMWINK;
18742 } else if (!strcasecmp(v->value, "fxs_ls")) {
18743 confp->chan.sig = SIG_FXSLS;
18744 } else if (!strcasecmp(v->value, "fxs_gs")) {
18745 confp->chan.sig = SIG_FXSGS;
18746 } else if (!strcasecmp(v->value, "fxs_ks")) {
18747 confp->chan.sig = SIG_FXSKS;
18748 } else if (!strcasecmp(v->value, "fxo_ls")) {
18749 confp->chan.sig = SIG_FXOLS;
18750 } else if (!strcasecmp(v->value, "fxo_gs")) {
18751 confp->chan.sig = SIG_FXOGS;
18752 } else if (!strcasecmp(v->value, "fxo_ks")) {
18753 confp->chan.sig = SIG_FXOKS;
18754 } else if (!strcasecmp(v->value, "fxs_rx")) {
18755 confp->chan.sig = SIG_FXSKS;
18756 confp->chan.radio = 1;
18757 } else if (!strcasecmp(v->value, "fxo_rx")) {
18758 confp->chan.sig = SIG_FXOLS;
18759 confp->chan.radio = 1;
18760 } else if (!strcasecmp(v->value, "fxs_tx")) {
18761 confp->chan.sig = SIG_FXSLS;
18762 confp->chan.radio = 1;
18763 } else if (!strcasecmp(v->value, "fxo_tx")) {
18764 confp->chan.sig = SIG_FXOGS;
18765 confp->chan.radio = 1;
18766 } else if (!strcasecmp(v->value, "em_rx")) {
18767 confp->chan.sig = SIG_EM;
18768 confp->chan.radio = 1;
18769 } else if (!strcasecmp(v->value, "em_tx")) {
18770 confp->chan.sig = SIG_EM;
18771 confp->chan.radio = 1;
18772 } else if (!strcasecmp(v->value, "em_rxtx")) {
18773 confp->chan.sig = SIG_EM;
18774 confp->chan.radio = 2;
18775 } else if (!strcasecmp(v->value, "em_txrx")) {
18776 confp->chan.sig = SIG_EM;
18777 confp->chan.radio = 2;
18778 } else if (!strcasecmp(v->value, "sf")) {
18779 confp->chan.sig = SIG_SF;
18780 } else if (!strcasecmp(v->value, "sf_w")) {
18781 confp->chan.sig = SIG_SFWINK;
18782 } else if (!strcasecmp(v->value, "sf_featd")) {
18783 confp->chan.sig = SIG_FEATD;
18784 } else if (!strcasecmp(v->value, "sf_featdmf")) {
18785 confp->chan.sig = SIG_FEATDMF;
18786 } else if (!strcasecmp(v->value, "sf_featb")) {
18787 confp->chan.sig = SIG_SF_FEATB;
18788 } else if (!strcasecmp(v->value, "sf")) {
18789 confp->chan.sig = SIG_SF;
18790 } else if (!strcasecmp(v->value, "sf_rx")) {
18791 confp->chan.sig = SIG_SF;
18792 confp->chan.radio = 1;
18793 } else if (!strcasecmp(v->value, "sf_tx")) {
18794 confp->chan.sig = SIG_SF;
18795 confp->chan.radio = 1;
18796 } else if (!strcasecmp(v->value, "sf_rxtx")) {
18797 confp->chan.sig = SIG_SF;
18798 confp->chan.radio = 2;
18799 } else if (!strcasecmp(v->value, "sf_txrx")) {
18800 confp->chan.sig = SIG_SF;
18801 confp->chan.radio = 2;
18802 } else if (!strcasecmp(v->value, "featd")) {
18803 confp->chan.sig = SIG_FEATD;
18804 } else if (!strcasecmp(v->value, "featdmf")) {
18805 confp->chan.sig = SIG_FEATDMF;
18806 } else if (!strcasecmp(v->value, "featdmf_ta")) {
18807 confp->chan.sig = SIG_FEATDMF_TA;
18808 } else if (!strcasecmp(v->value, "e911")) {
18809 confp->chan.sig = SIG_E911;
18810 } else if (!strcasecmp(v->value, "fgccama")) {
18811 confp->chan.sig = SIG_FGC_CAMA;
18812 } else if (!strcasecmp(v->value, "fgccamamf")) {
18813 confp->chan.sig = SIG_FGC_CAMAMF;
18814 } else if (!strcasecmp(v->value, "featb")) {
18815 confp->chan.sig = SIG_FEATB;
18816 #ifdef HAVE_PRI
18817 } else if (!strcasecmp(v->value, "pri_net")) {
18818 confp->chan.sig = SIG_PRI;
18819 confp->pri.pri.nodetype = PRI_NETWORK;
18820 } else if (!strcasecmp(v->value, "pri_cpe")) {
18821 confp->chan.sig = SIG_PRI;
18822 confp->pri.pri.nodetype = PRI_CPE;
18823 } else if (!strcasecmp(v->value, "bri_cpe")) {
18824 confp->chan.sig = SIG_BRI;
18825 confp->pri.pri.nodetype = PRI_CPE;
18826 } else if (!strcasecmp(v->value, "bri_net")) {
18827 confp->chan.sig = SIG_BRI;
18828 confp->pri.pri.nodetype = PRI_NETWORK;
18829 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
18830 confp->chan.sig = SIG_BRI_PTMP;
18831 confp->pri.pri.nodetype = PRI_CPE;
18832 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
18833 #if defined(HAVE_PRI_CALL_HOLD)
18834 confp->chan.sig = SIG_BRI_PTMP;
18835 confp->pri.pri.nodetype = PRI_NETWORK;
18836 #else
18837 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
18838 #endif /* !defined(HAVE_PRI_CALL_HOLD) */
18839 #endif
18840 #if defined(HAVE_SS7)
18841 } else if (!strcasecmp(v->value, "ss7")) {
18842 confp->chan.sig = SIG_SS7;
18843 #endif /* defined(HAVE_SS7) */
18844 #ifdef HAVE_OPENR2
18845 } else if (!strcasecmp(v->value, "mfcr2")) {
18846 confp->chan.sig = SIG_MFCR2;
18847 #endif
18848 } else if (!strcasecmp(v->value, "auto")) {
18849 confp->is_sig_auto = 1;
18850 } else {
18851 confp->chan.outsigmod = orig_outsigmod;
18852 confp->chan.radio = orig_radio;
18853 confp->is_sig_auto = orig_auto;
18854 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
18855 }
18856 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
18857 if (!strcasecmp(v->value, "em")) {
18858 confp->chan.outsigmod = SIG_EM;
18859 } else if (!strcasecmp(v->value, "em_e1")) {
18860 confp->chan.outsigmod = SIG_EM_E1;
18861 } else if (!strcasecmp(v->value, "em_w")) {
18862 confp->chan.outsigmod = SIG_EMWINK;
18863 } else if (!strcasecmp(v->value, "sf")) {
18864 confp->chan.outsigmod = SIG_SF;
18865 } else if (!strcasecmp(v->value, "sf_w")) {
18866 confp->chan.outsigmod = SIG_SFWINK;
18867 } else if (!strcasecmp(v->value, "sf_featd")) {
18868 confp->chan.outsigmod = SIG_FEATD;
18869 } else if (!strcasecmp(v->value, "sf_featdmf")) {
18870 confp->chan.outsigmod = SIG_FEATDMF;
18871 } else if (!strcasecmp(v->value, "sf_featb")) {
18872 confp->chan.outsigmod = SIG_SF_FEATB;
18873 } else if (!strcasecmp(v->value, "sf")) {
18874 confp->chan.outsigmod = SIG_SF;
18875 } else if (!strcasecmp(v->value, "featd")) {
18876 confp->chan.outsigmod = SIG_FEATD;
18877 } else if (!strcasecmp(v->value, "featdmf")) {
18878 confp->chan.outsigmod = SIG_FEATDMF;
18879 } else if (!strcasecmp(v->value, "featdmf_ta")) {
18880 confp->chan.outsigmod = SIG_FEATDMF_TA;
18881 } else if (!strcasecmp(v->value, "e911")) {
18882 confp->chan.outsigmod = SIG_E911;
18883 } else if (!strcasecmp(v->value, "fgccama")) {
18884 confp->chan.outsigmod = SIG_FGC_CAMA;
18885 } else if (!strcasecmp(v->value, "fgccamamf")) {
18886 confp->chan.outsigmod = SIG_FGC_CAMAMF;
18887 } else if (!strcasecmp(v->value, "featb")) {
18888 confp->chan.outsigmod = SIG_FEATB;
18889 } else {
18890 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
18891 }
18892 #ifdef HAVE_PRI
18893 } else if (!strcasecmp(v->name, "pridialplan")) {
18894 if (!strcasecmp(v->value, "national")) {
18895 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
18896 } else if (!strcasecmp(v->value, "unknown")) {
18897 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
18898 } else if (!strcasecmp(v->value, "private")) {
18899 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
18900 } else if (!strcasecmp(v->value, "international")) {
18901 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
18902 } else if (!strcasecmp(v->value, "local")) {
18903 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
18904 } else if (!strcasecmp(v->value, "dynamic")) {
18905 confp->pri.pri.dialplan = -1;
18906 } else if (!strcasecmp(v->value, "redundant")) {
18907 confp->pri.pri.dialplan = -2;
18908 } else {
18909 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
18910 }
18911 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
18912 if (!strcasecmp(v->value, "national")) {
18913 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
18914 } else if (!strcasecmp(v->value, "unknown")) {
18915 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
18916 } else if (!strcasecmp(v->value, "private")) {
18917 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
18918 } else if (!strcasecmp(v->value, "international")) {
18919 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
18920 } else if (!strcasecmp(v->value, "local")) {
18921 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
18922 } else if (!strcasecmp(v->value, "from_channel")) {
18923 confp->pri.pri.localdialplan = 0;
18924 } else if (!strcasecmp(v->value, "dynamic")) {
18925 confp->pri.pri.localdialplan = -1;
18926 } else if (!strcasecmp(v->value, "redundant")) {
18927 confp->pri.pri.localdialplan = -2;
18928 } else {
18929 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
18930 }
18931 } else if (!strcasecmp(v->name, "pricpndialplan")) {
18932 if (!strcasecmp(v->value, "national")) {
18933 confp->pri.pri.cpndialplan = PRI_NATIONAL_ISDN + 1;
18934 } else if (!strcasecmp(v->value, "unknown")) {
18935 confp->pri.pri.cpndialplan = PRI_UNKNOWN + 1;
18936 } else if (!strcasecmp(v->value, "private")) {
18937 confp->pri.pri.cpndialplan = PRI_PRIVATE + 1;
18938 } else if (!strcasecmp(v->value, "international")) {
18939 confp->pri.pri.cpndialplan = PRI_INTERNATIONAL_ISDN + 1;
18940 } else if (!strcasecmp(v->value, "local")) {
18941 confp->pri.pri.cpndialplan = PRI_LOCAL_ISDN + 1;
18942 } else if (!strcasecmp(v->value, "from_channel")) {
18943 confp->pri.pri.cpndialplan = 0;
18944 } else if (!strcasecmp(v->value, "dynamic")) {
18945 confp->pri.pri.cpndialplan = -1;
18946 } else if (!strcasecmp(v->value, "redundant")) {
18947 confp->pri.pri.cpndialplan = -2;
18948 } else {
18949 ast_log(LOG_WARNING, "Unknown PRI cpndialplan '%s' at line %d.\n", v->value, v->lineno);
18950 }
18951 } else if (!strcasecmp(v->name, "switchtype")) {
18952 if (!strcasecmp(v->value, "national"))
18953 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
18954 else if (!strcasecmp(v->value, "ni1"))
18955 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
18956 else if (!strcasecmp(v->value, "dms100"))
18957 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
18958 else if (!strcasecmp(v->value, "4ess"))
18959 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
18960 else if (!strcasecmp(v->value, "5ess"))
18961 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
18962 else if (!strcasecmp(v->value, "euroisdn"))
18963 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
18964 else if (!strcasecmp(v->value, "qsig"))
18965 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
18966 else {
18967 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
18968 return -1;
18969 }
18970 } else if (!strcasecmp(v->name, "msn")) {
18971 ast_copy_string(confp->pri.pri.msn_list, v->value,
18972 sizeof(confp->pri.pri.msn_list));
18973 } else if (!strcasecmp(v->name, "nsf")) {
18974 if (!strcasecmp(v->value, "sdn"))
18975 confp->pri.pri.nsf = PRI_NSF_SDN;
18976 else if (!strcasecmp(v->value, "megacom"))
18977 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
18978 else if (!strcasecmp(v->value, "tollfreemegacom"))
18979 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
18980 else if (!strcasecmp(v->value, "accunet"))
18981 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
18982 else if (!strcasecmp(v->value, "none"))
18983 confp->pri.pri.nsf = PRI_NSF_NONE;
18984 else {
18985 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
18986 confp->pri.pri.nsf = PRI_NSF_NONE;
18987 }
18988 } else if (!strcasecmp(v->name, "priindication")) {
18989 if (!strcasecmp(v->value, "outofband"))
18990 confp->chan.priindication_oob = 1;
18991 else if (!strcasecmp(v->value, "inband"))
18992 confp->chan.priindication_oob = 0;
18993 else
18994 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
18995 v->value, v->lineno);
18996 } else if (!strcasecmp(v->name, "priexclusive")) {
18997 confp->chan.priexclusive = ast_true(v->value);
18998 } else if (!strcasecmp(v->name, "internationalprefix")) {
18999 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
19000 } else if (!strcasecmp(v->name, "nationalprefix")) {
19001 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
19002 } else if (!strcasecmp(v->name, "localprefix")) {
19003 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
19004 } else if (!strcasecmp(v->name, "privateprefix")) {
19005 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
19006 } else if (!strcasecmp(v->name, "unknownprefix")) {
19007 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
19008 } else if (!strcasecmp(v->name, "resetinterval")) {
19009 if (!strcasecmp(v->value, "never"))
19010 confp->pri.pri.resetinterval = -1;
19011 else if (atoi(v->value) >= 60)
19012 confp->pri.pri.resetinterval = atoi(v->value);
19013 else
19014 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
19015 v->value, v->lineno);
19016 } else if (!strcasecmp(v->name, "force_restart_unavailable_chans")) {
19017 confp->pri.pri.force_restart_unavailable_chans = ast_true(v->value);
19018 } else if (!strcasecmp(v->name, "minunused")) {
19019 confp->pri.pri.minunused = atoi(v->value);
19020 } else if (!strcasecmp(v->name, "minidle")) {
19021 confp->pri.pri.minidle = atoi(v->value);
19022 } else if (!strcasecmp(v->name, "idleext")) {
19023 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
19024 } else if (!strcasecmp(v->name, "idledial")) {
19025 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
19026 } else if (!strcasecmp(v->name, "overlapdial")) {
19027 if (ast_true(v->value)) {
19028 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
19029 } else if (!strcasecmp(v->value, "incoming")) {
19030 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
19031 } else if (!strcasecmp(v->value, "outgoing")) {
19032 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
19033 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
19034 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
19035 } else {
19036 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
19037 }
19038 #ifdef HAVE_PRI_PROG_W_CAUSE
19039 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
19040 if (!strcasecmp(v->value, "logical")) {
19041 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
19042 } else if (!strcasecmp(v->value, "physical")) {
19043 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
19044 } else {
19045 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
19046 }
19047 #endif
19048 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
19049 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
19050 #if defined(HAVE_PRI_SERVICE_MESSAGES)
19051 } else if (!strcasecmp(v->name, "service_message_support")) {
19052 /* assuming switchtype for this channel group has been configured already */
19053 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
19054 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
19055 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
19056 confp->pri.pri.enable_service_message_support = 1;
19057 } else {
19058 confp->pri.pri.enable_service_message_support = 0;
19059 }
19060 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
19061 #ifdef HAVE_PRI_INBANDDISCONNECT
19062 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
19063 confp->pri.pri.inbanddisconnect = ast_true(v->value);
19064 #endif
19065 } else if (!strcasecmp(v->name, "pritimer")) {
19066 #ifdef PRI_GETSET_TIMERS
19067 char tmp[20];
19068 char *timerc;
19069 char *c;
19070 int timer;
19071 int timeridx;
19072
19073 ast_copy_string(tmp, v->value, sizeof(tmp));
19074 c = tmp;
19075 timerc = strsep(&c, ",");
19076 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
19077 timeridx = pri_timer2idx(timerc);
19078 timer = atoi(c);
19079 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
19080 ast_log(LOG_WARNING,
19081 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
19082 v->lineno);
19083 } else if (!timer) {
19084 ast_log(LOG_WARNING,
19085 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
19086 c, timerc, v->lineno);
19087 } else {
19088 confp->pri.pri.pritimers[timeridx] = timer;
19089 }
19090 } else {
19091 ast_log(LOG_WARNING,
19092 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
19093 v->value, v->lineno);
19094 }
19095 #endif /* PRI_GETSET_TIMERS */
19096 } else if (!strcasecmp(v->name, "facilityenable")) {
19097 confp->pri.pri.facilityenable = ast_true(v->value);
19098 #if defined(HAVE_PRI_AOC_EVENTS)
19099 } else if (!strcasecmp(v->name, "aoc_enable")) {
19100 confp->pri.pri.aoc_passthrough_flag = 0;
19101 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
19102 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
19103 }
19104 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
19105 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
19106 }
19107 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
19108 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
19109 }
19110 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
19111 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
19112 #endif /* defined(HAVE_PRI_AOC_EVENTS) */
19113 #if defined(HAVE_PRI_CALL_HOLD)
19114 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
19115 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
19116 #endif /* defined(HAVE_PRI_CALL_HOLD) */
19117 } else if (!strcasecmp(v->name, "moh_signaling")
19118 || !strcasecmp(v->name, "moh_signalling")) {
19119 if (!strcasecmp(v->value, "moh")) {
19120 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
19121 } else if (!strcasecmp(v->value, "notify")) {
19122 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_NOTIFY;
19123 #if defined(HAVE_PRI_CALL_HOLD)
19124 } else if (!strcasecmp(v->value, "hold")) {
19125 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_HOLD;
19126 #endif /* defined(HAVE_PRI_CALL_HOLD) */
19127 } else {
19128 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
19129 }
19130 #if defined(HAVE_PRI_CCSS)
19131 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
19132 if (!strcasecmp(v->value, "global")) {
19133 confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
19134 } else if (!strcasecmp(v->value, "specific")) {
19135 confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
19136 } else {
19137 confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
19138 }
19139 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
19140 if (!strcasecmp(v->value, "release")) {
19141 confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
19142 } else if (!strcasecmp(v->value, "retain")) {
19143 confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
19144 } else if (!strcasecmp(v->value, "do_not_care")) {
19145 confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
19146 } else {
19147 confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
19148 }
19149 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
19150 if (!strcasecmp(v->value, "release")) {
19151 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
19152 } else if (!strcasecmp(v->value, "retain")) {
19153 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
19154 } else {
19155 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
19156 }
19157 #endif /* defined(HAVE_PRI_CCSS) */
19158 #if defined(HAVE_PRI_CALL_WAITING)
19159 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
19160 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
19161 if (confp->pri.pri.max_call_waiting_calls < 0) {
19162 /* Negative values are not allowed. */
19163 confp->pri.pri.max_call_waiting_calls = 0;
19164 }
19165 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
19166 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
19167 #endif /* defined(HAVE_PRI_CALL_WAITING) */
19168 #if defined(HAVE_PRI_MWI)
19169 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
19170 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
19171 sizeof(confp->pri.pri.mwi_mailboxes));
19172 } else if (!strcasecmp(v->name, "mwi_vm_boxes")) {
19173 ast_copy_string(confp->pri.pri.mwi_vm_boxes, v->value,
19174 sizeof(confp->pri.pri.mwi_vm_boxes));
19175 } else if (!strcasecmp(v->name, "mwi_vm_numbers")) {
19176 ast_copy_string(confp->pri.pri.mwi_vm_numbers, v->value,
19177 sizeof(confp->pri.pri.mwi_vm_numbers));
19178 #endif /* defined(HAVE_PRI_MWI) */
19179 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
19180 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
19181 } else if (!strcasecmp(v->name, "inband_on_setup_ack")) {
19182 confp->pri.pri.inband_on_setup_ack = ast_true(v->value);
19183 } else if (!strcasecmp(v->name, "inband_on_proceeding")) {
19184 confp->pri.pri.inband_on_proceeding = ast_true(v->value);
19185 #if defined(HAVE_PRI_DISPLAY_TEXT)
19186 } else if (!strcasecmp(v->name, "display_send")) {
19187 confp->pri.pri.display_flags_send = dahdi_display_text_option(v->value);
19188 } else if (!strcasecmp(v->name, "display_receive")) {
19189 confp->pri.pri.display_flags_receive = dahdi_display_text_option(v->value);
19190 #endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
19191 #if defined(HAVE_PRI_MCID)
19192 } else if (!strcasecmp(v->name, "mcid_send")) {
19193 confp->pri.pri.mcid_send = ast_true(v->value);
19194 #endif /* defined(HAVE_PRI_MCID) */
19195 #if defined(HAVE_PRI_DATETIME_SEND)
19196 } else if (!strcasecmp(v->name, "datetime_send")) {
19197 confp->pri.pri.datetime_send = dahdi_datetime_send_option(v->value);
19198 #endif /* defined(HAVE_PRI_DATETIME_SEND) */
19199 } else if (!strcasecmp(v->name, "layer1_presence")) {
19200 if (!strcasecmp(v->value, "required")) {
19201 confp->pri.pri.layer1_ignored = 0;
19202 } else if (!strcasecmp(v->value, "ignore")) {
19203 confp->pri.pri.layer1_ignored = 1;
19204 } else {
19205 /* Default */
19206 confp->pri.pri.layer1_ignored = 0;
19207 }
19208 #if defined(HAVE_PRI_L2_PERSISTENCE)
19209 } else if (!strcasecmp(v->name, "layer2_persistence")) {
19210 if (!strcasecmp(v->value, "keep_up")) {
19211 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
19212 } else if (!strcasecmp(v->value, "leave_down")) {
19213 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
19214 } else {
19215 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
19216 }
19217 #endif /* defined(HAVE_PRI_L2_PERSISTENCE) */
19218 } else if (!strcasecmp(v->name, "colp_send")) {
19219 if (!strcasecmp(v->value, "block")) {
19220 confp->pri.pri.colp_send = SIG_PRI_COLP_BLOCK;
19221 } else if (!strcasecmp(v->value, "connect")) {
19222 confp->pri.pri.colp_send = SIG_PRI_COLP_CONNECT;
19223 } else if (!strcasecmp(v->value, "update")) {
19224 confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
19225 } else {
19226 confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
19227 }
19228 #endif /* HAVE_PRI */
19229 #if defined(HAVE_SS7)
19230 } else if (!strcasecmp(v->name, "ss7type")) {
19231 if (!strcasecmp(v->value, "itu")) {
19232 cur_ss7type = SS7_ITU;
19233 } else if (!strcasecmp(v->value, "ansi")) {
19234 cur_ss7type = SS7_ANSI;
19235 } else {
19236 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
19237 }
19238 } else if (!strcasecmp(v->name, "slc")) {
19239 cur_slc = atoi(v->value);
19240 } else if (!strcasecmp(v->name, "linkset")) {
19241 cur_linkset = atoi(v->value);
19242 } else if (!strcasecmp(v->name, "pointcode")) {
19243 cur_pointcode = parse_pointcode(v->value);
19244 } else if (!strcasecmp(v->name, "adjpointcode")) {
19245 cur_adjpointcode = parse_pointcode(v->value);
19246 } else if (!strcasecmp(v->name, "defaultdpc")) {
19247 cur_defaultdpc = parse_pointcode(v->value);
19248 } else if (!strcasecmp(v->name, "cicbeginswith")) {
19249 cur_cicbeginswith = atoi(v->value);
19250 } else if (!strcasecmp(v->name, "networkindicator")) {
19251 if (!strcasecmp(v->value, "national")) {
19252 cur_networkindicator = SS7_NI_NAT;
19253 } else if (!strcasecmp(v->value, "national_spare")) {
19254 cur_networkindicator = SS7_NI_NAT_SPARE;
19255 } else if (!strcasecmp(v->value, "international")) {
19256 cur_networkindicator = SS7_NI_INT;
19257 } else if (!strcasecmp(v->value, "international_spare")) {
19258 cur_networkindicator = SS7_NI_INT_SPARE;
19259 } else {
19260 cur_networkindicator = -1;
19261 }
19262 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
19263 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
19264 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
19265 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
19266 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
19267 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
19268 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
19269 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
19270 } else if (!strcasecmp(v->name, "ss7_networkroutedprefix")) {
19271 ast_copy_string(confp->ss7.ss7.networkroutedprefix, v->value, sizeof(confp->ss7.ss7.networkroutedprefix));
19272 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
19273 if (!strcasecmp(v->value, "national")) {
19274 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
19275 } else if (!strcasecmp(v->value, "international")) {
19276 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
19277 } else if (!strcasecmp(v->value, "subscriber")) {
19278 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
19279 } else if (!strcasecmp(v->value, "unknown")) {
19280 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
19281 } else if (!strcasecmp(v->value, "dynamic")) {
19282 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
19283 } else {
19284 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
19285 }
19286 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
19287 if (!strcasecmp(v->value, "national")) {
19288 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
19289 } else if (!strcasecmp(v->value, "international")) {
19290 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
19291 } else if (!strcasecmp(v->value, "subscriber")) {
19292 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
19293 } else if (!strcasecmp(v->value, "unknown")) {
19294 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
19295 } else if (!strcasecmp(v->value, "dynamic")) {
19296 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
19297 } else {
19298 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
19299 }
19300 } else if (!strcasecmp(v->name, "sigchan")) {
19301 int sigchan, res;
19302 sigchan = atoi(v->value);
19303 res = linkset_addsigchan(sigchan);
19304 if (res < 0) {
19305 return -1;
19306 }
19307 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
19308 struct dahdi_ss7 *link;
19309 link = ss7_resolve_linkset(cur_linkset);
19310 if (!link) {
19311 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19312 return -1;
19313 }
19314 if (ast_true(v->value)) {
19315 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
19316 } else {
19317 link->ss7.flags &= ~LINKSET_FLAG_EXPLICITACM;
19318 }
19319 } else if (!strcasecmp(v->name, "ss7_autoacm")) {
19320 struct dahdi_ss7 *link;
19321 link = ss7_resolve_linkset(cur_linkset);
19322 if (!link) {
19323 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19324 return -1;
19325 }
19326 if (ast_true(v->value)) {
19327 link->ss7.flags |= LINKSET_FLAG_AUTOACM;
19328 } else {
19329 link->ss7.flags &= ~LINKSET_FLAG_AUTOACM;
19330 }
19331 } else if (!strcasecmp(v->name, "ss7_initialhwblo")) {
19332 struct dahdi_ss7 *link;
19333 link = ss7_resolve_linkset(cur_linkset);
19334 if (!link) {
19335 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19336 return -1;
19337 }
19338 if (ast_true(v->value)) {
19339 link->ss7.flags |= LINKSET_FLAG_INITIALHWBLO;
19340 } else {
19341 link->ss7.flags &= ~LINKSET_FLAG_INITIALHWBLO;
19342 }
19343 } else if (!strcasecmp(v->name, "ss7_use_echocontrol")) {
19344 struct dahdi_ss7 *link;
19345 link = ss7_resolve_linkset(cur_linkset);
19346 if (!link) {
19347 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19348 return -1;
19349 }
19350 if (ast_true(v->value)) {
19351 link->ss7.flags |= LINKSET_FLAG_USEECHOCONTROL;
19352 } else {
19353 link->ss7.flags &= ~LINKSET_FLAG_USEECHOCONTROL;
19354 }
19355 } else if (!strcasecmp(v->name, "ss7_default_echocontrol")) {
19356 struct dahdi_ss7 *link;
19357 link = ss7_resolve_linkset(cur_linkset);
19358 if (!link) {
19359 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19360 return -1;
19361 }
19362 if (ast_true(v->value)) {
19363 link->ss7.flags |= LINKSET_FLAG_DEFAULTECHOCONTROL;
19364 } else {
19365 link->ss7.flags &= ~LINKSET_FLAG_DEFAULTECHOCONTROL;
19366 }
19367 } else if (!strncasecmp(v->name, "isup_timer.", 11)) {
19368 struct dahdi_ss7 *link;
19369 link = ss7_resolve_linkset(cur_linkset);
19370 if (!link) {
19371 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19372 return -1;
19373 }
19374 if (!link->ss7.ss7) {
19375 ast_log(LOG_ERROR, "Please specify isup timers after sigchan!\n");
19376 } else if (!ss7_set_isup_timer(link->ss7.ss7, strstr(v->name, ".") + 1, atoi(v->value))) {
19377 ast_log(LOG_ERROR, "Invalid isup timer %s\n", v->name);
19378 }
19379 } else if (!strncasecmp(v->name, "mtp3_timer.", 11)) {
19380 struct dahdi_ss7 *link;
19381 link = ss7_resolve_linkset(cur_linkset);
19382 if (!link) {
19383 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19384 return -1;
19385 }
19386 if (!link->ss7.ss7) {
19387 ast_log(LOG_ERROR, "Please specify mtp3 timers after sigchan!\n");
19388 } else if (!ss7_set_mtp3_timer(link->ss7.ss7, strstr(v->name, ".") + 1, atoi(v->value))) {
19389 ast_log(LOG_ERROR, "Invalid mtp3 timer %s\n", v->name);
19390 }
19391 } else if (!strcasecmp(v->name, "inr_if_no_calling")) {
19392 struct dahdi_ss7 *link;
19393 link = ss7_resolve_linkset(cur_linkset);
19394 if (!link) {
19395 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19396 return -1;
19397 }
19398 if (!link->ss7.ss7) {
19399 ast_log(LOG_ERROR, "Please specify inr_if_no_calling after sigchan!\n");
19400 } else if (ast_true(v->value)) {
19401 ss7_set_flags(link->ss7.ss7, SS7_INR_IF_NO_CALLING);
19402 } else {
19403 ss7_clear_flags(link->ss7.ss7, SS7_INR_IF_NO_CALLING);
19404 }
19405 } else if (!strcasecmp(v->name, "non_isdn_access")) {
19406 struct dahdi_ss7 *link;
19407 link = ss7_resolve_linkset(cur_linkset);
19408 if (!link) {
19409 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19410 return -1;
19411 }
19412 if (!link->ss7.ss7) {
19413 ast_log(LOG_ERROR, "Please specify non_isdn_access after sigchan!\n");
19414 } else if (ast_true(v->value)) {
19415 ss7_clear_flags(link->ss7.ss7, SS7_ISDN_ACCESS_INDICATOR);
19416 } else {
19417 ss7_set_flags(link->ss7.ss7, SS7_ISDN_ACCESS_INDICATOR);
19418 }
19419 } else if (!strcasecmp(v->name, "sls_shift")) {
19420 struct dahdi_ss7 *link;
19421 int sls_shift = atoi(v->value);
19422
19423 if (sls_shift < 0 || sls_shift > 7) {
19424 ast_log(LOG_ERROR, "Invalid sls_shift value. Must be between 0 and 7\n");
19425 return -1;
19426 }
19427
19428 link = ss7_resolve_linkset(cur_linkset);
19429 if (!link) {
19430 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19431 return -1;
19432 }
19433 if (!link->ss7.ss7) {
19434 ast_log(LOG_ERROR, "Please specify sls_shift after sigchan!\n");
19435 } else {
19436 ss7_set_sls_shift(link->ss7.ss7, sls_shift);
19437 }
19438 } else if (!strcasecmp(v->name, "cause_location")) {
19439 struct dahdi_ss7 *link;
19440 int cause_location = atoi(v->value);
19441
19442 if (cause_location < 0 || cause_location > 15) {
19443 ast_log(LOG_ERROR, "Invalid cause_location value. Must be between 0 and 15\n");
19444 return -1;
19445 }
19446 link = ss7_resolve_linkset(cur_linkset);
19447 if (!link) {
19448 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19449 return -1;
19450 }
19451 if (!link->ss7.ss7) {
19452 ast_log(LOG_ERROR, "Please specify cause_location after sigchan!\n");
19453 } else {
19454 ss7_set_cause_location(link->ss7.ss7, cause_location);
19455 }
19456 #endif /* defined(HAVE_SS7) */
19457 #ifdef HAVE_OPENR2
19458 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
19459 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
19460 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);
19461 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
19462 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
19463 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
19464 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
19465 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
19466 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
19467 confp->mfcr2.variant = OR2_VAR_ITU;
19468 }
19469 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
19470 confp->mfcr2.mfback_timeout = atoi(v->value);
19471 if (!confp->mfcr2.mfback_timeout) {
19472 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
19473 confp->mfcr2.mfback_timeout = -1;
19474 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
19475 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
19476 }
19477 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
19478 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
19479 if (confp->mfcr2.metering_pulse_timeout > 500) {
19480 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
19481 }
19482 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
19483 } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
19484 confp->mfcr2.dtmf_detection = ast_true(v->value) ? 1 : 0;
19485 } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
19486 confp->mfcr2.dtmf_dialing = ast_true(v->value) ? 1 : 0;
19487 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
19488 confp->mfcr2.dtmf_time_on = atoi(v->value);
19489 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
19490 confp->mfcr2.dtmf_time_off = atoi(v->value);
19491 #endif
19492 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
19493 } else if (!strcasecmp(v->name, "mfcr2_dtmf_end_timeout")) {
19494 confp->mfcr2.dtmf_end_timeout = atoi(v->value);
19495 #endif
19496 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
19497 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
19498 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
19499 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
19500 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
19501 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
19502 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
19503 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
19504 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
19505 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
19506 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
19507 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
19508 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
19509 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
19510 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
19511 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
19512 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
19513 #endif
19514 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
19515 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
19516 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
19517 confp->mfcr2.max_ani = atoi(v->value);
19518 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION) {
19519 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
19520 }
19521 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
19522 confp->mfcr2.max_dnis = atoi(v->value);
19523 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION) {
19524 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
19525 }
19526 } else if (!strcasecmp(v->name, "mfcr2_category")) {
19527 confp->mfcr2.category = openr2_proto_get_category(v->value);
19528 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
19529 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
19530 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
19531 v->value, v->lineno);
19532 }
19533 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
19534 openr2_log_level_t tmplevel;
19535 char *clevel;
19536 char *logval;
19537 char copy[strlen(v->value) + 1];
19538 strcpy(copy, v->value); /* safe */
19539 logval = copy;
19540 while (logval) {
19541 clevel = strsep(&logval,",");
19542 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
19543 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
19544 continue;
19545 }
19546 confp->mfcr2.loglevel |= tmplevel;
19547 }
19548 #endif /* HAVE_OPENR2 */
19549 } else if (!strcasecmp(v->name, "cadence")) {
19550 /* setup to scan our argument */
19551 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
19552 int i;
19553 struct dahdi_ring_cadence new_cadence;
19554 int cid_location = -1;
19555 int firstcadencepos = 0;
19556 char original_args[80];
19557 int cadence_is_ok = 1;
19558
19559 ast_copy_string(original_args, v->value, sizeof(original_args));
19560 /* 16 cadences allowed (8 pairs) */
19561 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]);
19562
19563 /* Cadence must be even (on/off) */
19564 if (element_count % 2 == 1) {
19565 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
19566 cadence_is_ok = 0;
19567 }
19568
19569 /* This check is only needed to satisfy the compiler that element_count can't cause an out of bounds */
19570 if (element_count > ARRAY_LEN(c)) {
19571 element_count = ARRAY_LEN(c);
19572 }
19573
19574 /* Ring cadences cannot be negative */
19575 for (i = 0; i < element_count; i++) {
19576 if (c[i] == 0) {
19577 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
19578 cadence_is_ok = 0;
19579 break;
19580 } else if (c[i] < 0) {
19581 if (i % 2 == 1) {
19582 /* Silence duration, negative possibly okay */
19583 if (cid_location == -1) {
19584 cid_location = i;
19585 c[i] *= -1;
19586 } else {
19587 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
19588 cadence_is_ok = 0;
19589 break;
19590 }
19591 } else {
19592 if (firstcadencepos == 0) {
19593 firstcadencepos = i; /* only recorded to avoid duplicate specification */
19594 /* duration will be passed negative to the DAHDI driver */
19595 } else {
19596 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
19597 cadence_is_ok = 0;
19598 break;
19599 }
19600 }
19601 }
19602 }
19603
19604 /* Substitute our scanned cadence */
19605 for (i = 0; i < 16; i++) {
19606 new_cadence.ringcadence[i] = c[i];
19607 }
19608
19609 if (cadence_is_ok) {
19610 /* ---we scanned it without getting annoyed; now some sanity checks--- */
19611 if (element_count < 2) {
19612 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
19613 } else {
19614 if (cid_location == -1) {
19615 /* user didn't say; default to first pause */
19616 cid_location = 1;
19617 } else {
19618 /* convert element_index to cidrings value */
19619 cid_location = (cid_location + 1) / 2;
19620 }
19621 /* ---we like their cadence; try to install it--- */
19622 if (!user_has_defined_cadences++)
19623 /* this is the first user-defined cadence; clear the default user cadences */
19624 num_cadence = 0;
19625 if ((num_cadence+1) >= NUM_CADENCE_MAX)
19626 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
19627 else {
19628 cadences[num_cadence] = new_cadence;
19629 cidrings[num_cadence++] = cid_location;
19630 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
19631 }
19632 }
19633 }
19634 } else if (!strcasecmp(v->name, "ringtimeout")) {
19635 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
19636 } else if (!strcasecmp(v->name, "prewink")) {
19637 confp->timing.prewinktime = atoi(v->value);
19638 } else if (!strcasecmp(v->name, "preflash")) {
19639 confp->timing.preflashtime = atoi(v->value);
19640 } else if (!strcasecmp(v->name, "wink")) {
19641 confp->timing.winktime = atoi(v->value);
19642 } else if (!strcasecmp(v->name, "flash")) {
19643 confp->timing.flashtime = atoi(v->value);
19644 } else if (!strcasecmp(v->name, "start")) {
19645 confp->timing.starttime = atoi(v->value);
19646 } else if (!strcasecmp(v->name, "rxwink")) {
19647 confp->timing.rxwinktime = atoi(v->value);
19648 } else if (!strcasecmp(v->name, "rxflash")) {
19649 confp->timing.rxflashtime = atoi(v->value);
19650 } else if (!strcasecmp(v->name, "debounce")) {
19651 confp->timing.debouncetime = atoi(v->value);
19652 } else if (!strcasecmp(v->name, "toneduration")) {
19653 int toneduration;
19654 int ctlfd;
19655 int res;
19656 struct dahdi_dialparams dps;
19657
19658 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
19659 if (ctlfd == -1) {
19660 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
19661 return -1;
19662 }
19663
19664 toneduration = atoi(v->value);
19665 if (toneduration > -1) {
19666 memset(&dps, 0, sizeof(dps));
19667
19668 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
19669 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
19670 if (res < 0) {
19671 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
19672 close(ctlfd);
19673 return -1;
19674 }
19675 }
19676 close(ctlfd);
19677 } else if (!strcasecmp(v->name, "defaultcic")) {
19678 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
19679 } else if (!strcasecmp(v->name, "defaultozz")) {
19680 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
19681 } else if (!strcasecmp(v->name, "mwilevel")) {
19682 mwilevel = atoi(v->value);
19683 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
19684 dtmfcid_level = atoi(v->value);
19685 } else if (!strcasecmp(v->name, "reportalarms")) {
19686 if (!strcasecmp(v->value, "all"))
19687 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
19688 if (!strcasecmp(v->value, "none"))
19689 report_alarms = 0;
19690 else if (!strcasecmp(v->value, "channels"))
19691 report_alarms = REPORT_CHANNEL_ALARMS;
19692 else if (!strcasecmp(v->value, "spans"))
19693 report_alarms = REPORT_SPAN_ALARMS;
19694 }
19695 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
19696 ast_log(LOG_NOTICE, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
19697 }
19698
19699 if (dahdichan) {
19700 /* Process the deferred dahdichan value. */
19701 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno)) {
19702 if (confp->ignore_failed_channels) {
19703 ast_log(LOG_WARNING,
19704 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
19705 dahdichan->value);
19706 } else {
19707 return -1;
19708 }
19709 }
19710 }
19711
19712 /*
19713 * Since confp has already filled individual dahdi_pvt objects with channels
19714 * at this point, clear the variables in confp's pvt.
19715 */
19716 if (confp->chan.vars) {
19717 ast_variables_destroy(confp->chan.vars);
19718 confp->chan.vars = NULL;
19719 }
19720
19721 /* mark the first channels of each DAHDI span to watch for their span alarms */
19722 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
19723 if (!tmp->destroy && tmp->span != y) {
19724 tmp->manages_span_alarms = 1;
19725 y = tmp->span;
19726 } else {
19727 tmp->manages_span_alarms = 0;
19728 }
19729 }
19730
19731 /*< \todo why check for the pseudo in the per-channel section.
19732 * Any actual use for manual setup of the pseudo channel? */
19733 if (!has_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
19734 /* use the default configuration for a channel, so
19735 that any settings from real configured channels
19736 don't "leak" into the pseudo channel config
19737 */
19738 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
19739
19740 if (conf.chan.cc_params) {
19741 tmp = mkintf(CHAN_PSEUDO, &conf, reload);
19742 } else {
19743 tmp = NULL;
19744 }
19745 if (tmp) {
19746 ast_verb(3, "Automatically generated pseudo channel\n");
19747 has_pseudo = 1;
19748 } else {
19749 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
19750 }
19751 ast_cc_config_params_destroy(conf.chan.cc_params);
19752 }
19753
19754 /* Since named callgroup and named pickup group are ref'd to dahdi_pvt at this point, unref container in confp's pvt. */
19755 confp->chan.named_callgroups = ast_unref_namedgroups(confp->chan.named_callgroups);
19756 confp->chan.named_pickupgroups = ast_unref_namedgroups(confp->chan.named_pickupgroups);
19757
19758 return 0;
19759 }
19760
19761 /*!
19762 * \internal
19763 * \brief Deep copy struct dahdi_chan_conf.
19764 * \since 1.8
19765 *
19766 * \param dest Destination.
19767 * \param src Source.
19768 */
19769 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
19770 {
19771 struct ast_cc_config_params *cc_params;
19772
19773 cc_params = dest->chan.cc_params;
19774 *dest = *src;
19775 dest->chan.cc_params = cc_params;
19776 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
19777 }
19778
19779 /*!
19780 * \internal
19781 * \brief Setup DAHDI channel driver.
19782 *
19783 * \param reload enum: load_module(0), reload(1), restart(2).
19784 * \param default_conf Default config parameters. So cc_params can be properly destroyed.
19785 * \param base_conf Default config parameters per section. So cc_params can be properly destroyed.
19786 * \param conf Local config parameters. So cc_params can be properly destroyed.
19787 *
19788 * \retval 0 on success.
19789 * \retval -1 on error.
19790 */
19791 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
19792 {
19793 struct ast_config *cfg;
19794 struct ast_config *ucfg;
19795 struct ast_variable *v;
19796 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
19797 const char *chans;
19798 const char *cat;
19799 int res;
19800
19801 #ifdef HAVE_PRI
19802 char *c;
19803 int spanno;
19804 int i;
19805 int logicalspan;
19806 int trunkgroup;
19807 int dchannels[SIG_PRI_NUM_DCHANS];
19808 #endif
19809 int have_cfg_now;
19810 static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
19811
19812 cfg = ast_config_load(config, config_flags);
19813 have_cfg_now = !!cfg;
19814 if (!cfg) {
19815 /* Error if we have no config file */
19816 if (had_cfg_before) {
19817 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
19818 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
19819 }
19820 cfg = ast_config_new();/* Dummy config */
19821 if (!cfg) {
19822 return 0;
19823 }
19824 ucfg = ast_config_load("users.conf", config_flags);
19825 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
19826 ast_config_destroy(cfg);
19827 return 0;
19828 }
19829 if (ucfg == CONFIG_STATUS_FILEINVALID) {
19830 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
19831 ast_config_destroy(cfg);
19832 return 0;
19833 }
19834 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
19835 ucfg = ast_config_load("users.conf", config_flags);
19836 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
19837 return 0;
19838 }
19839 if (ucfg == CONFIG_STATUS_FILEINVALID) {
19840 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
19841 return 0;
19842 }
19843 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
19844 cfg = ast_config_load(config, config_flags);
19845 have_cfg_now = !!cfg;
19846 if (!cfg) {
19847 if (had_cfg_before) {
19848 /* We should have been able to load the config. */
19849 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
19850 ast_config_destroy(ucfg);
19851 return 0;
19852 }
19853 cfg = ast_config_new();/* Dummy config */
19854 if (!cfg) {
19855 ast_config_destroy(ucfg);
19856 return 0;
19857 }
19858 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
19859 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
19860 ast_config_destroy(ucfg);
19861 return 0;
19862 }
19863 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
19864 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
19865 return 0;
19866 } else {
19867 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
19868 ucfg = ast_config_load("users.conf", config_flags);
19869 if (ucfg == CONFIG_STATUS_FILEINVALID) {
19870 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
19871 ast_config_destroy(cfg);
19872 return 0;
19873 }
19874 }
19875 had_cfg_before = have_cfg_now;
19876
19877 /* It's a little silly to lock it, but we might as well just to be sure */
19878 ast_mutex_lock(&iflock);
19879 #ifdef HAVE_PRI
19880 if (reload != 1) {
19881 /* Process trunkgroups first */
19882 v = ast_variable_browse(cfg, "trunkgroups");
19883 while (v) {
19884 if (!strcasecmp(v->name, "trunkgroup")) {
19885 trunkgroup = atoi(v->value);
19886 if (trunkgroup > 0) {
19887 if ((c = strchr(v->value, ','))) {
19888 i = 0;
19889 memset(dchannels, 0, sizeof(dchannels));
19890 while (c && (i < SIG_PRI_NUM_DCHANS)) {
19891 dchannels[i] = atoi(c + 1);
19892 if (dchannels[i] < 0) {
19893 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);
19894 } else
19895 i++;
19896 c = strchr(c + 1, ',');
19897 }
19898 if (i) {
19899 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
19900 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);
19901 } else
19902 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");
19903 } else
19904 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
19905 } else
19906 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
19907 } else
19908 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
19909 } else if (!strcasecmp(v->name, "spanmap")) {
19910 spanno = atoi(v->value);
19911 if (spanno > 0) {
19912 if ((c = strchr(v->value, ','))) {
19913 trunkgroup = atoi(c + 1);
19914 if (trunkgroup > 0) {
19915 if ((c = strchr(c + 1, ',')))
19916 logicalspan = atoi(c + 1);
19917 else
19918 logicalspan = 0;
19919 if (logicalspan >= 0) {
19920 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
19921 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
19922 } else
19923 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
19924 } else
19925 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);
19926 } else
19927 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
19928 } else
19929 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
19930 } else
19931 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
19932 } else {
19933 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
19934 }
19935 v = v->next;
19936 }
19937 }
19938 #endif
19939
19940 /* Copy the default jb config over global_jbconf */
19941 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
19942
19943 mwimonitornotify[0] = '\0';
19944
19945 v = ast_variable_browse(cfg, "channels");
19946 if ((res = process_dahdi(base_conf,
19947 "" /* Must be empty for the channels category. Silly voicemail mailbox. */,
19948 v, reload, 0))) {
19949 ast_mutex_unlock(&iflock);
19950 ast_config_destroy(cfg);
19951 if (ucfg) {
19952 ast_config_destroy(ucfg);
19953 }
19954 return res;
19955 }
19956
19957 /* Now get configuration from all normal sections in chan_dahdi.conf: */
19958 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
19959 /* [channels] and [trunkgroups] are used. Let's also reserve
19960 * [globals] and [general] for future use
19961 */
19962 if (!strcasecmp(cat, "general") ||
19963 !strcasecmp(cat, "trunkgroups") ||
19964 !strcasecmp(cat, "globals") ||
19965 !strcasecmp(cat, "channels")) {
19966 continue;
19967 }
19968
19969 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
19970 if (ast_strlen_zero(chans)) {
19971 /* Section is useless without a dahdichan value present. */
19972 continue;
19973 }
19974
19975 /* Copy base_conf to conf. */
19976 deep_copy_dahdi_chan_conf(conf, base_conf);
19977
19978 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
19979 ast_mutex_unlock(&iflock);
19980 ast_config_destroy(cfg);
19981 if (ucfg) {
19982 ast_config_destroy(ucfg);
19983 }
19984 return res;
19985 }
19986 }
19987
19988 ast_config_destroy(cfg);
19989
19990 if (ucfg) {
19991 /* Reset base_conf, so things don't leak from chan_dahdi.conf */
19992 deep_copy_dahdi_chan_conf(base_conf, default_conf);
19993 process_dahdi(base_conf,
19994 "" /* Must be empty for the general category. Silly voicemail mailbox. */,
19995 ast_variable_browse(ucfg, "general"), 1, 0);
19996
19997 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
19998 if (!strcasecmp(cat, "general")) {
19999 continue;
20000 }
20001
20002 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
20003 if (ast_strlen_zero(chans)) {
20004 /* Section is useless without a dahdichan value present. */
20005 continue;
20006 }
20007
20008 /* Copy base_conf to conf. */
20009 deep_copy_dahdi_chan_conf(conf, base_conf);
20010
20011 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
20012 ast_config_destroy(ucfg);
20013 ast_mutex_unlock(&iflock);
20014 return res;
20015 }
20016 }
20017 ast_config_destroy(ucfg);
20018 }
20019 ast_mutex_unlock(&iflock);
20020
20021 #ifdef HAVE_PRI
20022 if (reload != 1) {
20023 int x;
20024 for (x = 0; x < NUM_SPANS; x++) {
20025 if (pris[x].pri.pvts[0] &&
20026 pris[x].pri.master == AST_PTHREADT_NULL) {
20027 prepare_pri(pris + x);
20028 if (sig_pri_start_pri(&pris[x].pri)) {
20029 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
20030 return -1;
20031 } else
20032 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
20033 }
20034 }
20035 }
20036 #endif
20037 #if defined(HAVE_SS7)
20038 if (reload != 1) {
20039 int x;
20040 for (x = 0; x < NUM_SPANS; x++) {
20041 if (linksets[x].ss7.ss7) {
20042 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
20043 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
20044 return -1;
20045 } else
20046 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
20047 }
20048 }
20049 }
20050 #endif /* defined(HAVE_SS7) */
20051 #ifdef HAVE_OPENR2
20052 if (reload != 1) {
20053 struct r2link_entry *cur;
20054 int x = 0;
20055 AST_LIST_LOCK(&r2links);
20056 AST_LIST_TRAVERSE(&r2links, cur, list) {
20057 struct dahdi_mfcr2 *r2 = &cur->mfcr2;
20058 if (r2->r2master == AST_PTHREADT_NULL) {
20059 if (ast_pthread_create(&r2->r2master, NULL, mfcr2_monitor, r2)) {
20060 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
20061 return -1;
20062 } else {
20063 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
20064 }
20065 x++;
20066 }
20067 }
20068 AST_LIST_UNLOCK(&r2links);
20069 }
20070 #endif
20071 /* And start the monitor for the first time */
20072 restart_monitor();
20073 return 0;
20074 }
20075
20076 /*!
20077 * \internal
20078 * \brief Setup DAHDI channel driver.
20079 *
20080 * \param reload enum: load_module(0), reload(1), restart(2).
20081 *
20082 * \retval 0 on success.
20083 * \retval -1 on error.
20084 */
20085 static int setup_dahdi(int reload)
20086 {
20087 int res;
20088 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
20089 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
20090 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
20091
20092 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
20093 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
20094 } else {
20095 res = -1;
20096 }
20097 ast_cc_config_params_destroy(default_conf.chan.cc_params);
20098 ast_cc_config_params_destroy(base_conf.chan.cc_params);
20099 ast_cc_config_params_destroy(conf.chan.cc_params);
20100
20101 return res;
20102 }
20103
20104 /*!
20105 * \brief Load the module
20106 *
20107 * Module loading including tests for configuration or dependencies.
20108 * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
20109 * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
20110 * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
20111 * configuration file or other non-critical problem return
20112 * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
20113 */
20114 static int load_module(void)
20115 {
20116 int res;
20117 #if defined(HAVE_PRI) || defined(HAVE_SS7)
20118 int y;
20119 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
20120
20121 if (STASIS_MESSAGE_TYPE_INIT(dahdichannel_type)) {
20122 return AST_MODULE_LOAD_DECLINE;
20123 }
20124
20125 if (!(dahdi_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
20126 return AST_MODULE_LOAD_DECLINE;
20127 }
20128 ast_format_cap_append(dahdi_tech.capabilities, ast_format_slin, 0);
20129 ast_format_cap_append(dahdi_tech.capabilities, ast_format_ulaw, 0);
20130 ast_format_cap_append(dahdi_tech.capabilities, ast_format_alaw, 0);
20131
20132 if (dahdi_native_load(&dahdi_tech)) {
20133 ao2_ref(dahdi_tech.capabilities, -1);
20134 return AST_MODULE_LOAD_DECLINE;
20135 }
20136
20137 #ifdef HAVE_PRI
20138 memset(pris, 0, sizeof(pris));
20139 for (y = 0; y < NUM_SPANS; y++) {
20140 sig_pri_init_pri(&pris[y].pri);
20141 }
20142 pri_set_error(dahdi_pri_error);
20143 pri_set_message(dahdi_pri_message);
20144 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
20145 #ifdef HAVE_PRI_PROG_W_CAUSE
20146 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
20147 #endif
20148 #if defined(HAVE_PRI_CCSS)
20149 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
20150 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
20151 __unload_module();
20152 return AST_MODULE_LOAD_DECLINE;
20153 }
20154 #endif /* defined(HAVE_PRI_CCSS) */
20155 if (sig_pri_load(
20156 #if defined(HAVE_PRI_CCSS)
20157 dahdi_pri_cc_type
20158 #else
20159 NULL
20160 #endif /* defined(HAVE_PRI_CCSS) */
20161 )) {
20162 __unload_module();
20163 return AST_MODULE_LOAD_DECLINE;
20164 }
20165 #endif
20166 #if defined(HAVE_SS7)
20167 memset(linksets, 0, sizeof(linksets));
20168 for (y = 0; y < NUM_SPANS; y++) {
20169 sig_ss7_init_linkset(&linksets[y].ss7);
20170 }
20171 ss7_set_error(dahdi_ss7_error);
20172 ss7_set_message(dahdi_ss7_message);
20173 ss7_set_hangup(sig_ss7_cb_hangup);
20174 ss7_set_notinservice(sig_ss7_cb_notinservice);
20175 ss7_set_call_null(sig_ss7_cb_call_null);
20176 #endif /* defined(HAVE_SS7) */
20177 res = setup_dahdi(0);
20178 /* Make sure we can register our DAHDI channel type */
20179 if (res) {
20180 __unload_module();
20181 return AST_MODULE_LOAD_DECLINE;
20182 }
20183 if (ast_channel_register(&dahdi_tech)) {
20184 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
20185 __unload_module();
20186 return AST_MODULE_LOAD_DECLINE;
20187 }
20188 #ifdef HAVE_PRI
20189 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
20190 #endif
20191 #if defined(HAVE_SS7)
20192 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
20193 #endif /* defined(HAVE_SS7) */
20194 #ifdef HAVE_OPENR2
20195 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
20196 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
20197 #endif
20198
20199 ast_custom_function_register(&polarity_function);
20200
20201 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
20202 memset(round_robin, 0, sizeof(round_robin));
20203 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
20204 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
20205 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
20206 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
20207 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
20208 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
20209 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
20210 #if defined(HAVE_PRI)
20211 ast_manager_register_xml("PRIShowSpans", 0, action_prishowspans);
20212 ast_manager_register_xml("PRIDebugSet", 0, action_pri_debug_set);
20213 ast_manager_register_xml("PRIDebugFileSet", EVENT_FLAG_SYSTEM, action_pri_debug_file_set);
20214 ast_manager_register_xml("PRIDebugFileUnset", 0, action_pri_debug_file_unset);
20215 #endif /* defined(HAVE_PRI) */
20216
20217 ast_cond_init(&ss_thread_complete, NULL);
20218
20219 return res;
20220 }
20221
20222 static int dahdi_sendtext(struct ast_channel *c, const char *text)
20223 {
20224 #define END_SILENCE_LEN 400
20225 #define HEADER_MS 50
20226 #define TRAILER_MS 5
20227 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
20228 #define ASCII_BYTES_PER_CHAR 80
20229
20230 unsigned char *buf,*mybuf;
20231 struct dahdi_pvt *p = ast_channel_tech_pvt(c);
20232 struct pollfd fds[1];
20233 int size,res,fd,len,x;
20234 int bytes=0;
20235 int idx;
20236
20237 /*
20238 * Initial carrier (imaginary)
20239 *
20240 * Note: The following float variables are used by the
20241 * PUT_CLID_MARKMS and PUT_CLID() macros.
20242 */
20243 float cr = 1.0;
20244 float ci = 0.0;
20245 float scont = 0.0;
20246
20247 if (!text[0]) {
20248 return(0); /* if nothing to send, don't */
20249 }
20250 idx = dahdi_get_index(c, p, 0);
20251 if (idx < 0) {
20252 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
20253 return -1;
20254 }
20255 if ((!p->tdd) && (!p->mate)) {
20256 #if defined(HAVE_PRI)
20257 #if defined(HAVE_PRI_DISPLAY_TEXT)
20258 ast_mutex_lock(&p->lock);
20259 if (dahdi_sig_pri_lib_handles(p->sig)) {
20260 sig_pri_sendtext(p->sig_pvt, text);
20261 }
20262 ast_mutex_unlock(&p->lock);
20263 #endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
20264 #endif /* defined(HAVE_PRI) */
20265 return(0); /* if not in TDD mode, just return */
20266 }
20267 if (p->mate)
20268 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
20269 else
20270 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
20271 if (!buf)
20272 return -1;
20273 mybuf = buf;
20274 if (p->mate) {
20275 /* PUT_CLI_MARKMS is a macro and requires a format ptr called codec to be present */
20276 struct ast_format *codec = AST_LAW(p);
20277
20278 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
20279 PUT_CLID_MARKMS;
20280 }
20281 /* Put actual message */
20282 for (x = 0; text[x]; x++) {
20283 PUT_CLID(text[x]);
20284 }
20285 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
20286 PUT_CLID_MARKMS;
20287 }
20288 len = bytes;
20289 buf = mybuf;
20290 } else {
20291 len = tdd_generate(p->tdd, buf, text);
20292 if (len < 1) {
20293 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
20294 ast_free(mybuf);
20295 return -1;
20296 }
20297 }
20298 memset(buf + len, 0x7f, END_SILENCE_LEN);
20299 len += END_SILENCE_LEN;
20300 fd = p->subs[idx].dfd;
20301 while (len) {
20302 if (ast_check_hangup(c)) {
20303 ast_free(mybuf);
20304 return -1;
20305 }
20306 size = len;
20307 if (size > READ_SIZE)
20308 size = READ_SIZE;
20309 fds[0].fd = fd;
20310 fds[0].events = POLLOUT | POLLPRI;
20311 fds[0].revents = 0;
20312 res = poll(fds, 1, -1);
20313 if (!res) {
20314 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
20315 continue;
20316 }
20317 /* if got exception */
20318 if (fds[0].revents & POLLPRI) {
20319 ast_free(mybuf);
20320 return -1;
20321 }
20322 if (!(fds[0].revents & POLLOUT)) {
20323 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
20324 continue;
20325 }
20326 res = write(fd, buf, size);
20327 if (res != size) {
20328 if (res == -1) {
20329 ast_free(mybuf);
20330 return -1;
20331 }
20332 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
20333 break;
20334 }
20335 len -= size;
20336 buf += size;
20337 }
20338 ast_free(mybuf);
20339 return(0);
20340 }
20341
20342
20343 static int reload(void)
20344 {
20345 int res = 0;
20346
20347 res = setup_dahdi(1);
20348 if (res) {
20349 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
20350 return -1;
20351 }
20352 return 0;
20353 }
20354
20355 /* This is a workaround so that menuselect displays a proper description
20356 * AST_MODULE_INFO(, , "DAHDI Telephony"
20357 */
20358
20359 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
20360 .support_level = AST_MODULE_SUPPORT_CORE,
20361 .load = load_module,
20362 .unload = unload_module,
20363 .reload = reload,
20364 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
20365 .requires = "ccss",
20366 .optional_modules = "res_smdi",
20367 );