Support for withheld or missing CID string
[asterisk-bristuff.git] / channels / chan_dahdi.c
blob4a138c006452c14bc51d4aead4d7888fdbea2a2c
1 /*
2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
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.
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.
19 /*! \file
21 * \brief DAHDI Pseudo TDM interface
23 * \author Mark Spencer <markster@digium.com>
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.
29 * You need to install libraries before you attempt to compile
30 * and install the DAHDI channel.
32 * \par See also
33 * \arg \ref Config_dahdi
35 * \ingroup channel_drivers
37 * \todo Deprecate the "musiconhold" configuration option post 1.4
40 /*** MODULEINFO
41 <depend>res_smdi</depend>
42 <depend>dahdi</depend>
43 <depend>tonezone</depend>
44 <depend>res_features</depend>
45 <use>pri</use>
46 ***/
48 #include "asterisk.h"
50 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
52 #include <stdio.h>
53 #include <string.h>
54 #ifdef __NetBSD__
55 #include <pthread.h>
56 #include <signal.h>
57 #else
58 #include <sys/signal.h>
59 #endif
60 #include <errno.h>
61 #include <stdlib.h>
62 #if !defined(SOLARIS) && !defined(__FreeBSD__)
63 #include <stdint.h>
64 #endif
65 #include <unistd.h>
66 #include <sys/ioctl.h>
67 #include <math.h>
68 #include <ctype.h>
70 #ifdef HAVE_PRI
71 #include <libpri.h>
72 #endif
74 #include "asterisk/lock.h"
75 #include "asterisk/channel.h"
76 #include "asterisk/config.h"
77 #include "asterisk/logger.h"
78 #include "asterisk/module.h"
79 #include "asterisk/pbx.h"
80 #include "asterisk/options.h"
81 #include "asterisk/file.h"
82 #include "asterisk/ulaw.h"
83 #include "asterisk/alaw.h"
84 #include "asterisk/callerid.h"
85 #include "asterisk/adsi.h"
86 #include "asterisk/cli.h"
87 #include "asterisk/cdr.h"
88 #include "asterisk/features.h"
89 #include "asterisk/musiconhold.h"
90 #include "asterisk/say.h"
91 #include "asterisk/tdd.h"
92 #include "asterisk/app.h"
93 #include "asterisk/dsp.h"
94 #include "asterisk/astdb.h"
95 #include "asterisk/manager.h"
96 #include "asterisk/causes.h"
97 #include "asterisk/term.h"
98 #include "asterisk/utils.h"
99 #include "asterisk/transcap.h"
100 #include "asterisk/stringfields.h"
101 #include "asterisk/abstract_jb.h"
102 #include "asterisk/smdi.h"
103 #include "asterisk/astobj.h"
104 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
106 #include "asterisk/dahdi_compat.h"
107 #include "asterisk/tonezone_compat.h"
109 /*! Global jitterbuffer configuration - by default, jb is disabled */
110 static struct ast_jb_conf default_jbconf =
112 .flags = 0,
113 .max_size = -1,
114 .resync_threshold = -1,
115 .impl = ""
117 static struct ast_jb_conf global_jbconf;
119 #ifndef DAHDI_TONEDETECT
120 /* Work around older code with no tone detect */
121 #define DAHDI_EVENT_DTMFDOWN 0
122 #define DAHDI_EVENT_DTMFUP 0
123 #endif
125 /* define this to send PRI user-user information elements */
126 #undef SUPPORT_USERUSER
128 /*!
129 * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
130 * the user hangs up to reset the state machine so ring works properly.
131 * This is used to be able to support kewlstart by putting the zhone in
132 * groundstart mode since their forward disconnect supervision is entirely
133 * broken even though their documentation says it isn't and their support
134 * is entirely unwilling to provide any assistance with their channel banks
135 * even though their web site says they support their products for life.
137 /* #define ZHONE_HACK */
139 /*! \note
140 * Define if you want to check the hook state for an FXO (FXS signalled) interface
141 * before dialing on it. Certain FXO interfaces always think they're out of
142 * service with this method however.
144 /* #define DAHDI_CHECK_HOOKSTATE */
146 /*! \brief Typically, how many rings before we should send Caller*ID */
147 #define DEFAULT_CIDRINGS 1
149 #define CHANNEL_PSEUDO -12
151 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
153 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
154 #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))
156 static const char tdesc[] = "DAHDI Telephony Driver"
157 #ifdef HAVE_PRI
158 " w/PRI"
159 #endif
162 #define SIG_EM DAHDI_SIG_EM
163 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
164 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
165 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
166 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
167 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
168 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
169 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
170 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
171 #define SIG_FXSLS DAHDI_SIG_FXSLS
172 #define SIG_FXSGS DAHDI_SIG_FXSGS
173 #define SIG_FXSKS DAHDI_SIG_FXSKS
174 #define SIG_FXOLS DAHDI_SIG_FXOLS
175 #define SIG_FXOGS DAHDI_SIG_FXOGS
176 #define SIG_FXOKS DAHDI_SIG_FXOKS
177 #define SIG_PRI DAHDI_SIG_CLEAR
178 #define SIG_SF DAHDI_SIG_SF
179 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
180 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
181 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
182 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
183 #define SIG_EM_E1 DAHDI_SIG_EM_E1
184 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
185 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
187 #define NUM_SPANS DAHDI_MAX_SPANS /*!< no. of spans: DAHDI limitation */
188 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
189 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
191 #define CHAN_PSEUDO -2
193 #define DCHAN_PROVISIONED (1 << 0)
194 #define DCHAN_NOTINALARM (1 << 1)
195 #define DCHAN_UP (1 << 2)
197 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
199 static char defaultcic[64] = "";
200 static char defaultozz[64] = "";
202 static char progzone[10] = "";
204 static int distinctiveringaftercid = 0;
206 static int numbufs = 4;
208 #ifdef HAVE_PRI
209 static struct ast_channel inuse;
210 #ifdef PRI_GETSET_TIMERS
211 static int pritimers[PRI_MAX_TIMERS];
212 #endif
213 static int pridebugfd = -1;
214 static char pridebugfilename[1024] = "";
215 #endif
217 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
218 static int firstdigittimeout = 16000;
220 /*! \brief How long to wait for following digits (FXO logic) */
221 static int gendigittimeout = 8000;
223 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
224 static int matchdigittimeout = 3000;
226 /*! \brief Protect the interface list (of dahdi_pvt's) */
227 AST_MUTEX_DEFINE_STATIC(iflock);
230 static int ifcount = 0;
232 #ifdef HAVE_PRI
233 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
234 #endif
236 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
237 when it's doing something critical. */
238 AST_MUTEX_DEFINE_STATIC(monlock);
240 /*! \brief This is the thread for the monitor which checks for input on the channels
241 which are not currently in use. */
242 static pthread_t monitor_thread = AST_PTHREADT_NULL;
243 static ast_cond_t ss_thread_complete;
244 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
245 AST_MUTEX_DEFINE_STATIC(restart_lock);
246 static int ss_thread_count = 0;
247 static int num_restart_pending = 0;
249 static int restart_monitor(void);
251 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
253 static int dahdi_sendtext(struct ast_channel *c, const char *text);
255 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
256 static inline int dahdi_get_event(int fd)
258 int j;
259 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
260 return -1;
261 return j;
264 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
265 static inline int dahdi_wait_event(int fd)
267 int i, j = 0;
268 i = DAHDI_IOMUX_SIGEVENT;
269 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
270 return -1;
271 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
272 return -1;
273 return j;
276 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
277 #define READ_SIZE 160
279 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
280 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
282 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) /*!< 300 ms */
283 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
284 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) /*!< 500 ms */
285 #define MIN_MS_SINCE_FLASH ( (2000) ) /*!< 2000 ms */
286 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
288 struct dahdi_pvt;
290 static int ringt_base = DEFAULT_RINGT;
292 #ifdef HAVE_PRI
294 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
295 #define PRI_CHANNEL(p) ((p) & 0xff)
296 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
297 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
299 struct dahdi_pri {
300 pthread_t master; /*!< Thread of master */
301 ast_mutex_t lock; /*!< Mutex */
302 char idleext[AST_MAX_EXTENSION]; /*!< Where to idle extra calls */
303 char idlecontext[AST_MAX_CONTEXT]; /*!< What context to use for idle */
304 char idledial[AST_MAX_EXTENSION]; /*!< What to dial before dumping */
305 int minunused; /*!< Min # of channels to keep empty */
306 int minidle; /*!< Min # of "idling" calls to keep active */
307 int nodetype; /*!< Node type */
308 int switchtype; /*!< Type of switch to emulate */
309 int nsf; /*!< Network-Specific Facilities */
310 int dialplan; /*!< Dialing plan */
311 int localdialplan; /*!< Local dialing plan */
312 char nocid[AST_MAX_EXTENSION]; /*!< CallerID string to use if none provided */
313 char withheldcid[AST_MAX_EXTENSION]; /*!< CallerID string to use if CallerID is withheld */
314 char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
315 char nationalprefix[10]; /*!< area access code ('0' for european dialplans) */
316 char localprefix[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
317 char privateprefix[20]; /*!< for private dialplans */
318 char unknownprefix[20]; /*!< for unknown dialplans */
319 int dchannels[NUM_DCHANS]; /*!< What channel are the dchannels on */
320 int trunkgroup; /*!< What our trunkgroup is */
321 int mastertrunkgroup; /*!< What trunk group is our master */
322 int prilogicalspan; /*!< Logical span number within trunk group */
323 int numchans; /*!< Num of channels we represent */
324 int overlapdial; /*!< In overlap dialing mode */
325 int facilityenable; /*!< Enable facility IEs */
326 struct pri *dchans[NUM_DCHANS]; /*!< Actual d-channels */
327 int dchanavail[NUM_DCHANS]; /*!< Whether each channel is available */
328 struct pri *pri; /*!< Currently active D-channel */
329 int debug;
330 int fds[NUM_DCHANS]; /*!< FD's for d-channels */
331 int offset;
332 int span;
333 int resetting;
334 int resetpos;
335 #ifdef HAVE_PRI_INBANDDISCONNECT
336 unsigned int inbanddisconnect:1; /*!< Should we support inband audio after receiving DISCONNECT? */
337 #endif
338 time_t lastreset; /*!< time when unused channels were last reset */
339 long resetinterval; /*!< Interval (in seconds) for resetting unused channels */
340 struct dahdi_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
341 struct dahdi_pvt *crvs; /*!< Member CRV structs */
342 struct dahdi_pvt *crvend; /*!< Pointer to end of CRV structs */
346 static struct dahdi_pri pris[NUM_SPANS];
348 #if 0
349 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
350 #else
351 #define DEFAULT_PRI_DEBUG 0
352 #endif
354 static inline void pri_rel(struct dahdi_pri *pri)
356 ast_mutex_unlock(&pri->lock);
359 #else
360 /*! Shut up the compiler */
361 struct dahdi_pri;
362 #endif
364 #define SUB_REAL 0 /*!< Active call */
365 #define SUB_CALLWAIT 1 /*!< Call-Waiting call on hold */
366 #define SUB_THREEWAY 2 /*!< Three-way call */
368 /* Polarity states */
369 #define POLARITY_IDLE 0
370 #define POLARITY_REV 1
373 static struct dahdi_distRings drings;
375 struct distRingData {
376 int ring[3];
378 struct ringContextData {
379 char contextData[AST_MAX_CONTEXT];
381 struct dahdi_distRings {
382 struct distRingData ringnum[3];
383 struct ringContextData ringContext[3];
386 static char *subnames[] = {
387 "Real",
388 "Callwait",
389 "Threeway"
392 struct dahdi_subchannel {
393 int dfd;
394 struct ast_channel *owner;
395 int chan;
396 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
397 struct ast_frame f; /*!< One frame for each channel. How did this ever work before? */
398 unsigned int needringing:1;
399 unsigned int needbusy:1;
400 unsigned int needcongestion:1;
401 unsigned int needcallerid:1;
402 unsigned int needanswer:1;
403 unsigned int needflash:1;
404 unsigned int needhold:1;
405 unsigned int needunhold:1;
406 unsigned int linear:1;
407 unsigned int inthreeway:1;
408 struct dahdi_confinfo curconf;
411 #define CONF_USER_REAL (1 << 0)
412 #define CONF_USER_THIRDCALL (1 << 1)
414 #define MAX_SLAVES 4
416 static struct dahdi_pvt {
417 ast_mutex_t lock;
418 struct ast_channel *owner; /*!< Our current active owner (if applicable) */
419 /*!< Up to three channels can be associated with this call */
421 struct dahdi_subchannel sub_unused; /*!< Just a safety precaution */
422 struct dahdi_subchannel subs[3]; /*!< Sub-channels */
423 struct dahdi_confinfo saveconf; /*!< Saved conference info */
425 struct dahdi_pvt *slaves[MAX_SLAVES]; /*!< Slave to us (follows our conferencing) */
426 struct dahdi_pvt *master; /*!< Master to us (we follow their conferencing) */
427 int inconference; /*!< If our real should be in the conference */
429 int buf_no; /*!< Number of buffers */
430 int buf_policy; /*!< Buffer policy */
431 int sig; /*!< Signalling style */
432 int radio; /*!< radio type */
433 int outsigmod; /*!< Outbound Signalling style (modifier) */
434 int oprmode; /*!< "Operator Services" mode */
435 struct dahdi_pvt *oprpeer; /*!< "Operator Services" peer tech_pvt ptr */
436 float rxgain;
437 float txgain;
438 int tonezone; /*!< tone zone for this chan, or -1 for default */
439 struct dahdi_pvt *next; /*!< Next channel in list */
440 struct dahdi_pvt *prev; /*!< Prev channel in list */
442 /* flags */
443 unsigned int adsi:1;
444 unsigned int answeronpolarityswitch:1;
445 unsigned int busydetect:1;
446 unsigned int callreturn:1;
447 unsigned int callwaiting:1;
448 unsigned int callwaitingcallerid:1;
449 unsigned int cancallforward:1;
450 unsigned int canpark:1;
451 unsigned int confirmanswer:1; /*!< Wait for '#' to confirm answer */
452 unsigned int destroy:1;
453 unsigned int didtdd:1; /*!< flag to say its done it once */
454 unsigned int dialednone:1;
455 unsigned int dialing:1;
456 unsigned int digital:1;
457 unsigned int dnd:1;
458 unsigned int echobreak:1;
459 unsigned int echocanbridged:1;
460 unsigned int echocanon:1;
461 unsigned int faxhandled:1; /*!< Has a fax tone already been handled? */
462 unsigned int firstradio:1;
463 unsigned int hanguponpolarityswitch:1;
464 unsigned int hardwaredtmf:1;
465 unsigned int hidecallerid:1;
466 unsigned int hidecalleridname:1; /*!< Hide just the name not the number for legacy PBX use */
467 unsigned int ignoredtmf:1;
468 unsigned int immediate:1; /*!< Answer before getting digits? */
469 unsigned int inalarm:1;
470 unsigned int unknown_alarm:1;
471 unsigned int mate:1; /*!< flag to say its in MATE mode */
472 unsigned int outgoing:1;
473 unsigned int overlapdial:1;
474 unsigned int permcallwaiting:1;
475 unsigned int permhidecallerid:1; /*!< Whether to hide our outgoing caller ID or not */
476 unsigned int priindication_oob:1;
477 unsigned int priexclusive:1;
478 unsigned int pulse:1;
479 unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */
480 unsigned int restartpending:1; /*!< flag to ensure counted only once for restart */
481 unsigned int restrictcid:1; /*!< Whether restrict the callerid -> only send ANI */
482 unsigned int threewaycalling:1;
483 unsigned int transfer:1;
484 unsigned int use_callerid:1; /*!< Whether or not to use caller id on this channel */
485 unsigned int use_callingpres:1; /*!< Whether to use the callingpres the calling switch sends */
486 unsigned int usedistinctiveringdetection:1;
487 unsigned int dahditrcallerid:1; /*!< should we use the callerid from incoming call on dahdi transfer or not */
488 unsigned int transfertobusy:1; /*!< allow flash-transfers to busy channels */
489 #if defined(HAVE_PRI)
490 unsigned int alerting:1;
491 unsigned int alreadyhungup:1;
492 unsigned int isidlecall:1;
493 unsigned int proceeding:1;
494 unsigned int progress:1;
495 unsigned int resetting:1;
496 unsigned int setup_ack:1;
497 #endif
498 unsigned int use_smdi:1; /* Whether to use SMDI on this channel */
499 struct ast_smdi_interface *smdi_iface; /* The serial port to listen for SMDI data on */
501 struct dahdi_distRings drings;
503 char context[AST_MAX_CONTEXT];
504 char defcontext[AST_MAX_CONTEXT];
505 char exten[AST_MAX_EXTENSION];
506 char language[MAX_LANGUAGE];
507 char mohinterpret[MAX_MUSICCLASS];
508 char mohsuggest[MAX_MUSICCLASS];
509 #ifdef PRI_ANI
510 char cid_ani[AST_MAX_EXTENSION];
511 #endif
512 char cid_num[AST_MAX_EXTENSION];
513 int cid_ton; /*!< Type Of Number (TON) */
514 int cid_pres; /*!< Calling Presentation */
515 char cid_name[AST_MAX_EXTENSION];
516 char lastcid_num[AST_MAX_EXTENSION];
517 char lastcid_name[AST_MAX_EXTENSION];
518 char *origcid_num; /*!< malloced original callerid */
519 char *origcid_name; /*!< malloced original callerid */
520 char callwait_num[AST_MAX_EXTENSION];
521 char callwait_name[AST_MAX_EXTENSION];
522 char rdnis[AST_MAX_EXTENSION];
523 char dnid[AST_MAX_EXTENSION];
524 ast_group_t group;
525 int law;
526 int confno; /*!< Our conference */
527 int confusers; /*!< Who is using our conference */
528 int propconfno; /*!< Propagated conference number */
529 ast_group_t callgroup;
530 ast_group_t pickupgroup;
531 int channel; /*!< Channel Number or CRV */
532 int span; /*!< Span number */
533 time_t guardtime; /*!< Must wait this much time before using for new call */
534 int cid_signalling; /*!< CID signalling type bell202 or v23 */
535 int cid_start; /*!< CID start indicator, polarity or ring */
536 int callingpres; /*!< The value of callling presentation that we're going to use when placing a PRI call */
537 int callwaitingrepeat; /*!< How many samples to wait before repeating call waiting */
538 int cidcwexpire; /*!< When to expire our muting for CID/CW */
539 unsigned char *cidspill;
540 int cidpos;
541 int cidlen;
542 int ringt;
543 int ringt_base;
544 int stripmsd;
545 int callwaitcas;
546 int callwaitrings;
547 int echocancel;
548 int echotraining;
549 char echorest[20];
550 int busycount;
551 int busy_tonelength;
552 int busy_quietlength;
553 int callprogress;
554 struct timeval flashtime; /*!< Last flash-hook time */
555 struct ast_dsp *dsp;
556 int cref; /*!< Call reference number */
557 struct dahdi_dialoperation dop;
558 int whichwink; /*!< SIG_FEATDMF_TA Which wink are we on? */
559 char finaldial[64];
560 char accountcode[AST_MAX_ACCOUNT_CODE]; /*!< Account code */
561 int amaflags; /*!< AMA Flags */
562 struct tdd_state *tdd; /*!< TDD flag */
563 char call_forward[AST_MAX_EXTENSION];
564 char mailbox[AST_MAX_EXTENSION];
565 char dialdest[256];
566 int onhooktime;
567 int msgstate;
568 int distinctivering; /*!< Which distinctivering to use */
569 int cidrings; /*!< Which ring to deliver CID on */
570 int dtmfrelax; /*!< whether to run in relaxed DTMF mode */
571 int fake_event;
572 int polarityonanswerdelay;
573 struct timeval polaritydelaytv;
574 int sendcalleridafter;
575 #ifdef HAVE_PRI
576 struct dahdi_pri *pri;
577 struct dahdi_pvt *bearer;
578 struct dahdi_pvt *realcall;
579 q931_call *call;
580 int prioffset;
581 int logicalspan;
582 #endif
583 int polarity;
584 int dsp_features;
585 char begindigit;
586 } *iflist = NULL, *ifend = NULL;
588 /*! \brief Channel configuration from chan_dahdi.conf .
589 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
590 * Generally there is a field here for every possible configuration item.
592 * The state of fields is saved along the parsing and whenever a 'channel'
593 * statement is reached, the current dahdi_chan_conf is used to configure the
594 * channel (struct dahdi_pvt)
596 * @seealso dahdi_chan_init for the default values.
598 struct dahdi_chan_conf {
599 struct dahdi_pvt chan;
600 #ifdef HAVE_PRI
601 struct dahdi_pri pri;
602 #endif
603 struct dahdi_params timing;
605 char smdi_port[SMDI_MAX_FILENAME_LEN];
608 /** returns a new dahdi_chan_conf with default values (by-value) */
609 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
610 /* recall that if a field is not included here it is initialized
611 * to 0 or equivalent
613 struct dahdi_chan_conf conf = {
614 #ifdef HAVE_PRI
615 .pri = {
616 .nsf = PRI_NSF_NONE,
617 .switchtype = PRI_SWITCH_NI2,
618 .dialplan = PRI_NATIONAL_ISDN + 1,
619 .localdialplan = PRI_NATIONAL_ISDN + 1,
620 .nodetype = PRI_CPE,
622 .minunused = 2,
623 .idleext = "",
624 .idledial = "",
625 .nocid = "No CID available",
626 .withheldcid = "CID withheld",
627 .internationalprefix = "",
628 .nationalprefix = "",
629 .localprefix = "",
630 .privateprefix = "",
631 .unknownprefix = "",
633 .resetinterval = 3600
635 #endif
636 .chan = {
637 .context = "default",
638 .cid_num = "",
639 .cid_name = "",
640 .mohinterpret = "default",
641 .mohsuggest = "",
642 .transfertobusy = 1,
644 .cid_signalling = CID_SIG_BELL,
645 .cid_start = CID_START_RING,
646 .dahditrcallerid = 0,
647 .use_callerid = 1,
648 .sig = -1,
649 .outsigmod = -1,
651 .tonezone = -1,
653 .echocancel = 1,
655 .busycount = 3,
657 .accountcode = "",
659 .mailbox = "",
662 .polarityonanswerdelay = 600,
664 .sendcalleridafter = DEFAULT_CIDRINGS,
666 .buf_policy = DAHDI_POLICY_IMMEDIATE,
667 .buf_no = numbufs
669 .timing = {
670 .prewinktime = -1,
671 .preflashtime = -1,
672 .winktime = -1,
673 .flashtime = -1,
674 .starttime = -1,
675 .rxwinktime = -1,
676 .rxflashtime = -1,
677 .debouncetime = -1
679 .smdi_port = "/dev/ttyS0",
682 return conf;
686 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
687 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
688 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
689 static int dahdi_sendtext(struct ast_channel *c, const char *text);
690 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
691 static int dahdi_hangup(struct ast_channel *ast);
692 static int dahdi_answer(struct ast_channel *ast);
693 static struct ast_frame *dahdi_read(struct ast_channel *ast);
694 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
695 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
696 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
697 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
698 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
699 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len);
701 static const struct ast_channel_tech dahdi_tech = {
702 .type = "DAHDI",
703 .description = tdesc,
704 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
705 .requester = dahdi_request,
706 .send_digit_begin = dahdi_digit_begin,
707 .send_digit_end = dahdi_digit_end,
708 .send_text = dahdi_sendtext,
709 .call = dahdi_call,
710 .hangup = dahdi_hangup,
711 .answer = dahdi_answer,
712 .read = dahdi_read,
713 .write = dahdi_write,
714 .bridge = dahdi_bridge,
715 .exception = dahdi_exception,
716 .indicate = dahdi_indicate,
717 .fixup = dahdi_fixup,
718 .setoption = dahdi_setoption,
719 .func_channel_read = dahdi_func_read,
722 static const struct ast_channel_tech zap_tech = {
723 .type = "Zap",
724 .description = tdesc,
725 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
726 .requester = dahdi_request,
727 .send_digit_begin = dahdi_digit_begin,
728 .send_digit_end = dahdi_digit_end,
729 .send_text = dahdi_sendtext,
730 .call = dahdi_call,
731 .hangup = dahdi_hangup,
732 .answer = dahdi_answer,
733 .read = dahdi_read,
734 .write = dahdi_write,
735 .bridge = dahdi_bridge,
736 .exception = dahdi_exception,
737 .indicate = dahdi_indicate,
738 .fixup = dahdi_fixup,
739 .setoption = dahdi_setoption,
740 .func_channel_read = dahdi_func_read,
743 static const struct ast_channel_tech *chan_tech;
745 #ifdef HAVE_PRI
746 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
747 #else
748 #define GET_CHANNEL(p) ((p)->channel)
749 #endif
751 struct dahdi_pvt *round_robin[32];
753 #ifdef HAVE_PRI
754 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
756 int res;
757 /* Grab the lock first */
758 do {
759 res = ast_mutex_trylock(&pri->lock);
760 if (res) {
761 DEADLOCK_AVOIDANCE(&pvt->lock);
763 } while (res);
764 /* Then break the poll */
765 if (pri->master != AST_PTHREADT_NULL)
766 pthread_kill(pri->master, SIGURG);
767 return 0;
769 #endif
771 #define NUM_CADENCE_MAX 25
772 static int num_cadence = 4;
773 static int user_has_defined_cadences = 0;
775 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
776 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
777 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
778 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
779 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
782 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
783 * is 1, the second pause is 2 and so on.
786 static int cidrings[NUM_CADENCE_MAX] = {
787 2, /*!< Right after first long ring */
788 4, /*!< Right after long part */
789 3, /*!< After third chirp */
790 2, /*!< Second spell */
793 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
794 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
796 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
797 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
799 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
801 int res;
802 if (p->subs[SUB_REAL].owner == ast)
803 res = 0;
804 else if (p->subs[SUB_CALLWAIT].owner == ast)
805 res = 1;
806 else if (p->subs[SUB_THREEWAY].owner == ast)
807 res = 2;
808 else {
809 res = -1;
810 if (!nullok)
811 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
813 return res;
816 #ifdef HAVE_PRI
817 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
818 #else
819 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
820 #endif
822 #ifdef HAVE_PRI
823 if (pri)
824 ast_mutex_unlock(&pri->lock);
825 #endif
826 for (;;) {
827 if (p->subs[a].owner) {
828 if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
829 DEADLOCK_AVOIDANCE(&p->lock);
830 } else {
831 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
832 ast_mutex_unlock(&p->subs[a].owner->lock);
833 break;
835 } else
836 break;
838 #ifdef HAVE_PRI
839 if (pri)
840 ast_mutex_lock(&pri->lock);
841 #endif
844 #ifdef HAVE_PRI
845 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
846 #else
847 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)
848 #endif
850 /* We must unlock the PRI to avoid the possibility of a deadlock */
851 #ifdef HAVE_PRI
852 if (pri)
853 ast_mutex_unlock(&pri->lock);
854 #endif
855 for (;;) {
856 if (p->owner) {
857 if (ast_mutex_trylock(&p->owner->lock)) {
858 DEADLOCK_AVOIDANCE(&p->lock);
859 } else {
860 ast_queue_frame(p->owner, f);
861 ast_mutex_unlock(&p->owner->lock);
862 break;
864 } else
865 break;
867 #ifdef HAVE_PRI
868 if (pri)
869 ast_mutex_lock(&pri->lock);
870 #endif
873 static int restore_gains(struct dahdi_pvt *p);
875 static void swap_subs(struct dahdi_pvt *p, int a, int b)
877 int tchan;
878 int tinthreeway;
879 struct ast_channel *towner;
881 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
883 tchan = p->subs[a].chan;
884 towner = p->subs[a].owner;
885 tinthreeway = p->subs[a].inthreeway;
887 p->subs[a].chan = p->subs[b].chan;
888 p->subs[a].owner = p->subs[b].owner;
889 p->subs[a].inthreeway = p->subs[b].inthreeway;
891 p->subs[b].chan = tchan;
892 p->subs[b].owner = towner;
893 p->subs[b].inthreeway = tinthreeway;
895 if (p->subs[a].owner)
896 p->subs[a].owner->fds[0] = p->subs[a].dfd;
897 if (p->subs[b].owner)
898 p->subs[b].owner->fds[0] = p->subs[b].dfd;
899 wakeup_sub(p, a, NULL);
900 wakeup_sub(p, b, NULL);
903 static int dahdi_open(char *fn)
905 int fd;
906 int isnum;
907 int chan = 0;
908 int bs;
909 int x;
910 isnum = 1;
911 for (x = 0; x < strlen(fn); x++) {
912 if (!isdigit(fn[x])) {
913 isnum = 0;
914 break;
917 if (isnum) {
918 chan = atoi(fn);
919 if (chan < 1) {
920 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
921 return -1;
923 #ifdef HAVE_ZAPTEL
924 fn = "/dev/zap/channel";
925 #else
926 fn = "/dev/dahdi/channel";
927 #endif
929 fd = open(fn, O_RDWR | O_NONBLOCK);
930 if (fd < 0) {
931 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
932 return -1;
934 if (chan) {
935 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
936 x = errno;
937 close(fd);
938 errno = x;
939 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
940 return -1;
943 bs = READ_SIZE;
944 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
945 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
946 x = errno;
947 close(fd);
948 errno = x;
949 return -1;
951 return fd;
954 static void dahdi_close(int fd)
956 if (fd > 0)
957 close(fd);
960 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
962 dahdi_close(chan_pvt->subs[sub_num].dfd);
963 chan_pvt->subs[sub_num].dfd = -1;
966 #ifdef HAVE_PRI
967 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
969 dahdi_close(pri->fds[fd_num]);
970 pri->fds[fd_num] = -1;
972 #endif
974 static int dahdi_setlinear(int dfd, int linear)
976 int res;
977 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
978 if (res)
979 return res;
980 return 0;
984 static int alloc_sub(struct dahdi_pvt *p, int x)
986 struct dahdi_bufferinfo bi;
987 int res;
988 if (p->subs[x].dfd < 0) {
989 #ifdef HAVE_ZAPTEL
990 p->subs[x].dfd = dahdi_open("/dev/zap/pseudo");
991 #else
992 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
993 #endif
994 if (p->subs[x].dfd > -1) {
995 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
996 if (!res) {
997 bi.txbufpolicy = p->buf_policy;
998 bi.rxbufpolicy = p->buf_policy;
999 bi.numbufs = p->buf_no;
1000 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
1001 if (res < 0) {
1002 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
1004 } else
1005 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
1006 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
1007 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
1008 dahdi_close_sub(p, x);
1009 return -1;
1011 if (option_debug)
1012 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
1013 return 0;
1014 } else
1015 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
1016 return -1;
1018 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
1019 return -1;
1022 static int unalloc_sub(struct dahdi_pvt *p, int x)
1024 if (!x) {
1025 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
1026 return -1;
1028 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
1029 dahdi_close_sub(p, x);
1030 p->subs[x].linear = 0;
1031 p->subs[x].chan = 0;
1032 p->subs[x].owner = NULL;
1033 p->subs[x].inthreeway = 0;
1034 p->polarity = POLARITY_IDLE;
1035 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
1036 return 0;
1039 static int digit_to_dtmfindex(char digit)
1041 if (isdigit(digit))
1042 return DAHDI_TONE_DTMF_BASE + (digit - '0');
1043 else if (digit >= 'A' && digit <= 'D')
1044 return DAHDI_TONE_DTMF_A + (digit - 'A');
1045 else if (digit >= 'a' && digit <= 'd')
1046 return DAHDI_TONE_DTMF_A + (digit - 'a');
1047 else if (digit == '*')
1048 return DAHDI_TONE_DTMF_s;
1049 else if (digit == '#')
1050 return DAHDI_TONE_DTMF_p;
1051 else
1052 return -1;
1055 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
1057 struct dahdi_pvt *pvt;
1058 int index;
1059 int dtmf = -1;
1061 pvt = chan->tech_pvt;
1063 ast_mutex_lock(&pvt->lock);
1065 index = dahdi_get_index(chan, pvt, 0);
1067 if ((index != SUB_REAL) || !pvt->owner)
1068 goto out;
1070 #ifdef HAVE_PRI
1071 if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
1072 if (pvt->setup_ack) {
1073 if (!pri_grab(pvt, pvt->pri)) {
1074 pri_information(pvt->pri->pri, pvt->call, digit);
1075 pri_rel(pvt->pri);
1076 } else
1077 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
1078 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
1079 int res;
1080 ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
1081 res = strlen(pvt->dialdest);
1082 pvt->dialdest[res++] = digit;
1083 pvt->dialdest[res] = '\0';
1085 goto out;
1087 #endif
1088 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
1089 goto out;
1091 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
1092 int res;
1093 struct dahdi_dialoperation zo = {
1094 .op = DAHDI_DIAL_OP_APPEND,
1095 .dialstr[0] = 'T',
1096 .dialstr[1] = digit,
1097 .dialstr[2] = 0,
1099 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
1100 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
1101 else
1102 pvt->dialing = 1;
1103 } else {
1104 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
1105 pvt->dialing = 1;
1106 pvt->begindigit = digit;
1109 out:
1110 ast_mutex_unlock(&pvt->lock);
1112 return 0;
1115 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
1117 struct dahdi_pvt *pvt;
1118 int res = 0;
1119 int index;
1120 int x;
1122 pvt = chan->tech_pvt;
1124 ast_mutex_lock(&pvt->lock);
1126 index = dahdi_get_index(chan, pvt, 0);
1128 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
1129 goto out;
1131 #ifdef HAVE_PRI
1132 /* This means that the digit was already sent via PRI signalling */
1133 if (pvt->sig == SIG_PRI && !pvt->begindigit)
1134 goto out;
1135 #endif
1137 if (pvt->begindigit) {
1138 x = -1;
1139 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
1140 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
1141 pvt->dialing = 0;
1142 pvt->begindigit = 0;
1145 out:
1146 ast_mutex_unlock(&pvt->lock);
1148 return res;
1151 static char *events[] = {
1152 "No event",
1153 "On hook",
1154 "Ring/Answered",
1155 "Wink/Flash",
1156 "Alarm",
1157 "No more alarm",
1158 "HDLC Abort",
1159 "HDLC Overrun",
1160 "HDLC Bad FCS",
1161 "Dial Complete",
1162 "Ringer On",
1163 "Ringer Off",
1164 "Hook Transition Complete",
1165 "Bits Changed",
1166 "Pulse Start",
1167 "Timer Expired",
1168 "Timer Ping",
1169 "Polarity Reversal",
1170 "Ring Begin",
1173 static struct {
1174 int alarm;
1175 char *name;
1176 } alarms[] = {
1177 { DAHDI_ALARM_RED, "Red Alarm" },
1178 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
1179 { DAHDI_ALARM_BLUE, "Blue Alarm" },
1180 { DAHDI_ALARM_RECOVER, "Recovering" },
1181 { DAHDI_ALARM_LOOPBACK, "Loopback" },
1182 { DAHDI_ALARM_NOTOPEN, "Not Open" },
1183 { DAHDI_ALARM_NONE, "None" },
1186 static char *alarm2str(int alarm)
1188 int x;
1189 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
1190 if (alarms[x].alarm & alarm)
1191 return alarms[x].name;
1193 return alarm ? "Unknown Alarm" : "No Alarm";
1196 static char *event2str(int event)
1198 static char buf[256];
1199 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
1200 return events[event];
1201 sprintf(buf, "Event %d", event); /* safe */
1202 return buf;
1205 #ifdef HAVE_PRI
1206 static char *dialplan2str(int dialplan)
1208 if (dialplan == -1) {
1209 return("Dynamically set dialplan in ISDN");
1211 return (pri_plan2str(dialplan));
1213 #endif
1215 static char *dahdi_sig2str(int sig)
1217 static char buf[256];
1218 switch (sig) {
1219 case SIG_EM:
1220 return "E & M Immediate";
1221 case SIG_EMWINK:
1222 return "E & M Wink";
1223 case SIG_EM_E1:
1224 return "E & M E1";
1225 case SIG_FEATD:
1226 return "Feature Group D (DTMF)";
1227 case SIG_FEATDMF:
1228 return "Feature Group D (MF)";
1229 case SIG_FEATDMF_TA:
1230 return "Feature Groud D (MF) Tandem Access";
1231 case SIG_FEATB:
1232 return "Feature Group B (MF)";
1233 case SIG_E911:
1234 return "E911 (MF)";
1235 case SIG_FGC_CAMA:
1236 return "FGC/CAMA (Dialpulse)";
1237 case SIG_FGC_CAMAMF:
1238 return "FGC/CAMA (MF)";
1239 case SIG_FXSLS:
1240 return "FXS Loopstart";
1241 case SIG_FXSGS:
1242 return "FXS Groundstart";
1243 case SIG_FXSKS:
1244 return "FXS Kewlstart";
1245 case SIG_FXOLS:
1246 return "FXO Loopstart";
1247 case SIG_FXOGS:
1248 return "FXO Groundstart";
1249 case SIG_FXOKS:
1250 return "FXO Kewlstart";
1251 case SIG_PRI:
1252 return "ISDN PRI";
1253 case SIG_SF:
1254 return "SF (Tone) Immediate";
1255 case SIG_SFWINK:
1256 return "SF (Tone) Wink";
1257 case SIG_SF_FEATD:
1258 return "SF (Tone) with Feature Group D (DTMF)";
1259 case SIG_SF_FEATDMF:
1260 return "SF (Tone) with Feature Group D (MF)";
1261 case SIG_SF_FEATB:
1262 return "SF (Tone) with Feature Group B (MF)";
1263 case SIG_GR303FXOKS:
1264 return "GR-303 with FXOKS";
1265 case SIG_GR303FXSKS:
1266 return "GR-303 with FXSKS";
1267 case 0:
1268 return "Pseudo";
1269 default:
1270 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
1271 return buf;
1275 #define sig2str dahdi_sig2str
1277 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
1279 /* If the conference already exists, and we're already in it
1280 don't bother doing anything */
1281 struct dahdi_confinfo zi;
1283 memset(&zi, 0, sizeof(zi));
1284 zi.chan = 0;
1286 if (slavechannel > 0) {
1287 /* If we have only one slave, do a digital mon */
1288 zi.confmode = DAHDI_CONF_DIGITALMON;
1289 zi.confno = slavechannel;
1290 } else {
1291 if (!index) {
1292 /* Real-side and pseudo-side both participate in conference */
1293 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
1294 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
1295 } else
1296 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
1297 zi.confno = p->confno;
1299 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
1300 return 0;
1301 if (c->dfd < 0)
1302 return 0;
1303 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
1304 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
1305 return -1;
1307 if (slavechannel < 1) {
1308 p->confno = zi.confno;
1310 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1311 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
1312 return 0;
1315 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
1317 /* If they're listening to our channel, they're ours */
1318 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
1319 return 1;
1320 /* If they're a talker on our (allocated) conference, they're ours */
1321 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
1322 return 1;
1323 return 0;
1326 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
1328 struct dahdi_confinfo zi;
1329 if (/* Can't delete if there's no dfd */
1330 (c->dfd < 0) ||
1331 /* Don't delete from the conference if it's not our conference */
1332 !isourconf(p, c)
1333 /* Don't delete if we don't think it's conferenced at all (implied) */
1334 ) return 0;
1335 memset(&zi, 0, sizeof(zi));
1336 zi.chan = 0;
1337 zi.confno = 0;
1338 zi.confmode = 0;
1339 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
1340 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
1341 return -1;
1343 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
1344 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1345 return 0;
1348 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
1350 int x;
1351 int useslavenative;
1352 struct dahdi_pvt *slave = NULL;
1353 /* Start out optimistic */
1354 useslavenative = 1;
1355 /* Update conference state in a stateless fashion */
1356 for (x = 0; x < 3; x++) {
1357 /* Any three-way calling makes slave native mode *definitely* out
1358 of the question */
1359 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
1360 useslavenative = 0;
1362 /* If we don't have any 3-way calls, check to see if we have
1363 precisely one slave */
1364 if (useslavenative) {
1365 for (x = 0; x < MAX_SLAVES; x++) {
1366 if (p->slaves[x]) {
1367 if (slave) {
1368 /* Whoops already have a slave! No
1369 slave native and stop right away */
1370 slave = NULL;
1371 useslavenative = 0;
1372 break;
1373 } else {
1374 /* We have one slave so far */
1375 slave = p->slaves[x];
1380 /* If no slave, slave native definitely out */
1381 if (!slave)
1382 useslavenative = 0;
1383 else if (slave->law != p->law) {
1384 useslavenative = 0;
1385 slave = NULL;
1387 if (out)
1388 *out = slave;
1389 return useslavenative;
1392 static int reset_conf(struct dahdi_pvt *p)
1394 struct dahdi_confinfo zi;
1395 memset(&zi, 0, sizeof(zi));
1396 p->confno = -1;
1397 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
1398 if (p->subs[SUB_REAL].dfd > -1) {
1399 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
1400 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
1402 return 0;
1405 static int update_conf(struct dahdi_pvt *p)
1407 int needconf = 0;
1408 int x;
1409 int useslavenative;
1410 struct dahdi_pvt *slave = NULL;
1412 useslavenative = isslavenative(p, &slave);
1413 /* Start with the obvious, general stuff */
1414 for (x = 0; x < 3; x++) {
1415 /* Look for three way calls */
1416 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
1417 conf_add(p, &p->subs[x], x, 0);
1418 needconf++;
1419 } else {
1420 conf_del(p, &p->subs[x], x);
1423 /* If we have a slave, add him to our conference now. or DAX
1424 if this is slave native */
1425 for (x = 0; x < MAX_SLAVES; x++) {
1426 if (p->slaves[x]) {
1427 if (useslavenative)
1428 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
1429 else {
1430 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
1431 needconf++;
1435 /* If we're supposed to be in there, do so now */
1436 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
1437 if (useslavenative)
1438 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
1439 else {
1440 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
1441 needconf++;
1444 /* If we have a master, add ourselves to his conference */
1445 if (p->master) {
1446 if (isslavenative(p->master, NULL)) {
1447 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
1448 } else {
1449 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
1452 if (!needconf) {
1453 /* Nobody is left (or should be left) in our conference.
1454 Kill it. */
1455 p->confno = -1;
1457 if (option_debug)
1458 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
1459 return 0;
1462 static void dahdi_enable_ec(struct dahdi_pvt *p)
1464 int x;
1465 int res;
1466 if (!p)
1467 return;
1468 if (p->echocanon) {
1469 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
1470 return;
1472 if (p->digital) {
1473 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
1474 return;
1476 if (p->echocancel) {
1477 if (p->sig == SIG_PRI) {
1478 x = 1;
1479 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
1480 if (res)
1481 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
1483 x = p->echocancel;
1484 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
1485 if (res)
1486 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
1487 else {
1488 p->echocanon = 1;
1489 if (option_debug)
1490 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
1492 } else if (option_debug)
1493 ast_log(LOG_DEBUG, "No echo cancellation requested\n");
1496 static void dahdi_train_ec(struct dahdi_pvt *p)
1498 int x;
1499 int res;
1500 if (p && p->echocancel && p->echotraining) {
1501 x = p->echotraining;
1502 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
1503 if (res)
1504 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
1505 else {
1506 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
1508 } else
1509 ast_log(LOG_DEBUG, "No echo training requested\n");
1512 static void dahdi_disable_ec(struct dahdi_pvt *p)
1514 int x;
1515 int res;
1516 if (p->echocancel) {
1517 x = 0;
1518 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
1519 if (res)
1520 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
1521 else if (option_debug)
1522 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
1524 p->echocanon = 0;
1527 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
1529 int j;
1530 int k;
1531 float linear_gain = pow(10.0, gain / 20.0);
1533 switch (law) {
1534 case DAHDI_LAW_ALAW:
1535 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
1536 if (gain) {
1537 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1538 if (k > 32767) k = 32767;
1539 if (k < -32767) k = -32767;
1540 g->txgain[j] = AST_LIN2A(k);
1541 } else {
1542 g->txgain[j] = j;
1545 break;
1546 case DAHDI_LAW_MULAW:
1547 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
1548 if (gain) {
1549 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1550 if (k > 32767) k = 32767;
1551 if (k < -32767) k = -32767;
1552 g->txgain[j] = AST_LIN2MU(k);
1553 } else {
1554 g->txgain[j] = j;
1557 break;
1561 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
1563 int j;
1564 int k;
1565 float linear_gain = pow(10.0, gain / 20.0);
1567 switch (law) {
1568 case DAHDI_LAW_ALAW:
1569 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
1570 if (gain) {
1571 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1572 if (k > 32767) k = 32767;
1573 if (k < -32767) k = -32767;
1574 g->rxgain[j] = AST_LIN2A(k);
1575 } else {
1576 g->rxgain[j] = j;
1579 break;
1580 case DAHDI_LAW_MULAW:
1581 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
1582 if (gain) {
1583 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1584 if (k > 32767) k = 32767;
1585 if (k < -32767) k = -32767;
1586 g->rxgain[j] = AST_LIN2MU(k);
1587 } else {
1588 g->rxgain[j] = j;
1591 break;
1595 static int set_actual_txgain(int fd, int chan, float gain, int law)
1597 struct dahdi_gains g;
1598 int res;
1600 memset(&g, 0, sizeof(g));
1601 g.chan = chan;
1602 res = ioctl(fd, DAHDI_GETGAINS, &g);
1603 if (res) {
1604 if (option_debug)
1605 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
1606 return res;
1609 fill_txgain(&g, gain, law);
1611 return ioctl(fd, DAHDI_SETGAINS, &g);
1614 static int set_actual_rxgain(int fd, int chan, float gain, int law)
1616 struct dahdi_gains g;
1617 int res;
1619 memset(&g, 0, sizeof(g));
1620 g.chan = chan;
1621 res = ioctl(fd, DAHDI_GETGAINS, &g);
1622 if (res) {
1623 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
1624 return res;
1627 fill_rxgain(&g, gain, law);
1629 return ioctl(fd, DAHDI_SETGAINS, &g);
1632 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
1634 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
1637 static int bump_gains(struct dahdi_pvt *p)
1639 int res;
1641 /* Bump receive gain by 5.0db */
1642 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
1643 if (res) {
1644 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
1645 return -1;
1648 return 0;
1651 static int restore_gains(struct dahdi_pvt *p)
1653 int res;
1655 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
1656 if (res) {
1657 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
1658 return -1;
1661 return 0;
1664 static inline int dahdi_set_hook(int fd, int hs)
1666 int x, res;
1668 x = hs;
1669 res = ioctl(fd, DAHDI_HOOK, &x);
1671 if (res < 0) {
1672 if (errno == EINPROGRESS)
1673 return 0;
1674 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
1675 /* will expectedly fail if phone is off hook during operation, such as during a restart */
1678 return res;
1681 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
1683 int x, y, res;
1684 x = muted;
1685 if (p->sig == SIG_PRI) {
1686 y = 1;
1687 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
1688 if (res)
1689 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
1691 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
1692 if (res < 0)
1693 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
1694 return res;
1697 static int save_conference(struct dahdi_pvt *p)
1699 struct dahdi_confinfo c;
1700 int res;
1701 if (p->saveconf.confmode) {
1702 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
1703 return -1;
1705 p->saveconf.chan = 0;
1706 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
1707 if (res) {
1708 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
1709 p->saveconf.confmode = 0;
1710 return -1;
1712 c.chan = 0;
1713 c.confno = 0;
1714 c.confmode = DAHDI_CONF_NORMAL;
1715 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
1716 if (res) {
1717 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
1718 return -1;
1720 if (option_debug)
1721 ast_log(LOG_DEBUG, "Disabled conferencing\n");
1722 return 0;
1725 static int restore_conference(struct dahdi_pvt *p)
1727 int res;
1728 if (p->saveconf.confmode) {
1729 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
1730 p->saveconf.confmode = 0;
1731 if (res) {
1732 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
1733 return -1;
1736 if (option_debug)
1737 ast_log(LOG_DEBUG, "Restored conferencing\n");
1738 return 0;
1741 static int send_callerid(struct dahdi_pvt *p);
1743 static int send_cwcidspill(struct dahdi_pvt *p)
1745 p->callwaitcas = 0;
1746 p->cidcwexpire = 0;
1747 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
1748 return -1;
1749 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
1750 /* Make sure we account for the end */
1751 p->cidlen += READ_SIZE * 4;
1752 p->cidpos = 0;
1753 send_callerid(p);
1754 if (option_verbose > 2)
1755 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
1756 return 0;
1759 static int has_voicemail(struct dahdi_pvt *p)
1762 return ast_app_has_voicemail(p->mailbox, NULL);
1765 static int send_callerid(struct dahdi_pvt *p)
1767 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
1768 int res;
1769 /* Take out of linear mode if necessary */
1770 if (p->subs[SUB_REAL].linear) {
1771 p->subs[SUB_REAL].linear = 0;
1772 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
1774 while (p->cidpos < p->cidlen) {
1775 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
1776 if (res < 0) {
1777 if (errno == EAGAIN)
1778 return 0;
1779 else {
1780 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
1781 return -1;
1784 if (!res)
1785 return 0;
1786 p->cidpos += res;
1788 free(p->cidspill);
1789 p->cidspill = NULL;
1790 if (p->callwaitcas) {
1791 /* Wait for CID/CW to expire */
1792 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
1793 } else
1794 restore_conference(p);
1795 return 0;
1798 static int dahdi_callwait(struct ast_channel *ast)
1800 struct dahdi_pvt *p = ast->tech_pvt;
1801 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
1802 if (p->cidspill) {
1803 ast_log(LOG_WARNING, "Spill already exists?!?\n");
1804 free(p->cidspill);
1806 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
1807 return -1;
1808 save_conference(p);
1809 /* Silence */
1810 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
1811 if (!p->callwaitrings && p->callwaitingcallerid) {
1812 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
1813 p->callwaitcas = 1;
1814 p->cidlen = 2400 + 680 + READ_SIZE * 4;
1815 } else {
1816 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
1817 p->callwaitcas = 0;
1818 p->cidlen = 2400 + READ_SIZE * 4;
1820 p->cidpos = 0;
1821 send_callerid(p);
1823 return 0;
1826 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
1828 struct dahdi_pvt *p = ast->tech_pvt;
1829 int x, res, index,mysig;
1830 char *c, *n, *l;
1831 #ifdef HAVE_PRI
1832 char *s = NULL;
1833 #endif
1834 char dest[256]; /* must be same length as p->dialdest */
1835 ast_mutex_lock(&p->lock);
1836 ast_copy_string(dest, rdest, sizeof(dest));
1837 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
1838 if ((ast->_state == AST_STATE_BUSY)) {
1839 p->subs[SUB_REAL].needbusy = 1;
1840 ast_mutex_unlock(&p->lock);
1841 return 0;
1843 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
1844 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
1845 ast_mutex_unlock(&p->lock);
1846 return -1;
1848 p->dialednone = 0;
1849 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
1851 /* Special pseudo -- automatically up */
1852 ast_setstate(ast, AST_STATE_UP);
1853 ast_mutex_unlock(&p->lock);
1854 return 0;
1856 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
1857 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
1858 if (res)
1859 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
1860 p->outgoing = 1;
1862 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
1864 mysig = p->sig;
1865 if (p->outsigmod > -1)
1866 mysig = p->outsigmod;
1868 switch (mysig) {
1869 case SIG_FXOLS:
1870 case SIG_FXOGS:
1871 case SIG_FXOKS:
1872 if (p->owner == ast) {
1873 /* Normal ring, on hook */
1875 /* Don't send audio while on hook, until the call is answered */
1876 p->dialing = 1;
1877 if (p->use_callerid) {
1878 /* Generate the Caller-ID spill if desired */
1879 if (p->cidspill) {
1880 ast_log(LOG_WARNING, "cidspill already exists??\n");
1881 free(p->cidspill);
1883 p->callwaitcas = 0;
1884 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
1885 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
1886 p->cidpos = 0;
1887 send_callerid(p);
1890 /* Choose proper cadence */
1891 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
1892 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
1893 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
1894 p->cidrings = cidrings[p->distinctivering - 1];
1895 } else {
1896 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
1897 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
1898 p->cidrings = p->sendcalleridafter;
1901 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
1902 c = strchr(dest, '/');
1903 if (c)
1904 c++;
1905 if (c && (strlen(c) < p->stripmsd)) {
1906 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
1907 c = NULL;
1909 if (c) {
1910 p->dop.op = DAHDI_DIAL_OP_REPLACE;
1911 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
1912 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
1913 } else {
1914 p->dop.dialstr[0] = '\0';
1916 x = DAHDI_RING;
1917 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
1918 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
1919 ast_mutex_unlock(&p->lock);
1920 return -1;
1922 p->dialing = 1;
1923 } else {
1924 /* Call waiting call */
1925 p->callwaitrings = 0;
1926 if (ast->cid.cid_num)
1927 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
1928 else
1929 p->callwait_num[0] = '\0';
1930 if (ast->cid.cid_name)
1931 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
1932 else
1933 p->callwait_name[0] = '\0';
1934 /* Call waiting tone instead */
1935 if (dahdi_callwait(ast)) {
1936 ast_mutex_unlock(&p->lock);
1937 return -1;
1939 /* Make ring-back */
1940 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
1941 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
1944 n = ast->cid.cid_name;
1945 l = ast->cid.cid_num;
1946 if (l)
1947 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
1948 else
1949 p->lastcid_num[0] = '\0';
1950 if (n)
1951 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
1952 else
1953 p->lastcid_name[0] = '\0';
1954 ast_setstate(ast, AST_STATE_RINGING);
1955 index = dahdi_get_index(ast, p, 0);
1956 if (index > -1) {
1957 p->subs[index].needringing = 1;
1959 break;
1960 case SIG_FXSLS:
1961 case SIG_FXSGS:
1962 case SIG_FXSKS:
1963 case SIG_EMWINK:
1964 case SIG_EM:
1965 case SIG_EM_E1:
1966 case SIG_FEATD:
1967 case SIG_FEATDMF:
1968 case SIG_E911:
1969 case SIG_FGC_CAMA:
1970 case SIG_FGC_CAMAMF:
1971 case SIG_FEATB:
1972 case SIG_SFWINK:
1973 case SIG_SF:
1974 case SIG_SF_FEATD:
1975 case SIG_SF_FEATDMF:
1976 case SIG_FEATDMF_TA:
1977 case SIG_SF_FEATB:
1978 c = strchr(dest, '/');
1979 if (c)
1980 c++;
1981 else
1982 c = "";
1983 if (strlen(c) < p->stripmsd) {
1984 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
1985 ast_mutex_unlock(&p->lock);
1986 return -1;
1988 #ifdef HAVE_PRI
1989 /* Start the trunk, if not GR-303 */
1990 if (!p->pri) {
1991 #endif
1992 x = DAHDI_START;
1993 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
1994 if (res < 0) {
1995 if (errno != EINPROGRESS) {
1996 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
1997 ast_mutex_unlock(&p->lock);
1998 return -1;
2001 #ifdef HAVE_PRI
2003 #endif
2004 ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
2005 p->dop.op = DAHDI_DIAL_OP_REPLACE;
2007 c += p->stripmsd;
2009 switch (mysig) {
2010 case SIG_FEATD:
2011 l = ast->cid.cid_num;
2012 if (l)
2013 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
2014 else
2015 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
2016 break;
2017 case SIG_FEATDMF:
2018 l = ast->cid.cid_num;
2019 if (l)
2020 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
2021 else
2022 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
2023 break;
2024 case SIG_FEATDMF_TA:
2026 const char *cic, *ozz;
2028 /* If you have to go through a Tandem Access point you need to use this */
2029 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
2030 if (!ozz)
2031 ozz = defaultozz;
2032 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
2033 if (!cic)
2034 cic = defaultcic;
2035 if (!ozz || !cic) {
2036 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
2037 ast_mutex_unlock(&p->lock);
2038 return -1;
2040 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
2041 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
2042 p->whichwink = 0;
2044 break;
2045 case SIG_E911:
2046 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
2047 break;
2048 case SIG_FGC_CAMA:
2049 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
2050 break;
2051 case SIG_FGC_CAMAMF:
2052 case SIG_FEATB:
2053 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
2054 break;
2055 default:
2056 if (p->pulse)
2057 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
2058 else
2059 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
2060 break;
2063 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
2064 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
2065 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
2066 p->echorest[sizeof(p->echorest) - 1] = '\0';
2067 p->echobreak = 1;
2068 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
2069 } else
2070 p->echobreak = 0;
2071 if (!res) {
2072 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
2073 int saveerr = errno;
2075 x = DAHDI_ONHOOK;
2076 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
2077 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
2078 ast_mutex_unlock(&p->lock);
2079 return -1;
2081 } else
2082 ast_log(LOG_DEBUG, "Deferring dialing...\n");
2083 p->dialing = 1;
2084 if (ast_strlen_zero(c))
2085 p->dialednone = 1;
2086 ast_setstate(ast, AST_STATE_DIALING);
2087 break;
2088 case 0:
2089 /* Special pseudo -- automatically up*/
2090 ast_setstate(ast, AST_STATE_UP);
2091 break;
2092 case SIG_PRI:
2093 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2094 p->dialdest[0] = '\0';
2095 break;
2096 default:
2097 ast_log(LOG_DEBUG, "not yet implemented\n");
2098 ast_mutex_unlock(&p->lock);
2099 return -1;
2101 #ifdef HAVE_PRI
2102 if (p->pri) {
2103 struct pri_sr *sr;
2104 #ifdef SUPPORT_USERUSER
2105 const char *useruser;
2106 #endif
2107 int pridialplan;
2108 int dp_strip;
2109 int prilocaldialplan;
2110 int ldp_strip;
2111 int exclusive;
2112 const char *rr_str;
2113 int redirect_reason;
2115 c = strchr(dest, '/');
2116 if (c)
2117 c++;
2118 else
2119 c = dest;
2121 l = NULL;
2122 n = NULL;
2124 if (!p->hidecallerid) {
2125 l = ast->cid.cid_num;
2126 if (!p->hidecalleridname) {
2127 n = ast->cid.cid_name;
2132 if (strlen(c) < p->stripmsd) {
2133 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
2134 ast_mutex_unlock(&p->lock);
2135 return -1;
2137 if (mysig != SIG_FXSKS) {
2138 p->dop.op = DAHDI_DIAL_OP_REPLACE;
2139 s = strchr(c + p->stripmsd, 'w');
2140 if (s) {
2141 if (strlen(s) > 1)
2142 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
2143 else
2144 p->dop.dialstr[0] = '\0';
2145 *s = '\0';
2146 } else {
2147 p->dop.dialstr[0] = '\0';
2150 if (pri_grab(p, p->pri)) {
2151 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
2152 ast_mutex_unlock(&p->lock);
2153 return -1;
2155 if (!(p->call = pri_new_call(p->pri->pri))) {
2156 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
2157 pri_rel(p->pri);
2158 ast_mutex_unlock(&p->lock);
2159 return -1;
2161 if (!(sr = pri_sr_new())) {
2162 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
2163 pri_destroycall(p->pri->pri, p->call);
2164 p->call = NULL;
2165 pri_rel(p->pri);
2166 ast_mutex_unlock(&p->lock);
2167 return -1;
2169 if (p->bearer || (mysig == SIG_FXSKS)) {
2170 if (p->bearer) {
2171 ast_log(LOG_DEBUG, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
2172 p->bearer->call = p->call;
2173 } else
2174 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
2175 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
2177 p->digital = IS_DIGITAL(ast->transfercapability);
2178 /* Add support for exclusive override */
2179 if (p->priexclusive)
2180 exclusive = 1;
2181 else {
2182 /* otherwise, traditional behavior */
2183 if (p->pri->nodetype == PRI_NETWORK)
2184 exclusive = 0;
2185 else
2186 exclusive = 1;
2189 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
2190 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
2191 (p->digital ? -1 :
2192 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
2193 if (p->pri->facilityenable)
2194 pri_facility_enable(p->pri->pri);
2196 if (option_verbose > 2)
2197 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
2198 dp_strip = 0;
2199 pridialplan = p->pri->dialplan - 1;
2200 if (pridialplan == -2) { /* compute dynamically */
2201 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2202 dp_strip = strlen(p->pri->internationalprefix);
2203 pridialplan = PRI_INTERNATIONAL_ISDN;
2204 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2205 dp_strip = strlen(p->pri->nationalprefix);
2206 pridialplan = PRI_NATIONAL_ISDN;
2207 } else {
2208 pridialplan = PRI_LOCAL_ISDN;
2211 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
2213 ldp_strip = 0;
2214 prilocaldialplan = p->pri->localdialplan - 1;
2215 if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
2216 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2217 ldp_strip = strlen(p->pri->internationalprefix);
2218 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
2219 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2220 ldp_strip = strlen(p->pri->nationalprefix);
2221 prilocaldialplan = PRI_NATIONAL_ISDN;
2222 } else {
2223 prilocaldialplan = PRI_LOCAL_ISDN;
2226 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
2227 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
2228 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
2229 if (!strcasecmp(rr_str, "UNKNOWN"))
2230 redirect_reason = 0;
2231 else if (!strcasecmp(rr_str, "BUSY"))
2232 redirect_reason = 1;
2233 else if (!strcasecmp(rr_str, "NO_REPLY"))
2234 redirect_reason = 2;
2235 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
2236 redirect_reason = 15;
2237 else
2238 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2239 } else
2240 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2241 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
2243 #ifdef SUPPORT_USERUSER
2244 /* User-user info */
2245 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
2247 if (useruser)
2248 pri_sr_set_useruser(sr, useruser);
2249 #endif
2251 if (pri_setup(p->pri->pri, p->call, sr)) {
2252 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
2253 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
2254 pri_rel(p->pri);
2255 ast_mutex_unlock(&p->lock);
2256 pri_sr_free(sr);
2257 return -1;
2259 pri_sr_free(sr);
2260 ast_setstate(ast, AST_STATE_DIALING);
2261 pri_rel(p->pri);
2263 #endif
2264 ast_mutex_unlock(&p->lock);
2265 return 0;
2268 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
2270 struct dahdi_pvt *p = *pvt;
2271 /* Remove channel from the list */
2272 if (p->prev)
2273 p->prev->next = p->next;
2274 if (p->next)
2275 p->next->prev = p->prev;
2276 if (p->use_smdi)
2277 ast_smdi_interface_unref(p->smdi_iface);
2278 ast_mutex_destroy(&p->lock);
2279 dahdi_close_sub(p, SUB_REAL);
2280 if (p->owner)
2281 p->owner->tech_pvt = NULL;
2282 free(p);
2283 *pvt = NULL;
2286 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
2288 int owned = 0;
2289 int i = 0;
2291 if (!now) {
2292 if (cur->owner) {
2293 owned = 1;
2296 for (i = 0; i < 3; i++) {
2297 if (cur->subs[i].owner) {
2298 owned = 1;
2301 if (!owned) {
2302 if (prev) {
2303 prev->next = cur->next;
2304 if (prev->next)
2305 prev->next->prev = prev;
2306 else
2307 ifend = prev;
2308 } else {
2309 iflist = cur->next;
2310 if (iflist)
2311 iflist->prev = NULL;
2312 else
2313 ifend = NULL;
2315 destroy_dahdi_pvt(&cur);
2317 } else {
2318 if (prev) {
2319 prev->next = cur->next;
2320 if (prev->next)
2321 prev->next->prev = prev;
2322 else
2323 ifend = prev;
2324 } else {
2325 iflist = cur->next;
2326 if (iflist)
2327 iflist->prev = NULL;
2328 else
2329 ifend = NULL;
2331 destroy_dahdi_pvt(&cur);
2333 return 0;
2336 static void destroy_all_channels(void)
2338 int x;
2339 struct dahdi_pvt *p, *pl;
2341 while (num_restart_pending) {
2342 usleep(1);
2345 ast_mutex_lock(&iflock);
2346 /* Destroy all the interfaces and free their memory */
2347 p = iflist;
2348 while (p) {
2349 /* Free any callerid */
2350 if (p->cidspill)
2351 ast_free(p->cidspill);
2352 pl = p;
2353 p = p->next;
2354 x = pl->channel;
2355 /* Free associated memory */
2356 if (pl)
2357 destroy_dahdi_pvt(&pl);
2358 if (option_verbose > 2)
2359 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
2361 iflist = NULL;
2362 ifcount = 0;
2363 ast_mutex_unlock(&iflock);
2366 #ifdef HAVE_PRI
2367 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
2368 static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility";
2370 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
2371 static char *zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
2373 static char *dahdi_send_keypad_facility_descrip =
2374 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2375 " IE over the current channel.\n";
2376 static char *zap_send_keypad_facility_descrip =
2377 " ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2378 " IE over the current channel.\n";
2380 static int send_keypad_facility_exec(struct ast_channel *chan, void *data)
2382 /* Data will be our digit string */
2383 struct dahdi_pvt *p;
2384 char *digits = (char *) data;
2386 if (ast_strlen_zero(digits)) {
2387 ast_log(LOG_DEBUG, "No digit string sent to application!\n");
2388 return -1;
2391 p = (struct dahdi_pvt *)chan->tech_pvt;
2393 if (!p) {
2394 ast_log(LOG_DEBUG, "Unable to find technology private\n");
2395 return -1;
2398 ast_mutex_lock(&p->lock);
2400 if (!p->pri || !p->call) {
2401 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
2402 ast_mutex_unlock(&p->lock);
2403 return -1;
2406 if (!pri_grab(p, p->pri)) {
2407 pri_keypad_facility(p->pri->pri, p->call, digits);
2408 pri_rel(p->pri);
2409 } else {
2410 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
2411 ast_mutex_unlock(&p->lock);
2412 return -1;
2415 ast_mutex_unlock(&p->lock);
2417 return 0;
2420 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
2422 return send_keypad_facility_exec(chan, data);
2425 static int zap_send_keypad_facility_exec(struct ast_channel *chan, void *data)
2427 ast_log(LOG_WARNING, "Use of the command %s is deprecated, please use %s instead.\n", zap_send_keypad_facility_app, dahdi_send_keypad_facility_app);
2428 return send_keypad_facility_exec(chan, data);
2431 static int pri_is_up(struct dahdi_pri *pri)
2433 int x;
2434 for (x = 0; x < NUM_DCHANS; x++) {
2435 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
2436 return 1;
2438 return 0;
2441 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
2443 bearer->owner = &inuse;
2444 bearer->realcall = crv;
2445 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
2446 if (crv->subs[SUB_REAL].owner)
2447 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
2448 crv->bearer = bearer;
2449 crv->call = bearer->call;
2450 crv->pri = pri;
2451 return 0;
2454 static char *pri_order(int level)
2456 switch (level) {
2457 case 0:
2458 return "Primary";
2459 case 1:
2460 return "Secondary";
2461 case 2:
2462 return "Tertiary";
2463 case 3:
2464 return "Quaternary";
2465 default:
2466 return "<Unknown>";
2470 /* Returns fd of the active dchan */
2471 static int pri_active_dchan_fd(struct dahdi_pri *pri)
2473 int x = -1;
2475 for (x = 0; x < NUM_DCHANS; x++) {
2476 if ((pri->dchans[x] == pri->pri))
2477 break;
2480 return pri->fds[x];
2483 static int pri_find_dchan(struct dahdi_pri *pri)
2485 int oldslot = -1;
2486 struct pri *old;
2487 int newslot = -1;
2488 int x;
2489 old = pri->pri;
2490 for (x = 0; x < NUM_DCHANS; x++) {
2491 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
2492 newslot = x;
2493 if (pri->dchans[x] == old) {
2494 oldslot = x;
2497 if (newslot < 0) {
2498 newslot = 0;
2499 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2500 pri->dchannels[newslot]);
2502 if (old && (oldslot != newslot))
2503 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
2504 pri->dchannels[oldslot], pri->dchannels[newslot]);
2505 pri->pri = pri->dchans[newslot];
2506 return 0;
2508 #endif
2510 static int dahdi_hangup(struct ast_channel *ast)
2512 int res;
2513 int index,x, law;
2514 /*static int restore_gains(struct dahdi_pvt *p);*/
2515 struct dahdi_pvt *p = ast->tech_pvt;
2516 struct dahdi_pvt *tmp = NULL;
2517 struct dahdi_pvt *prev = NULL;
2518 struct dahdi_params par;
2520 if (option_debug)
2521 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
2522 if (!ast->tech_pvt) {
2523 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
2524 return 0;
2527 ast_mutex_lock(&p->lock);
2529 index = dahdi_get_index(ast, p, 1);
2531 if (p->sig == SIG_PRI) {
2532 x = 1;
2533 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
2536 x = 0;
2537 dahdi_confmute(p, 0);
2538 restore_gains(p);
2539 if (p->origcid_num) {
2540 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
2541 free(p->origcid_num);
2542 p->origcid_num = NULL;
2544 if (p->origcid_name) {
2545 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
2546 free(p->origcid_name);
2547 p->origcid_name = NULL;
2549 if (p->dsp)
2550 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
2551 if (p->exten)
2552 p->exten[0] = '\0';
2554 if (option_debug)
2555 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
2556 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
2557 p->ignoredtmf = 0;
2559 if (index > -1) {
2560 /* Real channel, do some fixup */
2561 p->subs[index].owner = NULL;
2562 p->subs[index].needanswer = 0;
2563 p->subs[index].needflash = 0;
2564 p->subs[index].needringing = 0;
2565 p->subs[index].needbusy = 0;
2566 p->subs[index].needcongestion = 0;
2567 p->subs[index].linear = 0;
2568 p->subs[index].needcallerid = 0;
2569 p->polarity = POLARITY_IDLE;
2570 dahdi_setlinear(p->subs[index].dfd, 0);
2571 if (index == SUB_REAL) {
2572 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
2573 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
2574 if (p->subs[SUB_CALLWAIT].inthreeway) {
2575 /* We had flipped over to answer a callwait and now it's gone */
2576 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
2577 /* Move to the call-wait, but un-own us until they flip back. */
2578 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
2579 unalloc_sub(p, SUB_CALLWAIT);
2580 p->owner = NULL;
2581 } else {
2582 /* The three way hung up, but we still have a call wait */
2583 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
2584 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2585 unalloc_sub(p, SUB_THREEWAY);
2586 if (p->subs[SUB_REAL].inthreeway) {
2587 /* This was part of a three way call. Immediately make way for
2588 another call */
2589 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
2590 p->owner = p->subs[SUB_REAL].owner;
2591 } else {
2592 /* This call hasn't been completed yet... Set owner to NULL */
2593 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
2594 p->owner = NULL;
2596 p->subs[SUB_REAL].inthreeway = 0;
2598 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
2599 /* Move to the call-wait and switch back to them. */
2600 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
2601 unalloc_sub(p, SUB_CALLWAIT);
2602 p->owner = p->subs[SUB_REAL].owner;
2603 if (p->owner->_state != AST_STATE_UP)
2604 p->subs[SUB_REAL].needanswer = 1;
2605 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
2606 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
2607 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
2608 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2609 unalloc_sub(p, SUB_THREEWAY);
2610 if (p->subs[SUB_REAL].inthreeway) {
2611 /* This was part of a three way call. Immediately make way for
2612 another call */
2613 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
2614 p->owner = p->subs[SUB_REAL].owner;
2615 } else {
2616 /* This call hasn't been completed yet... Set owner to NULL */
2617 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
2618 p->owner = NULL;
2620 p->subs[SUB_REAL].inthreeway = 0;
2622 } else if (index == SUB_CALLWAIT) {
2623 /* Ditch the holding callwait call, and immediately make it availabe */
2624 if (p->subs[SUB_CALLWAIT].inthreeway) {
2625 /* This is actually part of a three way, placed on hold. Place the third part
2626 on music on hold now */
2627 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
2628 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
2629 S_OR(p->mohsuggest, NULL),
2630 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
2632 p->subs[SUB_THREEWAY].inthreeway = 0;
2633 /* Make it the call wait now */
2634 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
2635 unalloc_sub(p, SUB_THREEWAY);
2636 } else
2637 unalloc_sub(p, SUB_CALLWAIT);
2638 } else if (index == SUB_THREEWAY) {
2639 if (p->subs[SUB_CALLWAIT].inthreeway) {
2640 /* The other party of the three way call is currently in a call-wait state.
2641 Start music on hold for them, and take the main guy out of the third call */
2642 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
2643 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
2644 S_OR(p->mohsuggest, NULL),
2645 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
2647 p->subs[SUB_CALLWAIT].inthreeway = 0;
2649 p->subs[SUB_REAL].inthreeway = 0;
2650 /* If this was part of a three way call index, let us make
2651 another three way call */
2652 unalloc_sub(p, SUB_THREEWAY);
2653 } else {
2654 /* This wasn't any sort of call, but how are we an index? */
2655 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
2659 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
2660 p->owner = NULL;
2661 p->ringt = 0;
2662 p->distinctivering = 0;
2663 p->confirmanswer = 0;
2664 p->cidrings = 1;
2665 p->outgoing = 0;
2666 p->digital = 0;
2667 p->faxhandled = 0;
2668 p->pulsedial = 0;
2669 p->onhooktime = time(NULL);
2670 #ifdef HAVE_PRI
2671 p->proceeding = 0;
2672 p->progress = 0;
2673 p->alerting = 0;
2674 p->setup_ack = 0;
2675 #endif
2676 if (p->dsp) {
2677 ast_dsp_free(p->dsp);
2678 p->dsp = NULL;
2681 law = DAHDI_LAW_DEFAULT;
2682 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
2683 if (res < 0)
2684 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
2685 /* Perform low level hangup if no owner left */
2686 #ifdef HAVE_PRI
2687 if (p->pri) {
2688 #ifdef SUPPORT_USERUSER
2689 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
2690 #endif
2692 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
2693 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
2694 if (!pri_grab(p, p->pri)) {
2695 if (p->alreadyhungup) {
2696 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
2698 #ifdef SUPPORT_USERUSER
2699 pri_call_set_useruser(p->call, useruser);
2700 #endif
2702 pri_hangup(p->pri->pri, p->call, -1);
2703 p->call = NULL;
2704 if (p->bearer)
2705 p->bearer->call = NULL;
2706 } else {
2707 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
2708 int icause = ast->hangupcause ? ast->hangupcause : -1;
2709 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
2711 #ifdef SUPPORT_USERUSER
2712 pri_call_set_useruser(p->call, useruser);
2713 #endif
2715 p->alreadyhungup = 1;
2716 if (p->bearer)
2717 p->bearer->alreadyhungup = 1;
2718 if (cause) {
2719 if (atoi(cause))
2720 icause = atoi(cause);
2722 pri_hangup(p->pri->pri, p->call, icause);
2724 if (res < 0)
2725 ast_log(LOG_WARNING, "pri_disconnect failed\n");
2726 pri_rel(p->pri);
2727 } else {
2728 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
2729 res = -1;
2731 } else {
2732 if (p->bearer)
2733 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
2734 p->call = NULL;
2735 res = 0;
2738 #endif
2739 if (p->sig && (p->sig != SIG_PRI))
2740 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
2741 if (res < 0) {
2742 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
2744 switch (p->sig) {
2745 case SIG_FXOGS:
2746 case SIG_FXOLS:
2747 case SIG_FXOKS:
2748 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
2749 if (!res) {
2750 #if 0
2751 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
2752 #endif
2753 /* If they're off hook, try playing congestion */
2754 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
2755 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
2756 else
2757 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
2759 break;
2760 case SIG_FXSGS:
2761 case SIG_FXSLS:
2762 case SIG_FXSKS:
2763 /* Make sure we're not made available for at least two seconds assuming
2764 we were actually used for an inbound or outbound call. */
2765 if (ast->_state != AST_STATE_RESERVED) {
2766 time(&p->guardtime);
2767 p->guardtime += 2;
2769 break;
2770 default:
2771 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
2773 if (p->cidspill)
2774 free(p->cidspill);
2775 if (p->sig)
2776 dahdi_disable_ec(p);
2777 x = 0;
2778 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
2779 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
2780 p->didtdd = 0;
2781 p->cidspill = NULL;
2782 p->callwaitcas = 0;
2783 p->callwaiting = p->permcallwaiting;
2784 p->hidecallerid = p->permhidecallerid;
2785 p->dialing = 0;
2786 p->rdnis[0] = '\0';
2787 update_conf(p);
2788 reset_conf(p);
2789 /* Restore data mode */
2790 if (p->sig == SIG_PRI) {
2791 x = 0;
2792 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
2794 #ifdef HAVE_PRI
2795 if (p->bearer) {
2796 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
2797 /* Free up the bearer channel as well, and
2798 don't use its file descriptor anymore */
2799 update_conf(p->bearer);
2800 reset_conf(p->bearer);
2801 p->bearer->owner = NULL;
2802 p->bearer->realcall = NULL;
2803 p->bearer = NULL;
2804 p->subs[SUB_REAL].dfd = -1;
2805 p->pri = NULL;
2807 #endif
2808 if (num_restart_pending == 0)
2809 restart_monitor();
2812 p->callwaitingrepeat = 0;
2813 p->cidcwexpire = 0;
2814 p->oprmode = 0;
2815 ast->tech_pvt = NULL;
2816 ast_mutex_unlock(&p->lock);
2817 ast_module_unref(ast_module_info->self);
2818 if (option_verbose > 2)
2819 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
2821 ast_mutex_lock(&iflock);
2823 if (p->restartpending) {
2824 num_restart_pending--;
2827 tmp = iflist;
2828 prev = NULL;
2829 if (p->destroy) {
2830 while (tmp) {
2831 if (tmp == p) {
2832 destroy_channel(prev, tmp, 0);
2833 break;
2834 } else {
2835 prev = tmp;
2836 tmp = tmp->next;
2840 ast_mutex_unlock(&iflock);
2841 return 0;
2844 static int dahdi_answer(struct ast_channel *ast)
2846 struct dahdi_pvt *p = ast->tech_pvt;
2847 int res = 0;
2848 int index;
2849 int oldstate = ast->_state;
2850 ast_setstate(ast, AST_STATE_UP);
2851 ast_mutex_lock(&p->lock);
2852 index = dahdi_get_index(ast, p, 0);
2853 if (index < 0)
2854 index = SUB_REAL;
2855 /* nothing to do if a radio channel */
2856 if ((p->radio || (p->oprmode < 0))) {
2857 ast_mutex_unlock(&p->lock);
2858 return 0;
2860 switch (p->sig) {
2861 case SIG_FXSLS:
2862 case SIG_FXSGS:
2863 case SIG_FXSKS:
2864 p->ringt = 0;
2865 /* Fall through */
2866 case SIG_EM:
2867 case SIG_EM_E1:
2868 case SIG_EMWINK:
2869 case SIG_FEATD:
2870 case SIG_FEATDMF:
2871 case SIG_FEATDMF_TA:
2872 case SIG_E911:
2873 case SIG_FGC_CAMA:
2874 case SIG_FGC_CAMAMF:
2875 case SIG_FEATB:
2876 case SIG_SF:
2877 case SIG_SFWINK:
2878 case SIG_SF_FEATD:
2879 case SIG_SF_FEATDMF:
2880 case SIG_SF_FEATB:
2881 case SIG_FXOLS:
2882 case SIG_FXOGS:
2883 case SIG_FXOKS:
2884 /* Pick up the line */
2885 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
2886 if (p->hanguponpolarityswitch) {
2887 gettimeofday(&p->polaritydelaytv, NULL);
2889 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
2890 tone_zone_play_tone(p->subs[index].dfd, -1);
2891 p->dialing = 0;
2892 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
2893 if (oldstate == AST_STATE_RINGING) {
2894 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
2895 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
2896 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2897 p->owner = p->subs[SUB_REAL].owner;
2900 if (p->sig & __DAHDI_SIG_FXS) {
2901 dahdi_enable_ec(p);
2902 dahdi_train_ec(p);
2904 break;
2905 #ifdef HAVE_PRI
2906 case SIG_PRI:
2907 /* Send a pri acknowledge */
2908 if (!pri_grab(p, p->pri)) {
2909 p->proceeding = 1;
2910 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
2911 pri_rel(p->pri);
2912 } else {
2913 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
2914 res = -1;
2916 break;
2917 #endif
2918 case 0:
2919 ast_mutex_unlock(&p->lock);
2920 return 0;
2921 default:
2922 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
2923 res = -1;
2925 ast_mutex_unlock(&p->lock);
2926 return res;
2929 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
2931 char *cp;
2932 signed char *scp;
2933 int x;
2934 int index;
2935 struct dahdi_pvt *p = chan->tech_pvt, *pp;
2936 struct oprmode *oprmode;
2939 /* all supported options require data */
2940 if (!data || (datalen < 1)) {
2941 errno = EINVAL;
2942 return -1;
2945 switch (option) {
2946 case AST_OPTION_TXGAIN:
2947 scp = (signed char *) data;
2948 index = dahdi_get_index(chan, p, 0);
2949 if (index < 0) {
2950 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
2951 return -1;
2953 if (option_debug)
2954 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
2955 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
2956 case AST_OPTION_RXGAIN:
2957 scp = (signed char *) data;
2958 index = dahdi_get_index(chan, p, 0);
2959 if (index < 0) {
2960 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
2961 return -1;
2963 if (option_debug)
2964 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
2965 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
2966 case AST_OPTION_TONE_VERIFY:
2967 if (!p->dsp)
2968 break;
2969 cp = (char *) data;
2970 switch (*cp) {
2971 case 1:
2972 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
2973 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
2974 break;
2975 case 2:
2976 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
2977 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
2978 break;
2979 default:
2980 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
2981 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
2982 break;
2984 break;
2985 case AST_OPTION_TDD:
2986 /* turn on or off TDD */
2987 cp = (char *) data;
2988 p->mate = 0;
2989 if (!*cp) { /* turn it off */
2990 if (option_debug)
2991 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
2992 if (p->tdd)
2993 tdd_free(p->tdd);
2994 p->tdd = 0;
2995 break;
2997 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
2998 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
2999 dahdi_disable_ec(p);
3000 /* otherwise, turn it on */
3001 if (!p->didtdd) { /* if havent done it yet */
3002 unsigned char mybuf[41000], *buf;
3003 int size, res, fd, len;
3004 struct pollfd fds[1];
3006 buf = mybuf;
3007 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
3008 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */
3009 len = 40000;
3010 index = dahdi_get_index(chan, p, 0);
3011 if (index < 0) {
3012 ast_log(LOG_WARNING, "No index in TDD?\n");
3013 return -1;
3015 fd = p->subs[index].dfd;
3016 while (len) {
3017 if (ast_check_hangup(chan))
3018 return -1;
3019 size = len;
3020 if (size > READ_SIZE)
3021 size = READ_SIZE;
3022 fds[0].fd = fd;
3023 fds[0].events = POLLPRI | POLLOUT;
3024 fds[0].revents = 0;
3025 res = poll(fds, 1, -1);
3026 if (!res) {
3027 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
3028 continue;
3030 /* if got exception */
3031 if (fds[0].revents & POLLPRI)
3032 return -1;
3033 if (!(fds[0].revents & POLLOUT)) {
3034 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
3035 continue;
3037 res = write(fd, buf, size);
3038 if (res != size) {
3039 if (res == -1) return -1;
3040 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
3041 break;
3043 len -= size;
3044 buf += size;
3046 p->didtdd = 1; /* set to have done it now */
3048 if (*cp == 2) { /* Mate mode */
3049 if (p->tdd)
3050 tdd_free(p->tdd);
3051 p->tdd = 0;
3052 p->mate = 1;
3053 break;
3055 if (!p->tdd) { /* if we dont have one yet */
3056 p->tdd = tdd_new(); /* allocate one */
3058 break;
3059 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
3060 if (!p->dsp)
3061 break;
3062 cp = (char *) data;
3063 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
3064 *cp ? "ON" : "OFF", (int) *cp, chan->name);
3065 p->dtmfrelax = 0;
3066 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
3067 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
3068 break;
3069 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
3070 cp = (char *) data;
3071 if (!*cp) {
3072 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
3073 x = 0;
3074 dahdi_disable_ec(p);
3075 } else {
3076 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
3077 x = 1;
3079 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
3080 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
3081 break;
3082 case AST_OPTION_OPRMODE: /* Operator services mode */
3083 oprmode = (struct oprmode *) data;
3084 pp = oprmode->peer->tech_pvt;
3085 p->oprmode = pp->oprmode = 0;
3086 /* setup peers */
3087 p->oprpeer = pp;
3088 pp->oprpeer = p;
3089 /* setup modes, if any */
3090 if (oprmode->mode)
3092 pp->oprmode = oprmode->mode;
3093 p->oprmode = -oprmode->mode;
3095 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
3096 oprmode->mode, chan->name,oprmode->peer->name);;
3097 break;
3098 case AST_OPTION_ECHOCAN:
3099 cp = (char *) data;
3100 if (*cp) {
3101 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
3102 dahdi_enable_ec(p);
3103 } else {
3104 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
3105 dahdi_disable_ec(p);
3107 break;
3109 errno = 0;
3111 return 0;
3114 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
3116 struct dahdi_pvt *p = chan->tech_pvt;
3118 if (!strcasecmp(data, "rxgain")) {
3119 ast_mutex_lock(&p->lock);
3120 snprintf(buf, len, "%f", p->rxgain);
3121 ast_mutex_unlock(&p->lock);
3122 } else if (!strcasecmp(data, "txgain")) {
3123 ast_mutex_lock(&p->lock);
3124 snprintf(buf, len, "%f", p->txgain);
3125 ast_mutex_unlock(&p->lock);
3126 } else {
3127 ast_copy_string(buf, "", len);
3129 return 0;
3133 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
3135 /* Unlink a specific slave or all slaves/masters from a given master */
3136 int x;
3137 int hasslaves;
3138 if (!master)
3139 return;
3140 if (needlock) {
3141 ast_mutex_lock(&master->lock);
3142 if (slave) {
3143 while (ast_mutex_trylock(&slave->lock)) {
3144 DEADLOCK_AVOIDANCE(&master->lock);
3148 hasslaves = 0;
3149 for (x = 0; x < MAX_SLAVES; x++) {
3150 if (master->slaves[x]) {
3151 if (!slave || (master->slaves[x] == slave)) {
3152 /* Take slave out of the conference */
3153 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
3154 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
3155 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
3156 master->slaves[x]->master = NULL;
3157 master->slaves[x] = NULL;
3158 } else
3159 hasslaves = 1;
3161 if (!hasslaves)
3162 master->inconference = 0;
3164 if (!slave) {
3165 if (master->master) {
3166 /* Take master out of the conference */
3167 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
3168 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
3169 hasslaves = 0;
3170 for (x = 0; x < MAX_SLAVES; x++) {
3171 if (master->master->slaves[x] == master)
3172 master->master->slaves[x] = NULL;
3173 else if (master->master->slaves[x])
3174 hasslaves = 1;
3176 if (!hasslaves)
3177 master->master->inconference = 0;
3179 master->master = NULL;
3181 update_conf(master);
3182 if (needlock) {
3183 if (slave)
3184 ast_mutex_unlock(&slave->lock);
3185 ast_mutex_unlock(&master->lock);
3189 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
3190 int x;
3191 if (!slave || !master) {
3192 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
3193 return;
3195 for (x = 0; x < MAX_SLAVES; x++) {
3196 if (!master->slaves[x]) {
3197 master->slaves[x] = slave;
3198 break;
3201 if (x >= MAX_SLAVES) {
3202 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
3203 master->slaves[MAX_SLAVES - 1] = slave;
3205 if (slave->master)
3206 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
3207 slave->master = master;
3209 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
3212 static void disable_dtmf_detect(struct dahdi_pvt *p)
3214 #ifdef DAHDI_TONEDETECT
3215 int val;
3216 #endif
3218 p->ignoredtmf = 1;
3220 #ifdef DAHDI_TONEDETECT
3221 val = 0;
3222 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
3223 #endif
3224 if (!p->hardwaredtmf && p->dsp) {
3225 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
3226 ast_dsp_set_features(p->dsp, p->dsp_features);
3230 static void enable_dtmf_detect(struct dahdi_pvt *p)
3232 #ifdef DAHDI_TONEDETECT
3233 int val;
3234 #endif
3236 if (p->channel == CHAN_PSEUDO)
3237 return;
3239 p->ignoredtmf = 0;
3241 #ifdef DAHDI_TONEDETECT
3242 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
3243 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
3244 #endif
3245 if (!p->hardwaredtmf && p->dsp) {
3246 p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
3247 ast_dsp_set_features(p->dsp, p->dsp_features);
3251 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
3253 struct ast_channel *who;
3254 struct dahdi_pvt *p0, *p1, *op0, *op1;
3255 struct dahdi_pvt *master = NULL, *slave = NULL;
3256 struct ast_frame *f;
3257 int inconf = 0;
3258 int nothingok = 1;
3259 int ofd0, ofd1;
3260 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
3261 int os0 = -1, os1 = -1;
3262 int priority = 0;
3263 struct ast_channel *oc0, *oc1;
3264 enum ast_bridge_result res;
3266 #ifdef PRI_2BCT
3267 int triedtopribridge = 0;
3268 q931_call *q931c0 = NULL, *q931c1 = NULL;
3269 #endif
3271 /* For now, don't attempt to native bridge if either channel needs DTMF detection.
3272 There is code below to handle it properly until DTMF is actually seen,
3273 but due to currently unresolved issues it's ignored...
3276 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
3277 return AST_BRIDGE_FAILED_NOWARN;
3279 ast_mutex_lock(&c0->lock);
3280 while (ast_mutex_trylock(&c1->lock)) {
3281 DEADLOCK_AVOIDANCE(&c0->lock);
3284 p0 = c0->tech_pvt;
3285 p1 = c1->tech_pvt;
3286 /* cant do pseudo-channels here */
3287 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
3288 ast_mutex_unlock(&c0->lock);
3289 ast_mutex_unlock(&c1->lock);
3290 return AST_BRIDGE_FAILED_NOWARN;
3293 oi0 = dahdi_get_index(c0, p0, 0);
3294 oi1 = dahdi_get_index(c1, p1, 0);
3295 if ((oi0 < 0) || (oi1 < 0)) {
3296 ast_mutex_unlock(&c0->lock);
3297 ast_mutex_unlock(&c1->lock);
3298 return AST_BRIDGE_FAILED;
3301 op0 = p0 = c0->tech_pvt;
3302 op1 = p1 = c1->tech_pvt;
3303 ofd0 = c0->fds[0];
3304 ofd1 = c1->fds[0];
3305 oc0 = p0->owner;
3306 oc1 = p1->owner;
3308 if (ast_mutex_trylock(&p0->lock)) {
3309 /* Don't block, due to potential for deadlock */
3310 ast_mutex_unlock(&c0->lock);
3311 ast_mutex_unlock(&c1->lock);
3312 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3313 return AST_BRIDGE_RETRY;
3315 if (ast_mutex_trylock(&p1->lock)) {
3316 /* Don't block, due to potential for deadlock */
3317 ast_mutex_unlock(&p0->lock);
3318 ast_mutex_unlock(&c0->lock);
3319 ast_mutex_unlock(&c1->lock);
3320 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3321 return AST_BRIDGE_RETRY;
3324 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3325 if (p0->owner && p1->owner) {
3326 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
3327 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
3328 master = p0;
3329 slave = p1;
3330 inconf = 1;
3331 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
3332 master = p1;
3333 slave = p0;
3334 inconf = 1;
3335 } else {
3336 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
3337 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
3338 p0->channel,
3339 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
3340 p0->subs[SUB_REAL].inthreeway, p0->channel,
3341 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
3342 p1->subs[SUB_REAL].inthreeway);
3344 nothingok = 0;
3346 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
3347 if (p1->subs[SUB_THREEWAY].inthreeway) {
3348 master = p1;
3349 slave = p0;
3350 nothingok = 0;
3352 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
3353 if (p0->subs[SUB_THREEWAY].inthreeway) {
3354 master = p0;
3355 slave = p1;
3356 nothingok = 0;
3358 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
3359 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
3360 don't put us in anything */
3361 if (p1->subs[SUB_CALLWAIT].inthreeway) {
3362 master = p1;
3363 slave = p0;
3364 nothingok = 0;
3366 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
3367 /* Same as previous */
3368 if (p0->subs[SUB_CALLWAIT].inthreeway) {
3369 master = p0;
3370 slave = p1;
3371 nothingok = 0;
3374 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
3375 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
3376 if (master && slave) {
3377 /* Stop any tones, or play ringtone as appropriate. If they're bridged
3378 in an active threeway call with a channel that is ringing, we should
3379 indicate ringing. */
3380 if ((oi1 == SUB_THREEWAY) &&
3381 p1->subs[SUB_THREEWAY].inthreeway &&
3382 p1->subs[SUB_REAL].owner &&
3383 p1->subs[SUB_REAL].inthreeway &&
3384 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3385 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
3386 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
3387 os1 = p1->subs[SUB_REAL].owner->_state;
3388 } else {
3389 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
3390 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
3392 if ((oi0 == SUB_THREEWAY) &&
3393 p0->subs[SUB_THREEWAY].inthreeway &&
3394 p0->subs[SUB_REAL].owner &&
3395 p0->subs[SUB_REAL].inthreeway &&
3396 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3397 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
3398 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
3399 os0 = p0->subs[SUB_REAL].owner->_state;
3400 } else {
3401 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
3402 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
3404 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3405 if (!p0->echocanbridged || !p1->echocanbridged) {
3406 /* Disable echo cancellation if appropriate */
3407 dahdi_disable_ec(p0);
3408 dahdi_disable_ec(p1);
3411 dahdi_link(slave, master);
3412 master->inconference = inconf;
3413 } else if (!nothingok)
3414 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
3416 update_conf(p0);
3417 update_conf(p1);
3418 t0 = p0->subs[SUB_REAL].inthreeway;
3419 t1 = p1->subs[SUB_REAL].inthreeway;
3421 ast_mutex_unlock(&p0->lock);
3422 ast_mutex_unlock(&p1->lock);
3424 ast_mutex_unlock(&c0->lock);
3425 ast_mutex_unlock(&c1->lock);
3427 /* Native bridge failed */
3428 if ((!master || !slave) && !nothingok) {
3429 dahdi_enable_ec(p0);
3430 dahdi_enable_ec(p1);
3431 return AST_BRIDGE_FAILED;
3434 if (option_verbose > 2)
3435 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
3437 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
3438 disable_dtmf_detect(op0);
3440 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
3441 disable_dtmf_detect(op1);
3443 for (;;) {
3444 struct ast_channel *c0_priority[2] = {c0, c1};
3445 struct ast_channel *c1_priority[2] = {c1, c0};
3447 /* Here's our main loop... Start by locking things, looking for private parts,
3448 and then balking if anything is wrong */
3449 ast_mutex_lock(&c0->lock);
3450 while (ast_mutex_trylock(&c1->lock)) {
3451 DEADLOCK_AVOIDANCE(&c0->lock);
3454 p0 = c0->tech_pvt;
3455 p1 = c1->tech_pvt;
3457 if (op0 == p0)
3458 i0 = dahdi_get_index(c0, p0, 1);
3459 if (op1 == p1)
3460 i1 = dahdi_get_index(c1, p1, 1);
3461 ast_mutex_unlock(&c0->lock);
3462 ast_mutex_unlock(&c1->lock);
3464 if (!timeoutms ||
3465 (op0 != p0) ||
3466 (op1 != p1) ||
3467 (ofd0 != c0->fds[0]) ||
3468 (ofd1 != c1->fds[0]) ||
3469 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
3470 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
3471 (oc0 != p0->owner) ||
3472 (oc1 != p1->owner) ||
3473 (t0 != p0->subs[SUB_REAL].inthreeway) ||
3474 (t1 != p1->subs[SUB_REAL].inthreeway) ||
3475 (oi0 != i0) ||
3476 (oi1 != i1)) {
3477 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
3478 op0->channel, oi0, op1->channel, oi1);
3479 res = AST_BRIDGE_RETRY;
3480 goto return_from_bridge;
3483 #ifdef PRI_2BCT
3484 q931c0 = p0->call;
3485 q931c1 = p1->call;
3486 if (p0->transfer && p1->transfer
3487 && q931c0 && q931c1
3488 && !triedtopribridge) {
3489 pri_channel_bridge(q931c0, q931c1);
3490 triedtopribridge = 1;
3492 #endif
3494 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
3495 if (!who) {
3496 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
3497 continue;
3499 f = ast_read(who);
3500 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
3501 *fo = f;
3502 *rc = who;
3503 res = AST_BRIDGE_COMPLETE;
3504 goto return_from_bridge;
3506 if (f->frametype == AST_FRAME_DTMF) {
3507 if ((who == c0) && p0->pulsedial) {
3508 ast_write(c1, f);
3509 } else if ((who == c1) && p1->pulsedial) {
3510 ast_write(c0, f);
3511 } else {
3512 *fo = f;
3513 *rc = who;
3514 res = AST_BRIDGE_COMPLETE;
3515 goto return_from_bridge;
3518 ast_frfree(f);
3520 /* Swap who gets priority */
3521 priority = !priority;
3524 return_from_bridge:
3525 if (op0 == p0)
3526 dahdi_enable_ec(p0);
3528 if (op1 == p1)
3529 dahdi_enable_ec(p1);
3531 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
3532 enable_dtmf_detect(op0);
3534 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
3535 enable_dtmf_detect(op1);
3537 dahdi_unlink(slave, master, 1);
3539 return res;
3542 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
3544 struct dahdi_pvt *p = newchan->tech_pvt;
3545 int x;
3546 ast_mutex_lock(&p->lock);
3547 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
3548 if (p->owner == oldchan) {
3549 p->owner = newchan;
3551 for (x = 0; x < 3; x++)
3552 if (p->subs[x].owner == oldchan) {
3553 if (!x)
3554 dahdi_unlink(NULL, p, 0);
3555 p->subs[x].owner = newchan;
3557 if (newchan->_state == AST_STATE_RINGING)
3558 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
3559 update_conf(p);
3560 ast_mutex_unlock(&p->lock);
3561 return 0;
3564 static int dahdi_ring_phone(struct dahdi_pvt *p)
3566 int x;
3567 int res;
3568 /* Make sure our transmit state is on hook */
3569 x = 0;
3570 x = DAHDI_ONHOOK;
3571 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
3572 do {
3573 x = DAHDI_RING;
3574 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
3575 if (res) {
3576 switch (errno) {
3577 case EBUSY:
3578 case EINTR:
3579 /* Wait just in case */
3580 usleep(10000);
3581 continue;
3582 case EINPROGRESS:
3583 res = 0;
3584 break;
3585 default:
3586 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
3587 res = 0;
3590 } while (res);
3591 return res;
3594 static void *ss_thread(void *data);
3596 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
3598 static int attempt_transfer(struct dahdi_pvt *p)
3600 /* In order to transfer, we need at least one of the channels to
3601 actually be in a call bridge. We can't conference two applications
3602 together (but then, why would we want to?) */
3603 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
3604 /* The three-way person we're about to transfer to could still be in MOH, so
3605 stop if now if appropriate */
3606 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
3607 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
3608 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
3609 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
3611 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
3612 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
3614 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
3615 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
3616 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
3617 return -1;
3619 /* Orphan the channel after releasing the lock */
3620 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3621 unalloc_sub(p, SUB_THREEWAY);
3622 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
3623 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
3624 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
3625 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
3627 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
3628 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
3630 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
3631 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
3632 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
3633 return -1;
3635 /* Three-way is now the REAL */
3636 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3637 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
3638 unalloc_sub(p, SUB_THREEWAY);
3639 /* Tell the caller not to hangup */
3640 return 1;
3641 } else {
3642 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
3643 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
3644 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3645 return -1;
3647 return 0;
3650 static int check_for_conference(struct dahdi_pvt *p)
3652 struct dahdi_confinfo ci;
3653 /* Fine if we already have a master, etc */
3654 if (p->master || (p->confno > -1))
3655 return 0;
3656 memset(&ci, 0, sizeof(ci));
3657 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
3658 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
3659 return 0;
3661 /* If we have no master and don't have a confno, then
3662 if we're in a conference, it's probably a MeetMe room or
3663 some such, so don't let us 3-way out! */
3664 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
3665 if (option_verbose > 2)
3666 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
3667 return 1;
3669 return 0;
3672 static int get_alarms(struct dahdi_pvt *p)
3674 int res;
3675 struct dahdi_spaninfo zi;
3676 #if defined(HAVE_DAHDI) || defined(HAVE_ZAPTEL_CHANALARMS)
3678 * The conditional compilation is needed only in asterisk-1.4 for
3679 * backward compatibility with old zaptel drivers that don't have
3680 * a DAHDI_PARAMS.chan_alarms field.
3682 struct dahdi_params params;
3683 #endif
3685 memset(&zi, 0, sizeof(zi));
3686 zi.spanno = p->span;
3688 /* First check for span alarms */
3689 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
3690 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
3691 return 0;
3693 if (zi.alarms != DAHDI_ALARM_NONE)
3694 return zi.alarms;
3695 #if defined(HAVE_DAHDI) || defined(HAVE_ZAPTEL_CHANALARMS)
3696 /* No alarms on the span. Check for channel alarms. */
3697 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
3698 return params.chan_alarms;
3699 /* ioctl failed */
3700 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
3701 #endif
3702 return DAHDI_ALARM_NONE;
3705 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
3707 struct dahdi_pvt *p = ast->tech_pvt;
3708 struct ast_frame *f = *dest;
3710 if (option_debug)
3711 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
3713 if (p->confirmanswer) {
3714 if (option_debug)
3715 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
3716 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
3717 of a DTMF digit */
3718 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3719 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3720 *dest = &p->subs[index].f;
3721 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
3722 p->confirmanswer = 0;
3723 } else if (p->callwaitcas) {
3724 if ((f->subclass == 'A') || (f->subclass == 'D')) {
3725 if (option_debug)
3726 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
3727 if (p->cidspill)
3728 free(p->cidspill);
3729 send_cwcidspill(p);
3731 if ((f->subclass != 'm') && (f->subclass != 'u'))
3732 p->callwaitcas = 0;
3733 p->subs[index].f.frametype = AST_FRAME_NULL;
3734 p->subs[index].f.subclass = 0;
3735 *dest = &p->subs[index].f;
3736 } else if (f->subclass == 'f') {
3737 /* Fax tone -- Handle and return NULL */
3738 if ((p->callprogress & 0x6) && !p->faxhandled) {
3739 p->faxhandled++;
3740 if (strcmp(ast->exten, "fax")) {
3741 const char *target_context = S_OR(ast->macrocontext, ast->context);
3743 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
3744 if (option_verbose > 2)
3745 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
3746 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
3747 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
3748 if (ast_async_goto(ast, target_context, "fax", 1))
3749 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
3750 } else
3751 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
3752 } else if (option_debug)
3753 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
3754 } else if (option_debug)
3755 ast_log(LOG_DEBUG, "Fax already handled\n");
3756 dahdi_confmute(p, 0);
3757 p->subs[index].f.frametype = AST_FRAME_NULL;
3758 p->subs[index].f.subclass = 0;
3759 *dest = &p->subs[index].f;
3760 } else if (f->subclass == 'm') {
3761 /* Confmute request */
3762 dahdi_confmute(p, 1);
3763 p->subs[index].f.frametype = AST_FRAME_NULL;
3764 p->subs[index].f.subclass = 0;
3765 *dest = &p->subs[index].f;
3766 } else if (f->subclass == 'u') {
3767 /* Unmute */
3768 dahdi_confmute(p, 0);
3769 p->subs[index].f.frametype = AST_FRAME_NULL;
3770 p->subs[index].f.subclass = 0;
3771 *dest = &p->subs[index].f;
3772 } else
3773 dahdi_confmute(p, 0);
3776 static void handle_alarms(struct dahdi_pvt *p, int alarms)
3778 const char *alarm_str = alarm2str(alarms);
3780 /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code
3781 * doesn't know what to do with it. Don't confuse users with log messages. */
3782 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
3783 p->unknown_alarm = 1;
3784 return;
3785 } else {
3786 p->unknown_alarm = 0;
3789 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
3790 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
3791 "Alarm: %s\r\n"
3792 "Channel: %d\r\n",
3793 alarm_str, p->channel);
3796 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
3798 int res, x;
3799 int index, mysig;
3800 char *c;
3801 struct dahdi_pvt *p = ast->tech_pvt;
3802 pthread_t threadid;
3803 pthread_attr_t attr;
3804 struct ast_channel *chan;
3805 struct ast_frame *f;
3807 index = dahdi_get_index(ast, p, 0);
3808 mysig = p->sig;
3809 if (p->outsigmod > -1)
3810 mysig = p->outsigmod;
3811 p->subs[index].f.frametype = AST_FRAME_NULL;
3812 p->subs[index].f.subclass = 0;
3813 p->subs[index].f.datalen = 0;
3814 p->subs[index].f.samples = 0;
3815 p->subs[index].f.mallocd = 0;
3816 p->subs[index].f.offset = 0;
3817 p->subs[index].f.src = "dahdi_handle_event";
3818 p->subs[index].f.data = NULL;
3819 f = &p->subs[index].f;
3821 if (index < 0)
3822 return &p->subs[index].f;
3823 if (p->fake_event) {
3824 res = p->fake_event;
3825 p->fake_event = 0;
3826 } else
3827 res = dahdi_get_event(p->subs[index].dfd);
3829 if (option_debug)
3830 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
3832 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
3833 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
3835 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
3836 #ifdef HAVE_PRI
3837 if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
3838 /* absorb event */
3839 } else {
3840 #endif
3841 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
3842 p->subs[index].f.subclass = res & 0xff;
3843 #ifdef HAVE_PRI
3845 #endif
3846 dahdi_handle_dtmfup(ast, index, &f);
3847 return f;
3850 if (res & DAHDI_EVENT_DTMFDOWN) {
3851 if (option_debug)
3852 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
3853 /* Mute conference */
3854 dahdi_confmute(p, 1);
3855 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
3856 p->subs[index].f.subclass = res & 0xff;
3857 return &p->subs[index].f;
3860 switch (res) {
3861 #ifdef DAHDI_EVENT_EC_DISABLED
3862 case DAHDI_EVENT_EC_DISABLED:
3863 if (option_verbose > 2)
3864 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
3865 p->echocanon = 0;
3866 break;
3867 #endif
3868 case DAHDI_EVENT_BITSCHANGED:
3869 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
3870 case DAHDI_EVENT_PULSE_START:
3871 /* Stop tone if there's a pulse start and the PBX isn't started */
3872 if (!ast->pbx)
3873 tone_zone_play_tone(p->subs[index].dfd, -1);
3874 break;
3875 case DAHDI_EVENT_DIALCOMPLETE:
3876 if (p->inalarm) break;
3877 if ((p->radio || (p->oprmode < 0))) break;
3878 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
3879 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
3880 return NULL;
3882 if (!x) { /* if not still dialing in driver */
3883 dahdi_enable_ec(p);
3884 if (p->echobreak) {
3885 dahdi_train_ec(p);
3886 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
3887 p->dop.op = DAHDI_DIAL_OP_REPLACE;
3888 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
3889 p->echobreak = 0;
3890 } else {
3891 p->dialing = 0;
3892 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
3893 /* if thru with dialing after offhook */
3894 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
3895 ast_setstate(ast, AST_STATE_UP);
3896 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3897 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3898 break;
3899 } else { /* if to state wait for offhook to dial rest */
3900 /* we now wait for off hook */
3901 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
3904 if (ast->_state == AST_STATE_DIALING) {
3905 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
3906 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
3907 } else if (p->confirmanswer || (!p->dialednone && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) || (mysig == SIG_SF) || (mysig == SIG_SFWINK) || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) || (mysig == SIG_SF_FEATB)))) {
3908 ast_setstate(ast, AST_STATE_RINGING);
3909 } else if (!p->answeronpolarityswitch) {
3910 ast_setstate(ast, AST_STATE_UP);
3911 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3912 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3913 /* If aops=0 and hops=1, this is necessary */
3914 p->polarity = POLARITY_REV;
3915 } else {
3916 /* Start clean, so we can catch the change to REV polarity when party answers */
3917 p->polarity = POLARITY_IDLE;
3922 break;
3923 case DAHDI_EVENT_ALARM:
3924 #ifdef HAVE_PRI
3925 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
3926 /* T309 is not enabled : hangup calls when alarm occurs */
3927 if (p->call) {
3928 if (p->pri && p->pri->pri) {
3929 if (!pri_grab(p, p->pri)) {
3930 pri_hangup(p->pri->pri, p->call, -1);
3931 pri_destroycall(p->pri->pri, p->call);
3932 p->call = NULL;
3933 pri_rel(p->pri);
3934 } else
3935 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
3936 } else
3937 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
3939 if (p->owner)
3940 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
3942 if (p->bearer)
3943 p->bearer->inalarm = 1;
3944 else
3945 #endif
3946 p->inalarm = 1;
3947 res = get_alarms(p);
3948 handle_alarms(p, res);
3949 #ifdef HAVE_LIBPRI
3950 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
3951 /* fall through intentionally */
3952 } else {
3953 break;
3955 #endif
3956 case DAHDI_EVENT_ONHOOK:
3957 if (p->radio) {
3958 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3959 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
3960 break;
3962 if (p->oprmode < 0)
3964 if (p->oprmode != -1) break;
3965 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
3967 /* Make sure it starts ringing */
3968 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
3969 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
3970 save_conference(p->oprpeer);
3971 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
3973 break;
3975 switch (p->sig) {
3976 case SIG_FXOLS:
3977 case SIG_FXOGS:
3978 case SIG_FXOKS:
3979 p->onhooktime = time(NULL);
3980 p->msgstate = -1;
3981 /* Check for some special conditions regarding call waiting */
3982 if (index == SUB_REAL) {
3983 /* The normal line was hung up */
3984 if (p->subs[SUB_CALLWAIT].owner) {
3985 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
3986 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
3987 if (option_verbose > 2)
3988 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
3989 unalloc_sub(p, SUB_CALLWAIT);
3990 #if 0
3991 p->subs[index].needanswer = 0;
3992 p->subs[index].needringing = 0;
3993 #endif
3994 p->callwaitingrepeat = 0;
3995 p->cidcwexpire = 0;
3996 p->owner = NULL;
3997 /* Don't start streaming audio yet if the incoming call isn't up yet */
3998 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
3999 p->dialing = 1;
4000 dahdi_ring_phone(p);
4001 } else if (p->subs[SUB_THREEWAY].owner) {
4002 unsigned int mssinceflash;
4003 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
4004 the private structure -- not especially easy or clean */
4005 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
4006 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
4007 ast_mutex_unlock(&p->lock);
4008 DEADLOCK_AVOIDANCE(&ast->lock);
4009 /* We can grab ast and p in that order, without worry. We should make sure
4010 nothing seriously bad has happened though like some sort of bizarre double
4011 masquerade! */
4012 ast_mutex_lock(&p->lock);
4013 if (p->owner != ast) {
4014 ast_log(LOG_WARNING, "This isn't good...\n");
4015 return NULL;
4018 if (!p->subs[SUB_THREEWAY].owner) {
4019 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
4020 return NULL;
4022 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
4023 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
4024 if (mssinceflash < MIN_MS_SINCE_FLASH) {
4025 /* It hasn't been long enough since the last flashook. This is probably a bounce on
4026 hanging up. Hangup both channels now */
4027 if (p->subs[SUB_THREEWAY].owner)
4028 ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
4029 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4030 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
4031 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4032 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
4033 if (p->transfer) {
4034 /* In any case this isn't a threeway call anymore */
4035 p->subs[SUB_REAL].inthreeway = 0;
4036 p->subs[SUB_THREEWAY].inthreeway = 0;
4037 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
4038 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
4039 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4040 /* Swap subs and dis-own channel */
4041 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4042 p->owner = NULL;
4043 /* Ring the phone */
4044 dahdi_ring_phone(p);
4045 } else {
4046 if ((res = attempt_transfer(p)) < 0) {
4047 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4048 if (p->subs[SUB_THREEWAY].owner)
4049 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4050 } else if (res) {
4051 /* Don't actually hang up at this point */
4052 if (p->subs[SUB_THREEWAY].owner)
4053 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4054 break;
4057 } else {
4058 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4059 if (p->subs[SUB_THREEWAY].owner)
4060 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4062 } else {
4063 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4064 /* Swap subs and dis-own channel */
4065 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4066 p->owner = NULL;
4067 /* Ring the phone */
4068 dahdi_ring_phone(p);
4071 } else {
4072 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
4074 /* Fall through */
4075 default:
4076 dahdi_disable_ec(p);
4077 return NULL;
4079 break;
4080 case DAHDI_EVENT_RINGOFFHOOK:
4081 if (p->inalarm) break;
4082 if (p->oprmode < 0)
4084 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
4086 /* Make sure it stops ringing */
4087 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
4088 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
4089 restore_conference(p->oprpeer);
4091 break;
4093 if (p->radio)
4095 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4096 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
4097 break;
4099 /* for E911, its supposed to wait for offhook then dial
4100 the second half of the dial string */
4101 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
4102 c = strchr(p->dialdest, '/');
4103 if (c)
4104 c++;
4105 else
4106 c = p->dialdest;
4107 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
4108 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
4109 if (strlen(p->dop.dialstr) > 4) {
4110 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
4111 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
4112 p->echorest[sizeof(p->echorest) - 1] = '\0';
4113 p->echobreak = 1;
4114 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
4115 } else
4116 p->echobreak = 0;
4117 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
4118 int saveerr = errno;
4120 x = DAHDI_ONHOOK;
4121 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
4122 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
4123 return NULL;
4125 p->dialing = 1;
4126 return &p->subs[index].f;
4128 switch (p->sig) {
4129 case SIG_FXOLS:
4130 case SIG_FXOGS:
4131 case SIG_FXOKS:
4132 switch (ast->_state) {
4133 case AST_STATE_RINGING:
4134 dahdi_enable_ec(p);
4135 dahdi_train_ec(p);
4136 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4137 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4138 /* Make sure it stops ringing */
4139 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
4140 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
4141 if (p->cidspill) {
4142 /* Cancel any running CallerID spill */
4143 free(p->cidspill);
4144 p->cidspill = NULL;
4146 p->dialing = 0;
4147 p->callwaitcas = 0;
4148 if (p->confirmanswer) {
4149 /* Ignore answer if "confirm answer" is enabled */
4150 p->subs[index].f.frametype = AST_FRAME_NULL;
4151 p->subs[index].f.subclass = 0;
4152 } else if (!ast_strlen_zero(p->dop.dialstr)) {
4153 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
4154 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4155 if (res < 0) {
4156 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4157 p->dop.dialstr[0] = '\0';
4158 return NULL;
4159 } else {
4160 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
4161 p->subs[index].f.frametype = AST_FRAME_NULL;
4162 p->subs[index].f.subclass = 0;
4163 p->dialing = 1;
4165 p->dop.dialstr[0] = '\0';
4166 ast_setstate(ast, AST_STATE_DIALING);
4167 } else
4168 ast_setstate(ast, AST_STATE_UP);
4169 return &p->subs[index].f;
4170 case AST_STATE_DOWN:
4171 ast_setstate(ast, AST_STATE_RING);
4172 ast->rings = 1;
4173 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4174 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
4175 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
4176 return &p->subs[index].f;
4177 case AST_STATE_UP:
4178 /* Make sure it stops ringing */
4179 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
4180 /* Okay -- probably call waiting*/
4181 if (ast_bridged_channel(p->owner))
4182 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4183 p->subs[index].needunhold = 1;
4184 break;
4185 case AST_STATE_RESERVED:
4186 /* Start up dialtone */
4187 if (has_voicemail(p))
4188 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
4189 else
4190 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
4191 break;
4192 default:
4193 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
4195 break;
4196 case SIG_FXSLS:
4197 case SIG_FXSGS:
4198 case SIG_FXSKS:
4199 if (ast->_state == AST_STATE_RING) {
4200 p->ringt = p->ringt_base;
4203 /* Fall through */
4204 case SIG_EM:
4205 case SIG_EM_E1:
4206 case SIG_EMWINK:
4207 case SIG_FEATD:
4208 case SIG_FEATDMF:
4209 case SIG_FEATDMF_TA:
4210 case SIG_E911:
4211 case SIG_FGC_CAMA:
4212 case SIG_FGC_CAMAMF:
4213 case SIG_FEATB:
4214 case SIG_SF:
4215 case SIG_SFWINK:
4216 case SIG_SF_FEATD:
4217 case SIG_SF_FEATDMF:
4218 case SIG_SF_FEATB:
4219 if (ast->_state == AST_STATE_PRERING)
4220 ast_setstate(ast, AST_STATE_RING);
4221 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
4222 if (option_debug)
4223 ast_log(LOG_DEBUG, "Ring detected\n");
4224 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4225 p->subs[index].f.subclass = AST_CONTROL_RING;
4226 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
4227 if (option_debug)
4228 ast_log(LOG_DEBUG, "Line answered\n");
4229 if (p->confirmanswer) {
4230 p->subs[index].f.frametype = AST_FRAME_NULL;
4231 p->subs[index].f.subclass = 0;
4232 } else {
4233 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4234 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4235 ast_setstate(ast, AST_STATE_UP);
4237 } else if (ast->_state != AST_STATE_RING)
4238 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
4239 break;
4240 default:
4241 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
4243 break;
4244 #ifdef DAHDI_EVENT_RINGBEGIN
4245 case DAHDI_EVENT_RINGBEGIN:
4246 switch (p->sig) {
4247 case SIG_FXSLS:
4248 case SIG_FXSGS:
4249 case SIG_FXSKS:
4250 if (ast->_state == AST_STATE_RING) {
4251 p->ringt = p->ringt_base;
4253 break;
4255 break;
4256 #endif
4257 case DAHDI_EVENT_RINGEROFF:
4258 if (p->inalarm) break;
4259 if ((p->radio || (p->oprmode < 0))) break;
4260 ast->rings++;
4261 if ((ast->rings > p->cidrings) && (p->cidspill)) {
4262 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
4263 free(p->cidspill);
4264 p->cidspill = NULL;
4265 p->callwaitcas = 0;
4267 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4268 p->subs[index].f.subclass = AST_CONTROL_RINGING;
4269 break;
4270 case DAHDI_EVENT_RINGERON:
4271 break;
4272 case DAHDI_EVENT_NOALARM:
4273 p->inalarm = 0;
4274 #ifdef HAVE_PRI
4275 /* Extremely unlikely but just in case */
4276 if (p->bearer)
4277 p->bearer->inalarm = 0;
4278 #endif
4279 if (!p->unknown_alarm) {
4280 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
4281 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
4282 "Channel: %d\r\n", p->channel);
4283 } else {
4284 p->unknown_alarm = 0;
4286 break;
4287 case DAHDI_EVENT_WINKFLASH:
4288 if (p->inalarm) break;
4289 if (p->radio) break;
4290 if (p->oprmode < 0) break;
4291 if (p->oprmode > 1)
4293 struct dahdi_params par;
4295 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
4297 if (!par.rxisoffhook)
4299 /* Make sure it stops ringing */
4300 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
4301 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
4302 save_conference(p);
4303 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
4306 break;
4308 /* Remember last time we got a flash-hook */
4309 gettimeofday(&p->flashtime, NULL);
4310 switch (mysig) {
4311 case SIG_FXOLS:
4312 case SIG_FXOGS:
4313 case SIG_FXOKS:
4314 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
4315 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
4316 p->callwaitcas = 0;
4318 if (index != SUB_REAL) {
4319 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
4320 goto winkflashdone;
4323 if (p->subs[SUB_CALLWAIT].owner) {
4324 /* Swap to call-wait */
4325 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
4326 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
4327 p->owner = p->subs[SUB_REAL].owner;
4328 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
4329 if (p->owner->_state == AST_STATE_RINGING) {
4330 ast_setstate(p->owner, AST_STATE_UP);
4331 p->subs[SUB_REAL].needanswer = 1;
4333 p->callwaitingrepeat = 0;
4334 p->cidcwexpire = 0;
4335 /* Start music on hold if appropriate */
4336 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
4337 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
4338 S_OR(p->mohsuggest, NULL),
4339 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4341 p->subs[SUB_CALLWAIT].needhold = 1;
4342 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
4343 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
4344 S_OR(p->mohsuggest, NULL),
4345 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4347 p->subs[SUB_REAL].needunhold = 1;
4348 } else if (!p->subs[SUB_THREEWAY].owner) {
4349 char cid_num[256];
4350 char cid_name[256];
4352 if (!p->threewaycalling) {
4353 /* Just send a flash if no 3-way calling */
4354 p->subs[SUB_REAL].needflash = 1;
4355 goto winkflashdone;
4356 } else if (!check_for_conference(p)) {
4357 if (p->dahditrcallerid && p->owner) {
4358 if (p->owner->cid.cid_num)
4359 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
4360 if (p->owner->cid.cid_name)
4361 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
4363 /* XXX This section needs much more error checking!!! XXX */
4364 /* Start a 3-way call if feasible */
4365 if (!((ast->pbx) ||
4366 (ast->_state == AST_STATE_UP) ||
4367 (ast->_state == AST_STATE_RING))) {
4368 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
4369 goto winkflashdone;
4371 if (alloc_sub(p, SUB_THREEWAY)) {
4372 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
4373 goto winkflashdone;
4375 /* Make new channel */
4376 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
4377 if (p->dahditrcallerid) {
4378 if (!p->origcid_num)
4379 p->origcid_num = ast_strdup(p->cid_num);
4380 if (!p->origcid_name)
4381 p->origcid_name = ast_strdup(p->cid_name);
4382 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
4383 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
4385 /* Swap things around between the three-way and real call */
4386 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4387 /* Disable echo canceller for better dialing */
4388 dahdi_disable_ec(p);
4389 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
4390 if (res)
4391 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
4392 p->owner = chan;
4393 pthread_attr_init(&attr);
4394 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
4395 if (!chan) {
4396 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
4397 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
4398 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
4399 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
4400 dahdi_enable_ec(p);
4401 ast_hangup(chan);
4402 } else {
4403 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
4404 int way3bridge = 0, cdr3way = 0;
4406 if (!other) {
4407 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
4408 } else
4409 way3bridge = 1;
4411 if (p->subs[SUB_THREEWAY].owner->cdr)
4412 cdr3way = 1;
4414 if (option_verbose > 2)
4415 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
4416 /* Start music on hold if appropriate */
4417 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
4418 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
4419 S_OR(p->mohsuggest, NULL),
4420 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4422 p->subs[SUB_THREEWAY].needhold = 1;
4424 pthread_attr_destroy(&attr);
4426 } else {
4427 /* Already have a 3 way call */
4428 if (p->subs[SUB_THREEWAY].inthreeway) {
4429 /* Call is already up, drop the last person */
4430 if (option_debug)
4431 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
4432 /* If the primary call isn't answered yet, use it */
4433 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
4434 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
4435 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4436 p->owner = p->subs[SUB_REAL].owner;
4438 /* Drop the last call and stop the conference */
4439 if (option_verbose > 2)
4440 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
4441 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4442 p->subs[SUB_REAL].inthreeway = 0;
4443 p->subs[SUB_THREEWAY].inthreeway = 0;
4444 } else {
4445 /* Lets see what we're up to */
4446 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
4447 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
4448 int otherindex = SUB_THREEWAY;
4449 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
4450 int way3bridge = 0, cdr3way = 0;
4452 if (!other) {
4453 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
4454 } else
4455 way3bridge = 1;
4457 if (p->subs[SUB_THREEWAY].owner->cdr)
4458 cdr3way = 1;
4460 if (option_verbose > 2)
4461 ast_verbose(VERBOSE_PREFIX_3 "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
4462 /* Put them in the threeway, and flip */
4463 p->subs[SUB_THREEWAY].inthreeway = 1;
4464 p->subs[SUB_REAL].inthreeway = 1;
4465 if (ast->_state == AST_STATE_UP) {
4466 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4467 otherindex = SUB_REAL;
4469 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
4470 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
4471 p->subs[otherindex].needunhold = 1;
4472 p->owner = p->subs[SUB_REAL].owner;
4473 if (ast->_state == AST_STATE_RINGING) {
4474 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
4475 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
4476 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
4478 } else {
4479 if (option_verbose > 2)
4480 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
4481 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4482 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4483 p->owner = p->subs[SUB_REAL].owner;
4484 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
4485 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
4486 p->subs[SUB_REAL].needunhold = 1;
4487 dahdi_enable_ec(p);
4492 winkflashdone:
4493 update_conf(p);
4494 break;
4495 case SIG_EM:
4496 case SIG_EM_E1:
4497 case SIG_EMWINK:
4498 case SIG_FEATD:
4499 case SIG_SF:
4500 case SIG_SFWINK:
4501 case SIG_SF_FEATD:
4502 case SIG_FXSLS:
4503 case SIG_FXSGS:
4504 if (p->dialing)
4505 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
4506 else
4507 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
4508 break;
4509 case SIG_FEATDMF_TA:
4510 switch (p->whichwink) {
4511 case 0:
4512 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
4513 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
4514 break;
4515 case 1:
4516 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
4517 break;
4518 case 2:
4519 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
4520 return NULL;
4522 p->whichwink++;
4523 /* Fall through */
4524 case SIG_FEATDMF:
4525 case SIG_E911:
4526 case SIG_FGC_CAMAMF:
4527 case SIG_FGC_CAMA:
4528 case SIG_FEATB:
4529 case SIG_SF_FEATDMF:
4530 case SIG_SF_FEATB:
4531 /* FGD MF *Must* wait for wink */
4532 if (!ast_strlen_zero(p->dop.dialstr)) {
4533 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4534 if (res < 0) {
4535 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4536 p->dop.dialstr[0] = '\0';
4537 return NULL;
4538 } else
4539 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
4541 p->dop.dialstr[0] = '\0';
4542 break;
4543 default:
4544 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
4546 break;
4547 case DAHDI_EVENT_HOOKCOMPLETE:
4548 if (p->inalarm) break;
4549 if ((p->radio || (p->oprmode < 0))) break;
4550 switch (mysig) {
4551 case SIG_FXSLS: /* only interesting for FXS */
4552 case SIG_FXSGS:
4553 case SIG_FXSKS:
4554 case SIG_EM:
4555 case SIG_EM_E1:
4556 case SIG_EMWINK:
4557 case SIG_FEATD:
4558 case SIG_SF:
4559 case SIG_SFWINK:
4560 case SIG_SF_FEATD:
4561 if (!ast_strlen_zero(p->dop.dialstr)) {
4562 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4563 if (res < 0) {
4564 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4565 p->dop.dialstr[0] = '\0';
4566 return NULL;
4567 } else
4568 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
4570 p->dop.dialstr[0] = '\0';
4571 p->dop.op = DAHDI_DIAL_OP_REPLACE;
4572 break;
4573 case SIG_FEATDMF:
4574 case SIG_FEATDMF_TA:
4575 case SIG_E911:
4576 case SIG_FGC_CAMA:
4577 case SIG_FGC_CAMAMF:
4578 case SIG_FEATB:
4579 case SIG_SF_FEATDMF:
4580 case SIG_SF_FEATB:
4581 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
4582 break;
4583 default:
4584 break;
4586 break;
4587 case DAHDI_EVENT_POLARITY:
4589 * If we get a Polarity Switch event, check to see
4590 * if we should change the polarity state and
4591 * mark the channel as UP or if this is an indication
4592 * of remote end disconnect.
4594 if (p->polarity == POLARITY_IDLE) {
4595 p->polarity = POLARITY_REV;
4596 if (p->answeronpolarityswitch &&
4597 ((ast->_state == AST_STATE_DIALING) ||
4598 (ast->_state == AST_STATE_RINGING))) {
4599 ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
4600 ast_setstate(p->owner, AST_STATE_UP);
4601 if (p->hanguponpolarityswitch) {
4602 gettimeofday(&p->polaritydelaytv, NULL);
4604 } else
4605 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
4607 /* Removed else statement from here as it was preventing hangups from ever happening*/
4608 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
4609 if (p->hanguponpolarityswitch &&
4610 (p->polarityonanswerdelay > 0) &&
4611 (p->polarity == POLARITY_REV) &&
4612 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
4613 /* Added log_debug information below to provide a better indication of what is going on */
4614 ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
4616 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
4617 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
4618 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
4619 p->polarity = POLARITY_IDLE;
4620 } else {
4621 ast_log(LOG_DEBUG, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
4623 } else {
4624 p->polarity = POLARITY_IDLE;
4625 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
4627 /* Added more log_debug information below to provide a better indication of what is going on */
4628 ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
4629 break;
4630 default:
4631 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
4633 return &p->subs[index].f;
4636 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
4638 struct dahdi_pvt *p = ast->tech_pvt;
4639 int res;
4640 int usedindex=-1;
4641 int index;
4642 struct ast_frame *f;
4645 index = dahdi_get_index(ast, p, 1);
4647 p->subs[index].f.frametype = AST_FRAME_NULL;
4648 p->subs[index].f.datalen = 0;
4649 p->subs[index].f.samples = 0;
4650 p->subs[index].f.mallocd = 0;
4651 p->subs[index].f.offset = 0;
4652 p->subs[index].f.subclass = 0;
4653 p->subs[index].f.delivery = ast_tv(0,0);
4654 p->subs[index].f.src = "dahdi_exception";
4655 p->subs[index].f.data = NULL;
4658 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
4659 /* If nobody owns us, absorb the event appropriately, otherwise
4660 we loop indefinitely. This occurs when, during call waiting, the
4661 other end hangs up our channel so that it no longer exists, but we
4662 have neither FLASH'd nor ONHOOK'd to signify our desire to
4663 change to the other channel. */
4664 if (p->fake_event) {
4665 res = p->fake_event;
4666 p->fake_event = 0;
4667 } else
4668 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
4669 /* Switch to real if there is one and this isn't something really silly... */
4670 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
4671 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
4672 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
4673 p->owner = p->subs[SUB_REAL].owner;
4674 if (p->owner && ast_bridged_channel(p->owner))
4675 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4676 p->subs[SUB_REAL].needunhold = 1;
4678 switch (res) {
4679 case DAHDI_EVENT_ONHOOK:
4680 dahdi_disable_ec(p);
4681 if (p->owner) {
4682 if (option_verbose > 2)
4683 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
4684 dahdi_ring_phone(p);
4685 p->callwaitingrepeat = 0;
4686 p->cidcwexpire = 0;
4687 } else
4688 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
4689 update_conf(p);
4690 break;
4691 case DAHDI_EVENT_RINGOFFHOOK:
4692 dahdi_enable_ec(p);
4693 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
4694 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
4695 p->subs[SUB_REAL].needanswer = 1;
4696 p->dialing = 0;
4698 break;
4699 case DAHDI_EVENT_HOOKCOMPLETE:
4700 case DAHDI_EVENT_RINGERON:
4701 case DAHDI_EVENT_RINGEROFF:
4702 /* Do nothing */
4703 break;
4704 case DAHDI_EVENT_WINKFLASH:
4705 gettimeofday(&p->flashtime, NULL);
4706 if (p->owner) {
4707 if (option_verbose > 2)
4708 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
4709 if (p->owner->_state != AST_STATE_UP) {
4710 /* Answer if necessary */
4711 usedindex = dahdi_get_index(p->owner, p, 0);
4712 if (usedindex > -1) {
4713 p->subs[usedindex].needanswer = 1;
4715 ast_setstate(p->owner, AST_STATE_UP);
4717 p->callwaitingrepeat = 0;
4718 p->cidcwexpire = 0;
4719 if (ast_bridged_channel(p->owner))
4720 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4721 p->subs[SUB_REAL].needunhold = 1;
4722 } else
4723 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
4724 update_conf(p);
4725 break;
4726 default:
4727 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
4729 f = &p->subs[index].f;
4730 return f;
4732 if (!(p->radio || (p->oprmode < 0)) && option_debug)
4733 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
4734 /* If it's not us, return NULL immediately */
4735 if (ast != p->owner) {
4736 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
4737 f = &p->subs[index].f;
4738 return f;
4740 f = dahdi_handle_event(ast);
4741 return f;
4744 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
4746 struct dahdi_pvt *p = ast->tech_pvt;
4747 struct ast_frame *f;
4748 ast_mutex_lock(&p->lock);
4749 f = __dahdi_exception(ast);
4750 ast_mutex_unlock(&p->lock);
4751 return f;
4754 static struct ast_frame *dahdi_read(struct ast_channel *ast)
4756 struct dahdi_pvt *p = ast->tech_pvt;
4757 int res;
4758 int index;
4759 void *readbuf;
4760 struct ast_frame *f;
4762 while (ast_mutex_trylock(&p->lock)) {
4763 DEADLOCK_AVOIDANCE(&ast->lock);
4766 index = dahdi_get_index(ast, p, 0);
4768 /* Hang up if we don't really exist */
4769 if (index < 0) {
4770 ast_log(LOG_WARNING, "We dont exist?\n");
4771 ast_mutex_unlock(&p->lock);
4772 return NULL;
4775 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
4777 p->subs[index].f.frametype = AST_FRAME_NULL;
4778 p->subs[index].f.datalen = 0;
4779 p->subs[index].f.samples = 0;
4780 p->subs[index].f.mallocd = 0;
4781 p->subs[index].f.offset = 0;
4782 p->subs[index].f.subclass = 0;
4783 p->subs[index].f.delivery = ast_tv(0,0);
4784 p->subs[index].f.src = "dahdi_read";
4785 p->subs[index].f.data = NULL;
4787 /* make sure it sends initial key state as first frame */
4788 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
4790 struct dahdi_params ps;
4792 ps.channo = p->channel;
4793 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
4794 ast_mutex_unlock(&p->lock);
4795 return NULL;
4797 p->firstradio = 1;
4798 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4799 if (ps.rxisoffhook)
4801 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
4803 else
4805 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
4807 ast_mutex_unlock(&p->lock);
4808 return &p->subs[index].f;
4810 if (p->ringt == 1) {
4811 ast_mutex_unlock(&p->lock);
4812 return NULL;
4814 else if (p->ringt > 0)
4815 p->ringt--;
4817 if (p->subs[index].needringing) {
4818 /* Send ringing frame if requested */
4819 p->subs[index].needringing = 0;
4820 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4821 p->subs[index].f.subclass = AST_CONTROL_RINGING;
4822 ast_setstate(ast, AST_STATE_RINGING);
4823 ast_mutex_unlock(&p->lock);
4824 return &p->subs[index].f;
4827 if (p->subs[index].needbusy) {
4828 /* Send busy frame if requested */
4829 p->subs[index].needbusy = 0;
4830 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4831 p->subs[index].f.subclass = AST_CONTROL_BUSY;
4832 ast_mutex_unlock(&p->lock);
4833 return &p->subs[index].f;
4836 if (p->subs[index].needcongestion) {
4837 /* Send congestion frame if requested */
4838 p->subs[index].needcongestion = 0;
4839 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4840 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
4841 ast_mutex_unlock(&p->lock);
4842 return &p->subs[index].f;
4845 if (p->subs[index].needcallerid) {
4846 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
4847 S_OR(p->lastcid_name, NULL),
4848 S_OR(p->lastcid_num, NULL)
4850 p->subs[index].needcallerid = 0;
4853 if (p->subs[index].needanswer) {
4854 /* Send answer frame if requested */
4855 p->subs[index].needanswer = 0;
4856 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4857 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4858 ast_mutex_unlock(&p->lock);
4859 return &p->subs[index].f;
4862 if (p->subs[index].needflash) {
4863 /* Send answer frame if requested */
4864 p->subs[index].needflash = 0;
4865 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4866 p->subs[index].f.subclass = AST_CONTROL_FLASH;
4867 ast_mutex_unlock(&p->lock);
4868 return &p->subs[index].f;
4871 if (p->subs[index].needhold) {
4872 /* Send answer frame if requested */
4873 p->subs[index].needhold = 0;
4874 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4875 p->subs[index].f.subclass = AST_CONTROL_HOLD;
4876 ast_mutex_unlock(&p->lock);
4877 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
4878 return &p->subs[index].f;
4881 if (p->subs[index].needunhold) {
4882 /* Send answer frame if requested */
4883 p->subs[index].needunhold = 0;
4884 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4885 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
4886 ast_mutex_unlock(&p->lock);
4887 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
4888 return &p->subs[index].f;
4891 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
4892 if (!p->subs[index].linear) {
4893 p->subs[index].linear = 1;
4894 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
4895 if (res)
4896 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
4898 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
4899 (ast->rawreadformat == AST_FORMAT_ALAW)) {
4900 if (p->subs[index].linear) {
4901 p->subs[index].linear = 0;
4902 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
4903 if (res)
4904 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
4906 } else {
4907 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
4908 ast_mutex_unlock(&p->lock);
4909 return NULL;
4911 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
4912 CHECK_BLOCKING(ast);
4913 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
4914 ast_clear_flag(ast, AST_FLAG_BLOCKING);
4915 /* Check for hangup */
4916 if (res < 0) {
4917 f = NULL;
4918 if (res == -1) {
4919 if (errno == EAGAIN) {
4920 /* Return "NULL" frame if there is nobody there */
4921 ast_mutex_unlock(&p->lock);
4922 return &p->subs[index].f;
4923 } else if (errno == ELAST) {
4924 f = __dahdi_exception(ast);
4925 } else
4926 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
4928 ast_mutex_unlock(&p->lock);
4929 return f;
4931 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
4932 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
4933 f = __dahdi_exception(ast);
4934 ast_mutex_unlock(&p->lock);
4935 return f;
4937 if (p->tdd) { /* if in TDD mode, see if we receive that */
4938 int c;
4940 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
4941 if (c < 0) {
4942 ast_log(LOG_DEBUG,"tdd_feed failed\n");
4943 ast_mutex_unlock(&p->lock);
4944 return NULL;
4946 if (c) { /* if a char to return */
4947 p->subs[index].f.subclass = 0;
4948 p->subs[index].f.frametype = AST_FRAME_TEXT;
4949 p->subs[index].f.mallocd = 0;
4950 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
4951 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
4952 p->subs[index].f.datalen = 1;
4953 *((char *) p->subs[index].f.data) = c;
4954 ast_mutex_unlock(&p->lock);
4955 return &p->subs[index].f;
4958 /* Ensure the CW timer decrements only on a single subchannel */
4959 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
4960 p->callwaitingrepeat--;
4962 if (p->cidcwexpire)
4963 p->cidcwexpire--;
4964 /* Repeat callwaiting */
4965 if (p->callwaitingrepeat == 1) {
4966 p->callwaitrings++;
4967 dahdi_callwait(ast);
4969 /* Expire CID/CW */
4970 if (p->cidcwexpire == 1) {
4971 if (option_verbose > 2)
4972 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
4973 restore_conference(p);
4975 if (p->subs[index].linear) {
4976 p->subs[index].f.datalen = READ_SIZE * 2;
4977 } else
4978 p->subs[index].f.datalen = READ_SIZE;
4980 /* Handle CallerID Transmission */
4981 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
4982 send_callerid(p);
4985 p->subs[index].f.frametype = AST_FRAME_VOICE;
4986 p->subs[index].f.subclass = ast->rawreadformat;
4987 p->subs[index].f.samples = READ_SIZE;
4988 p->subs[index].f.mallocd = 0;
4989 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
4990 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
4991 #if 0
4992 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
4993 #endif
4994 if (p->dialing || /* Transmitting something */
4995 (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
4996 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
4998 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
4999 don't send anything */
5000 p->subs[index].f.frametype = AST_FRAME_NULL;
5001 p->subs[index].f.subclass = 0;
5002 p->subs[index].f.samples = 0;
5003 p->subs[index].f.mallocd = 0;
5004 p->subs[index].f.offset = 0;
5005 p->subs[index].f.data = NULL;
5006 p->subs[index].f.datalen= 0;
5008 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
5009 /* Perform busy detection. etc on the dahdi line */
5010 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
5011 if (f) {
5012 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
5013 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
5014 /* Treat this as a "hangup" instead of a "busy" on the assumption that
5015 a busy */
5016 f = NULL;
5018 } else if (f->frametype == AST_FRAME_DTMF) {
5019 #ifdef HAVE_PRI
5020 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
5021 /* Don't accept in-band DTMF when in overlap dial mode */
5022 f->frametype = AST_FRAME_NULL;
5023 f->subclass = 0;
5025 #endif
5026 /* DSP clears us of being pulse */
5027 p->pulsedial = 0;
5030 } else
5031 f = &p->subs[index].f;
5033 if (f && (f->frametype == AST_FRAME_DTMF))
5034 dahdi_handle_dtmfup(ast, index, &f);
5036 /* If we have a fake_event, trigger exception to handle it */
5037 if (p->fake_event)
5038 ast_set_flag(ast, AST_FLAG_EXCEPTION);
5040 ast_mutex_unlock(&p->lock);
5041 return f;
5044 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
5046 int sent=0;
5047 int size;
5048 int res;
5049 int fd;
5050 fd = p->subs[index].dfd;
5051 while (len) {
5052 size = len;
5053 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
5054 size = (linear ? READ_SIZE * 2 : READ_SIZE);
5055 res = write(fd, buf, size);
5056 if (res != size) {
5057 if (option_debug)
5058 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
5059 return sent;
5061 len -= size;
5062 buf += size;
5064 return sent;
5067 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
5069 struct dahdi_pvt *p = ast->tech_pvt;
5070 int res;
5071 int index;
5072 index = dahdi_get_index(ast, p, 0);
5073 if (index < 0) {
5074 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
5075 return -1;
5078 #if 0
5079 #ifdef HAVE_PRI
5080 ast_mutex_lock(&p->lock);
5081 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5082 if (p->pri->pri) {
5083 if (!pri_grab(p, p->pri)) {
5084 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5085 pri_rel(p->pri);
5086 } else
5087 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5089 p->proceeding=1;
5091 ast_mutex_unlock(&p->lock);
5092 #endif
5093 #endif
5094 /* Write a frame of (presumably voice) data */
5095 if (frame->frametype != AST_FRAME_VOICE) {
5096 if (frame->frametype != AST_FRAME_IMAGE)
5097 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
5098 return 0;
5100 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
5101 (frame->subclass != AST_FORMAT_ULAW) &&
5102 (frame->subclass != AST_FORMAT_ALAW)) {
5103 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
5104 return -1;
5106 if (p->dialing) {
5107 if (option_debug)
5108 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
5109 return 0;
5111 if (!p->owner) {
5112 if (option_debug)
5113 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
5114 return 0;
5116 if (p->cidspill) {
5117 if (option_debug)
5118 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
5119 return 0;
5121 /* Return if it's not valid data */
5122 if (!frame->data || !frame->datalen)
5123 return 0;
5125 if (frame->subclass == AST_FORMAT_SLINEAR) {
5126 if (!p->subs[index].linear) {
5127 p->subs[index].linear = 1;
5128 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
5129 if (res)
5130 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
5132 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
5133 } else {
5134 /* x-law already */
5135 if (p->subs[index].linear) {
5136 p->subs[index].linear = 0;
5137 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
5138 if (res)
5139 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
5141 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
5143 if (res < 0) {
5144 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
5145 return -1;
5147 return 0;
5150 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
5152 struct dahdi_pvt *p = chan->tech_pvt;
5153 int res=-1;
5154 int index;
5155 int func = DAHDI_FLASH;
5156 ast_mutex_lock(&p->lock);
5157 index = dahdi_get_index(chan, p, 0);
5158 if (option_debug)
5159 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
5160 if (index == SUB_REAL) {
5161 switch (condition) {
5162 case AST_CONTROL_BUSY:
5163 #ifdef HAVE_PRI
5164 if (p->priindication_oob && p->sig == SIG_PRI) {
5165 chan->hangupcause = AST_CAUSE_USER_BUSY;
5166 chan->_softhangup |= AST_SOFTHANGUP_DEV;
5167 res = 0;
5168 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5169 if (p->pri->pri) {
5170 if (!pri_grab(p, p->pri)) {
5171 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5172 pri_rel(p->pri);
5174 else
5175 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5177 p->progress = 1;
5178 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
5179 } else
5180 #endif
5181 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
5182 break;
5183 case AST_CONTROL_RINGING:
5184 #ifdef HAVE_PRI
5185 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
5186 if (p->pri->pri) {
5187 if (!pri_grab(p, p->pri)) {
5188 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5189 pri_rel(p->pri);
5191 else
5192 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5194 p->alerting = 1;
5196 #endif
5197 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
5198 if (chan->_state != AST_STATE_UP) {
5199 if ((chan->_state != AST_STATE_RING) ||
5200 ((p->sig != SIG_FXSKS) &&
5201 (p->sig != SIG_FXSLS) &&
5202 (p->sig != SIG_FXSGS)))
5203 ast_setstate(chan, AST_STATE_RINGING);
5205 break;
5206 case AST_CONTROL_PROCEEDING:
5207 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
5208 #ifdef HAVE_PRI
5209 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5210 if (p->pri->pri) {
5211 if (!pri_grab(p, p->pri)) {
5212 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5213 pri_rel(p->pri);
5215 else
5216 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5218 p->proceeding = 1;
5220 #endif
5221 /* don't continue in ast_indicate */
5222 res = 0;
5223 break;
5224 case AST_CONTROL_PROGRESS:
5225 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
5226 #ifdef HAVE_PRI
5227 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */
5228 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5229 if (p->pri->pri) {
5230 if (!pri_grab(p, p->pri)) {
5231 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5232 pri_rel(p->pri);
5234 else
5235 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5237 p->progress = 1;
5239 #endif
5240 /* don't continue in ast_indicate */
5241 res = 0;
5242 break;
5243 case AST_CONTROL_CONGESTION:
5244 chan->hangupcause = AST_CAUSE_CONGESTION;
5245 #ifdef HAVE_PRI
5246 if (p->priindication_oob && p->sig == SIG_PRI) {
5247 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
5248 chan->_softhangup |= AST_SOFTHANGUP_DEV;
5249 res = 0;
5250 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5251 if (p->pri) {
5252 if (!pri_grab(p, p->pri)) {
5253 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5254 pri_rel(p->pri);
5255 } else
5256 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5258 p->progress = 1;
5259 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5260 } else
5261 #endif
5262 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5263 break;
5264 case AST_CONTROL_HOLD:
5265 #ifdef HAVE_PRI
5266 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
5267 if (!pri_grab(p, p->pri)) {
5268 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
5269 pri_rel(p->pri);
5270 } else
5271 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5272 } else
5273 #endif
5274 ast_moh_start(chan, data, p->mohinterpret);
5275 break;
5276 case AST_CONTROL_UNHOLD:
5277 #ifdef HAVE_PRI
5278 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
5279 if (!pri_grab(p, p->pri)) {
5280 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
5281 pri_rel(p->pri);
5282 } else
5283 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5284 } else
5285 #endif
5286 ast_moh_stop(chan);
5287 break;
5288 case AST_CONTROL_RADIO_KEY:
5289 if (p->radio)
5290 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
5291 res = 0;
5292 break;
5293 case AST_CONTROL_RADIO_UNKEY:
5294 if (p->radio)
5295 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
5296 res = 0;
5297 break;
5298 case AST_CONTROL_FLASH:
5299 /* flash hookswitch */
5300 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
5301 /* Clear out the dial buffer */
5302 p->dop.dialstr[0] = '\0';
5303 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
5304 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
5305 chan->name, strerror(errno));
5306 } else
5307 res = 0;
5308 } else
5309 res = 0;
5310 break;
5311 case AST_CONTROL_SRCUPDATE:
5312 res = 0;
5313 break;
5314 case -1:
5315 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5316 break;
5318 } else
5319 res = 0;
5320 ast_mutex_unlock(&p->lock);
5321 return res;
5324 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
5326 struct ast_channel *tmp;
5327 int deflaw;
5328 int res;
5329 int x,y;
5330 int features;
5331 char *b2 = NULL;
5332 struct dahdi_params ps;
5333 char chanprefix[*dahdi_chan_name_len + 4];
5335 if (i->subs[index].owner) {
5336 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
5337 return NULL;
5339 y = 1;
5340 do {
5341 if (b2)
5342 free(b2);
5343 #ifdef HAVE_PRI
5344 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
5345 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
5346 else
5347 #endif
5348 if (i->channel == CHAN_PSEUDO)
5349 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
5350 else
5351 b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
5352 for (x = 0; x < 3; x++) {
5353 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
5354 break;
5356 y++;
5357 } while (x < 3);
5358 strcpy(chanprefix, dahdi_chan_name);
5359 strcat(chanprefix, "/%s");
5360 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
5361 if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
5362 free(b2);
5363 if (!tmp)
5364 return NULL;
5365 tmp->tech = chan_tech;
5366 ps.channo = i->channel;
5367 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
5368 if (res) {
5369 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
5370 ps.curlaw = DAHDI_LAW_MULAW;
5372 if (ps.curlaw == DAHDI_LAW_ALAW)
5373 deflaw = AST_FORMAT_ALAW;
5374 else
5375 deflaw = AST_FORMAT_ULAW;
5376 if (law) {
5377 if (law == DAHDI_LAW_ALAW)
5378 deflaw = AST_FORMAT_ALAW;
5379 else
5380 deflaw = AST_FORMAT_ULAW;
5382 tmp->fds[0] = i->subs[index].dfd;
5383 tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
5384 /* Start out assuming ulaw since it's smaller :) */
5385 tmp->rawreadformat = deflaw;
5386 tmp->readformat = deflaw;
5387 tmp->rawwriteformat = deflaw;
5388 tmp->writeformat = deflaw;
5389 i->subs[index].linear = 0;
5390 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
5391 features = 0;
5392 if (index == SUB_REAL) {
5393 if (i->busydetect && CANBUSYDETECT(i))
5394 features |= DSP_FEATURE_BUSY_DETECT;
5395 if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
5396 features |= DSP_FEATURE_CALL_PROGRESS;
5397 if ((!i->outgoing && (i->callprogress & 4)) ||
5398 (i->outgoing && (i->callprogress & 2))) {
5399 features |= DSP_FEATURE_FAX_DETECT;
5401 #ifdef DAHDI_TONEDETECT
5402 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
5403 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
5404 #endif
5405 i->hardwaredtmf = 0;
5406 features |= DSP_FEATURE_DTMF_DETECT;
5407 #ifdef DAHDI_TONEDETECT
5408 } else if (NEED_MFDETECT(i)) {
5409 i->hardwaredtmf = 1;
5410 features |= DSP_FEATURE_DTMF_DETECT;
5412 #endif
5414 if (features) {
5415 if (i->dsp) {
5416 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
5417 } else {
5418 if (i->channel != CHAN_PSEUDO)
5419 i->dsp = ast_dsp_new();
5420 else
5421 i->dsp = NULL;
5422 if (i->dsp) {
5423 i->dsp_features = features;
5424 #ifdef HAVE_PRI
5425 /* We cannot do progress detection until receives PROGRESS message */
5426 if (i->outgoing && (i->sig == SIG_PRI)) {
5427 /* Remember requested DSP features, don't treat
5428 talking as ANSWER */
5429 i->dsp_features = features & ~DSP_PROGRESS_TALK;
5430 features = 0;
5432 #endif
5433 ast_dsp_set_features(i->dsp, features);
5434 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
5435 if (!ast_strlen_zero(progzone))
5436 ast_dsp_set_call_progress_zone(i->dsp, progzone);
5437 if (i->busydetect && CANBUSYDETECT(i)) {
5438 ast_dsp_set_busy_count(i->dsp, i->busycount);
5439 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
5445 if (state == AST_STATE_RING)
5446 tmp->rings = 1;
5447 tmp->tech_pvt = i;
5448 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
5449 /* Only FXO signalled stuff can be picked up */
5450 tmp->callgroup = i->callgroup;
5451 tmp->pickupgroup = i->pickupgroup;
5453 if (!ast_strlen_zero(i->language))
5454 ast_string_field_set(tmp, language, i->language);
5455 if (!i->owner)
5456 i->owner = tmp;
5457 if (!ast_strlen_zero(i->accountcode))
5458 ast_string_field_set(tmp, accountcode, i->accountcode);
5459 if (i->amaflags)
5460 tmp->amaflags = i->amaflags;
5461 i->subs[index].owner = tmp;
5462 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
5463 ast_string_field_set(tmp, call_forward, i->call_forward);
5464 /* If we've been told "no ADSI" then enforce it */
5465 if (!i->adsi)
5466 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
5467 if (!ast_strlen_zero(i->exten))
5468 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
5469 if (!ast_strlen_zero(i->rdnis))
5470 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
5471 if (!ast_strlen_zero(i->dnid))
5472 tmp->cid.cid_dnid = ast_strdup(i->dnid);
5474 /* Don't use ast_set_callerid() here because it will
5475 * generate a needless NewCallerID event */
5476 #ifdef PRI_ANI
5477 if (!ast_strlen_zero(i->cid_ani))
5478 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
5479 else
5480 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5481 #else
5482 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5483 #endif
5484 tmp->cid.cid_pres = i->callingpres;
5485 tmp->cid.cid_ton = i->cid_ton;
5486 #ifdef HAVE_PRI
5487 tmp->transfercapability = transfercapability;
5488 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
5489 if (transfercapability & PRI_TRANS_CAP_DIGITAL)
5490 i->digital = 1;
5491 /* Assume calls are not idle calls unless we're told differently */
5492 i->isidlecall = 0;
5493 i->alreadyhungup = 0;
5494 #endif
5495 /* clear the fake event in case we posted one before we had ast_channel */
5496 i->fake_event = 0;
5497 /* Assure there is no confmute on this channel */
5498 dahdi_confmute(i, 0);
5499 /* Configure the new channel jb */
5500 ast_jb_configure(tmp, &global_jbconf);
5501 if (startpbx) {
5502 if (ast_pbx_start(tmp)) {
5503 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
5504 ast_hangup(tmp);
5505 i->owner = NULL;
5506 return NULL;
5510 ast_module_ref(ast_module_info->self);
5512 return tmp;
5516 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
5518 char c;
5520 *str = 0; /* start with empty output buffer */
5521 for (;;)
5523 /* Wait for the first digit (up to specified ms). */
5524 c = ast_waitfordigit(chan, ms);
5525 /* if timeout, hangup or error, return as such */
5526 if (c < 1)
5527 return c;
5528 *str++ = c;
5529 *str = 0;
5530 if (strchr(term, c))
5531 return 1;
5535 static int dahdi_wink(struct dahdi_pvt *p, int index)
5537 int j;
5538 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
5539 for (;;)
5541 /* set bits of interest */
5542 j = DAHDI_IOMUX_SIGEVENT;
5543 /* wait for some happening */
5544 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
5545 /* exit loop if we have it */
5546 if (j & DAHDI_IOMUX_SIGEVENT) break;
5548 /* get the event info */
5549 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
5550 return 0;
5553 static void *ss_thread(void *data)
5555 struct ast_channel *chan = data;
5556 struct dahdi_pvt *p = chan->tech_pvt;
5557 char exten[AST_MAX_EXTENSION] = "";
5558 char exten2[AST_MAX_EXTENSION] = "";
5559 unsigned char buf[256];
5560 char dtmfcid[300];
5561 char dtmfbuf[300];
5562 struct callerid_state *cs = NULL;
5563 char *name = NULL, *number = NULL;
5564 int distMatches;
5565 int curRingData[3];
5566 int receivedRingT;
5567 int counter1;
5568 int counter;
5569 int samples = 0;
5570 struct ast_smdi_md_message *smdi_msg = NULL;
5571 int flags;
5572 int i;
5573 int timeout;
5574 int getforward = 0;
5575 char *s1, *s2;
5576 int len = 0;
5577 int res;
5578 int index;
5580 ast_mutex_lock(&ss_thread_lock);
5581 ss_thread_count++;
5582 ast_mutex_unlock(&ss_thread_lock);
5583 /* in the bizarre case where the channel has become a zombie before we
5584 even get started here, abort safely
5586 if (!p) {
5587 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
5588 ast_hangup(chan);
5589 goto quit;
5591 if (option_verbose > 2)
5592 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
5593 index = dahdi_get_index(chan, p, 1);
5594 if (index < 0) {
5595 ast_log(LOG_WARNING, "Huh?\n");
5596 ast_hangup(chan);
5597 goto quit;
5599 if (p->dsp)
5600 ast_dsp_digitreset(p->dsp);
5601 switch (p->sig) {
5602 #ifdef HAVE_PRI
5603 case SIG_PRI:
5604 /* Now loop looking for an extension */
5605 ast_copy_string(exten, p->exten, sizeof(exten));
5606 len = strlen(exten);
5607 res = 0;
5608 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
5609 if (len && !ast_ignore_pattern(chan->context, exten))
5610 tone_zone_play_tone(p->subs[index].dfd, -1);
5611 else
5612 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5613 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
5614 timeout = matchdigittimeout;
5615 else
5616 timeout = gendigittimeout;
5617 res = ast_waitfordigit(chan, timeout);
5618 if (res < 0) {
5619 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5620 ast_hangup(chan);
5621 goto quit;
5622 } else if (res) {
5623 exten[len++] = res;
5624 exten[len] = '\0';
5625 } else
5626 break;
5628 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
5629 if (ast_strlen_zero(exten)) {
5630 if (option_verbose > 2)
5631 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
5632 exten[0] = 's';
5633 exten[1] = '\0';
5635 tone_zone_play_tone(p->subs[index].dfd, -1);
5636 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
5637 /* Start the real PBX */
5638 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5639 if (p->dsp) ast_dsp_digitreset(p->dsp);
5640 dahdi_enable_ec(p);
5641 ast_setstate(chan, AST_STATE_RING);
5642 res = ast_pbx_run(chan);
5643 if (res) {
5644 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
5646 } else {
5647 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
5648 chan->hangupcause = AST_CAUSE_UNALLOCATED;
5649 ast_hangup(chan);
5650 p->exten[0] = '\0';
5651 /* Since we send release complete here, we won't get one */
5652 p->call = NULL;
5654 goto quit;
5655 break;
5656 #endif
5657 case SIG_FEATD:
5658 case SIG_FEATDMF:
5659 case SIG_FEATDMF_TA:
5660 case SIG_E911:
5661 case SIG_FGC_CAMAMF:
5662 case SIG_FEATB:
5663 case SIG_EMWINK:
5664 case SIG_SF_FEATD:
5665 case SIG_SF_FEATDMF:
5666 case SIG_SF_FEATB:
5667 case SIG_SFWINK:
5668 if (dahdi_wink(p, index))
5669 goto quit;
5670 /* Fall through */
5671 case SIG_EM:
5672 case SIG_EM_E1:
5673 case SIG_SF:
5674 case SIG_FGC_CAMA:
5675 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5676 if (p->dsp)
5677 ast_dsp_digitreset(p->dsp);
5678 /* set digit mode appropriately */
5679 if (p->dsp) {
5680 if (NEED_MFDETECT(p))
5681 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
5682 else
5683 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5685 memset(dtmfbuf, 0, sizeof(dtmfbuf));
5686 /* Wait for the first digit only if immediate=no */
5687 if (!p->immediate)
5688 /* Wait for the first digit (up to 5 seconds). */
5689 res = ast_waitfordigit(chan, 5000);
5690 else
5691 res = 0;
5692 if (res > 0) {
5693 /* save first char */
5694 dtmfbuf[0] = res;
5695 switch (p->sig) {
5696 case SIG_FEATD:
5697 case SIG_SF_FEATD:
5698 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
5699 if (res > 0)
5700 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
5701 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5702 break;
5703 case SIG_FEATDMF_TA:
5704 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5705 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5706 if (dahdi_wink(p, index)) goto quit;
5707 dtmfbuf[0] = 0;
5708 /* Wait for the first digit (up to 5 seconds). */
5709 res = ast_waitfordigit(chan, 5000);
5710 if (res <= 0) break;
5711 dtmfbuf[0] = res;
5712 /* fall through intentionally */
5713 case SIG_FEATDMF:
5714 case SIG_E911:
5715 case SIG_FGC_CAMAMF:
5716 case SIG_SF_FEATDMF:
5717 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5718 /* if international caca, do it again to get real ANO */
5719 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
5721 if (dahdi_wink(p, index)) goto quit;
5722 dtmfbuf[0] = 0;
5723 /* Wait for the first digit (up to 5 seconds). */
5724 res = ast_waitfordigit(chan, 5000);
5725 if (res <= 0) break;
5726 dtmfbuf[0] = res;
5727 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5729 if (res > 0) {
5730 /* if E911, take off hook */
5731 if (p->sig == SIG_E911)
5732 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
5733 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
5735 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5736 break;
5737 case SIG_FEATB:
5738 case SIG_SF_FEATB:
5739 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5740 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5741 break;
5742 case SIG_EMWINK:
5743 /* if we received a '*', we are actually receiving Feature Group D
5744 dial syntax, so use that mode; otherwise, fall through to normal
5745 mode
5747 if (res == '*') {
5748 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
5749 if (res > 0)
5750 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
5751 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5752 break;
5754 default:
5755 /* If we got the first digit, get the rest */
5756 len = 1;
5757 dtmfbuf[len] = '\0';
5758 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
5759 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
5760 timeout = matchdigittimeout;
5761 } else {
5762 timeout = gendigittimeout;
5764 res = ast_waitfordigit(chan, timeout);
5765 if (res < 0) {
5766 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5767 ast_hangup(chan);
5768 goto quit;
5769 } else if (res) {
5770 dtmfbuf[len++] = res;
5771 dtmfbuf[len] = '\0';
5772 } else {
5773 break;
5776 break;
5779 if (res == -1) {
5780 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
5781 ast_hangup(chan);
5782 goto quit;
5783 } else if (res < 0) {
5784 ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
5785 ast_hangup(chan);
5786 goto quit;
5789 if (p->sig == SIG_FGC_CAMA) {
5790 char anibuf[100];
5792 if (ast_safe_sleep(chan,1000) == -1) {
5793 ast_hangup(chan);
5794 goto quit;
5796 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
5797 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
5798 res = my_getsigstr(chan, anibuf, "#", 10000);
5799 if ((res > 0) && (strlen(anibuf) > 2)) {
5800 if (anibuf[strlen(anibuf) - 1] == '#')
5801 anibuf[strlen(anibuf) - 1] = 0;
5802 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
5804 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5807 ast_copy_string(exten, dtmfbuf, sizeof(exten));
5808 if (ast_strlen_zero(exten))
5809 ast_copy_string(exten, "s", sizeof(exten));
5810 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
5811 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
5812 if (exten[0] == '*') {
5813 char *stringp=NULL;
5814 ast_copy_string(exten2, exten, sizeof(exten2));
5815 /* Parse out extension and callerid */
5816 stringp=exten2 +1;
5817 s1 = strsep(&stringp, "*");
5818 s2 = strsep(&stringp, "*");
5819 if (s2) {
5820 if (!ast_strlen_zero(p->cid_num))
5821 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5822 else
5823 ast_set_callerid(chan, s1, NULL, s1);
5824 ast_copy_string(exten, s2, sizeof(exten));
5825 } else
5826 ast_copy_string(exten, s1, sizeof(exten));
5827 } else if (p->sig == SIG_FEATD)
5828 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
5830 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
5831 if (exten[0] == '*') {
5832 char *stringp=NULL;
5833 ast_copy_string(exten2, exten, sizeof(exten2));
5834 /* Parse out extension and callerid */
5835 stringp=exten2 +1;
5836 s1 = strsep(&stringp, "#");
5837 s2 = strsep(&stringp, "#");
5838 if (s2) {
5839 if (!ast_strlen_zero(p->cid_num))
5840 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5841 else
5842 if (*(s1 + 2))
5843 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
5844 ast_copy_string(exten, s2 + 1, sizeof(exten));
5845 } else
5846 ast_copy_string(exten, s1 + 2, sizeof(exten));
5847 } else
5848 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
5850 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
5851 if (exten[0] == '*') {
5852 char *stringp=NULL;
5853 ast_copy_string(exten2, exten, sizeof(exten2));
5854 /* Parse out extension and callerid */
5855 stringp=exten2 +1;
5856 s1 = strsep(&stringp, "#");
5857 s2 = strsep(&stringp, "#");
5858 if (s2 && (*(s2 + 1) == '0')) {
5859 if (*(s2 + 2))
5860 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
5862 if (s1) ast_copy_string(exten, s1, sizeof(exten));
5863 else ast_copy_string(exten, "911", sizeof(exten));
5864 } else
5865 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
5867 if (p->sig == SIG_FEATB) {
5868 if (exten[0] == '*') {
5869 char *stringp=NULL;
5870 ast_copy_string(exten2, exten, sizeof(exten2));
5871 /* Parse out extension and callerid */
5872 stringp=exten2 +1;
5873 s1 = strsep(&stringp, "#");
5874 ast_copy_string(exten, exten2 + 1, sizeof(exten));
5875 } else
5876 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
5878 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
5879 dahdi_wink(p, index);
5880 /* some switches require a minimum guard time between
5881 the last FGD wink and something that answers
5882 immediately. This ensures it */
5883 if (ast_safe_sleep(chan,100)) goto quit;
5885 dahdi_enable_ec(p);
5886 if (NEED_MFDETECT(p)) {
5887 if (p->dsp) {
5888 if (!p->hardwaredtmf)
5889 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5890 else {
5891 ast_dsp_free(p->dsp);
5892 p->dsp = NULL;
5897 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
5898 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5899 if (p->dsp) ast_dsp_digitreset(p->dsp);
5900 res = ast_pbx_run(chan);
5901 if (res) {
5902 ast_log(LOG_WARNING, "PBX exited non-zero\n");
5903 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5905 goto quit;
5906 } else {
5907 if (option_verbose > 2)
5908 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
5909 sleep(2);
5910 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
5911 if (res < 0)
5912 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
5913 else
5914 sleep(1);
5915 res = ast_streamfile(chan, "ss-noservice", chan->language);
5916 if (res >= 0)
5917 ast_waitstream(chan, "");
5918 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5919 ast_hangup(chan);
5920 goto quit;
5922 break;
5923 case SIG_FXOLS:
5924 case SIG_FXOGS:
5925 case SIG_FXOKS:
5926 /* Read the first digit */
5927 timeout = firstdigittimeout;
5928 /* If starting a threeway call, never timeout on the first digit so someone
5929 can use flash-hook as a "hold" feature */
5930 if (p->subs[SUB_THREEWAY].owner)
5931 timeout = 999999;
5932 while (len < AST_MAX_EXTENSION-1) {
5933 /* Read digit unless it's supposed to be immediate, in which case the
5934 only answer is 's' */
5935 if (p->immediate)
5936 res = 's';
5937 else
5938 res = ast_waitfordigit(chan, timeout);
5939 timeout = 0;
5940 if (res < 0) {
5941 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5942 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5943 ast_hangup(chan);
5944 goto quit;
5945 } else if (res) {
5946 exten[len++]=res;
5947 exten[len] = '\0';
5949 if (!ast_ignore_pattern(chan->context, exten))
5950 tone_zone_play_tone(p->subs[index].dfd, -1);
5951 else
5952 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5953 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
5954 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
5955 if (getforward) {
5956 /* Record this as the forwarding extension */
5957 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
5958 if (option_verbose > 2)
5959 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
5960 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5961 if (res)
5962 break;
5963 usleep(500000);
5964 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5965 sleep(1);
5966 memset(exten, 0, sizeof(exten));
5967 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5968 len = 0;
5969 getforward = 0;
5970 } else {
5971 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5972 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5973 if (!ast_strlen_zero(p->cid_num)) {
5974 if (!p->hidecallerid)
5975 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5976 else
5977 ast_set_callerid(chan, NULL, NULL, p->cid_num);
5979 if (!ast_strlen_zero(p->cid_name)) {
5980 if (!p->hidecallerid)
5981 ast_set_callerid(chan, NULL, p->cid_name, NULL);
5983 ast_setstate(chan, AST_STATE_RING);
5984 dahdi_enable_ec(p);
5985 res = ast_pbx_run(chan);
5986 if (res) {
5987 ast_log(LOG_WARNING, "PBX exited non-zero\n");
5988 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5990 goto quit;
5992 } else {
5993 /* It's a match, but they just typed a digit, and there is an ambiguous match,
5994 so just set the timeout to matchdigittimeout and wait some more */
5995 timeout = matchdigittimeout;
5997 } else if (res == 0) {
5998 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
5999 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6000 dahdi_wait_event(p->subs[index].dfd);
6001 ast_hangup(chan);
6002 goto quit;
6003 } else if (p->callwaiting && !strcmp(exten, "*70")) {
6004 if (option_verbose > 2)
6005 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
6006 /* Disable call waiting if enabled */
6007 p->callwaiting = 0;
6008 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6009 if (res) {
6010 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6011 chan->name, strerror(errno));
6013 len = 0;
6014 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
6015 memset(exten, 0, sizeof(exten));
6016 timeout = firstdigittimeout;
6018 } else if (!strcmp(exten,ast_pickup_ext())) {
6019 /* Scan all channels and see if there are any
6020 * ringing channels that have call groups
6021 * that equal this channels pickup group
6023 if (index == SUB_REAL) {
6024 /* Switch us from Third call to Call Wait */
6025 if (p->subs[SUB_THREEWAY].owner) {
6026 /* If you make a threeway call and the *8# a call, it should actually
6027 look like a callwait */
6028 alloc_sub(p, SUB_CALLWAIT);
6029 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
6030 unalloc_sub(p, SUB_THREEWAY);
6032 dahdi_enable_ec(p);
6033 if (ast_pickup_call(chan)) {
6034 ast_log(LOG_DEBUG, "No call pickup possible...\n");
6035 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6036 dahdi_wait_event(p->subs[index].dfd);
6038 ast_hangup(chan);
6039 goto quit;
6040 } else {
6041 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
6042 ast_hangup(chan);
6043 goto quit;
6046 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
6047 if (option_verbose > 2)
6048 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
6049 /* Disable Caller*ID if enabled */
6050 p->hidecallerid = 1;
6051 if (chan->cid.cid_num)
6052 free(chan->cid.cid_num);
6053 chan->cid.cid_num = NULL;
6054 if (chan->cid.cid_name)
6055 free(chan->cid.cid_name);
6056 chan->cid.cid_name = NULL;
6057 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6058 if (res) {
6059 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6060 chan->name, strerror(errno));
6062 len = 0;
6063 memset(exten, 0, sizeof(exten));
6064 timeout = firstdigittimeout;
6065 } else if (p->callreturn && !strcmp(exten, "*69")) {
6066 res = 0;
6067 if (!ast_strlen_zero(p->lastcid_num)) {
6068 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
6070 if (!res)
6071 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6072 break;
6073 } else if (!strcmp(exten, "*78")) {
6074 /* Do not disturb */
6075 if (option_verbose > 2)
6076 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
6077 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
6078 "Channel: %s/%d\r\n"
6079 "Status: enabled\r\n", dahdi_chan_name, p->channel);
6080 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6081 p->dnd = 1;
6082 getforward = 0;
6083 memset(exten, 0, sizeof(exten));
6084 len = 0;
6085 } else if (!strcmp(exten, "*79")) {
6086 /* Do not disturb */
6087 if (option_verbose > 2)
6088 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
6089 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
6090 "Channel: %s/%d\r\n"
6091 "Status: disabled\r\n", dahdi_chan_name, p->channel);
6092 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6093 p->dnd = 0;
6094 getforward = 0;
6095 memset(exten, 0, sizeof(exten));
6096 len = 0;
6097 } else if (p->cancallforward && !strcmp(exten, "*72")) {
6098 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6099 getforward = 1;
6100 memset(exten, 0, sizeof(exten));
6101 len = 0;
6102 } else if (p->cancallforward && !strcmp(exten, "*73")) {
6103 if (option_verbose > 2)
6104 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
6105 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6106 memset(p->call_forward, 0, sizeof(p->call_forward));
6107 getforward = 0;
6108 memset(exten, 0, sizeof(exten));
6109 len = 0;
6110 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
6111 p->subs[SUB_THREEWAY].owner &&
6112 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
6113 /* This is a three way call, the main call being a real channel,
6114 and we're parking the first call. */
6115 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
6116 if (option_verbose > 2)
6117 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
6118 break;
6119 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
6120 if (option_verbose > 2)
6121 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
6122 res = ast_db_put("blacklist", p->lastcid_num, "1");
6123 if (!res) {
6124 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6125 memset(exten, 0, sizeof(exten));
6126 len = 0;
6128 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
6129 if (option_verbose > 2)
6130 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
6131 /* Enable Caller*ID if enabled */
6132 p->hidecallerid = 0;
6133 if (chan->cid.cid_num)
6134 free(chan->cid.cid_num);
6135 chan->cid.cid_num = NULL;
6136 if (chan->cid.cid_name)
6137 free(chan->cid.cid_name);
6138 chan->cid.cid_name = NULL;
6139 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
6140 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6141 if (res) {
6142 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6143 chan->name, strerror(errno));
6145 len = 0;
6146 memset(exten, 0, sizeof(exten));
6147 timeout = firstdigittimeout;
6148 } else if (!strcmp(exten, "*0")) {
6149 struct ast_channel *nbridge =
6150 p->subs[SUB_THREEWAY].owner;
6151 struct dahdi_pvt *pbridge = NULL;
6152 /* set up the private struct of the bridged one, if any */
6153 if (nbridge && ast_bridged_channel(nbridge))
6154 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
6155 if (nbridge && pbridge &&
6156 (nbridge->tech == chan_tech) &&
6157 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
6158 ISTRUNK(pbridge)) {
6159 int func = DAHDI_FLASH;
6160 /* Clear out the dial buffer */
6161 p->dop.dialstr[0] = '\0';
6162 /* flash hookswitch */
6163 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
6164 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
6165 nbridge->name, strerror(errno));
6167 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6168 unalloc_sub(p, SUB_THREEWAY);
6169 p->owner = p->subs[SUB_REAL].owner;
6170 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
6171 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
6172 ast_hangup(chan);
6173 goto quit;
6174 } else {
6175 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6176 dahdi_wait_event(p->subs[index].dfd);
6177 tone_zone_play_tone(p->subs[index].dfd, -1);
6178 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6179 unalloc_sub(p, SUB_THREEWAY);
6180 p->owner = p->subs[SUB_REAL].owner;
6181 ast_hangup(chan);
6182 goto quit;
6184 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
6185 ((exten[0] != '*') || (strlen(exten) > 2))) {
6186 if (option_debug)
6187 ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
6188 break;
6190 if (!timeout)
6191 timeout = gendigittimeout;
6192 if (len && !ast_ignore_pattern(chan->context, exten))
6193 tone_zone_play_tone(p->subs[index].dfd, -1);
6195 break;
6196 case SIG_FXSLS:
6197 case SIG_FXSGS:
6198 case SIG_FXSKS:
6199 #ifdef HAVE_PRI
6200 if (p->pri) {
6201 /* This is a GR-303 trunk actually. Wait for the first ring... */
6202 struct ast_frame *f;
6203 int res;
6204 time_t start;
6206 time(&start);
6207 ast_setstate(chan, AST_STATE_RING);
6208 while (time(NULL) < start + 3) {
6209 res = ast_waitfor(chan, 1000);
6210 if (res) {
6211 f = ast_read(chan);
6212 if (!f) {
6213 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
6214 ast_hangup(chan);
6215 goto quit;
6216 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
6217 res = 1;
6218 } else
6219 res = 0;
6220 ast_frfree(f);
6221 if (res) {
6222 ast_log(LOG_DEBUG, "Got ring!\n");
6223 res = 0;
6224 break;
6229 #endif
6230 /* check for SMDI messages */
6231 if (p->use_smdi && p->smdi_iface) {
6232 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
6234 if (smdi_msg != NULL) {
6235 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
6237 if (smdi_msg->type == 'B')
6238 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
6239 else if (smdi_msg->type == 'N')
6240 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
6242 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
6243 } else {
6244 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
6248 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
6249 number = smdi_msg->calling_st;
6251 /* If we want caller id, we're in a prering state due to a polarity reversal
6252 * and we're set to use a polarity reversal to trigger the start of caller id,
6253 * grab the caller id and wait for ringing to start... */
6254 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
6255 /* If set to use DTMF CID signalling, listen for DTMF */
6256 if (p->cid_signalling == CID_SIG_DTMF) {
6257 int i = 0;
6258 cs = NULL;
6259 ast_log(LOG_DEBUG, "Receiving DTMF cid on "
6260 "channel %s\n", chan->name);
6261 dahdi_setlinear(p->subs[index].dfd, 0);
6262 res = 2000;
6263 for (;;) {
6264 struct ast_frame *f;
6265 res = ast_waitfor(chan, res);
6266 if (res <= 0) {
6267 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
6268 "Exiting simple switch\n");
6269 ast_hangup(chan);
6270 goto quit;
6272 f = ast_read(chan);
6273 if (!f)
6274 break;
6275 if (f->frametype == AST_FRAME_DTMF) {
6276 dtmfbuf[i++] = f->subclass;
6277 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
6278 res = 2000;
6280 ast_frfree(f);
6281 if (chan->_state == AST_STATE_RING ||
6282 chan->_state == AST_STATE_RINGING)
6283 break; /* Got ring */
6285 dtmfbuf[i] = '\0';
6286 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6287 /* Got cid and ring. */
6288 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
6289 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
6290 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
6291 dtmfcid, flags);
6292 /* If first byte is NULL, we have no cid */
6293 if (!ast_strlen_zero(dtmfcid))
6294 number = dtmfcid;
6295 else
6296 number = NULL;
6297 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
6298 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
6299 cs = callerid_new(p->cid_signalling);
6300 if (cs) {
6301 samples = 0;
6302 #if 1
6303 bump_gains(p);
6304 #endif
6305 /* Take out of linear mode for Caller*ID processing */
6306 dahdi_setlinear(p->subs[index].dfd, 0);
6308 /* First we wait and listen for the Caller*ID */
6309 for (;;) {
6310 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6311 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6312 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6313 callerid_free(cs);
6314 ast_hangup(chan);
6315 goto quit;
6317 if (i & DAHDI_IOMUX_SIGEVENT) {
6318 res = dahdi_get_event(p->subs[index].dfd);
6319 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6321 if (p->cid_signalling == CID_SIG_V23_JP) {
6322 #ifdef DAHDI_EVENT_RINGBEGIN
6323 if (res == DAHDI_EVENT_RINGBEGIN) {
6324 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6325 usleep(1);
6327 #endif
6328 } else {
6329 res = 0;
6330 break;
6332 } else if (i & DAHDI_IOMUX_READ) {
6333 res = read(p->subs[index].dfd, buf, sizeof(buf));
6334 if (res < 0) {
6335 if (errno != ELAST) {
6336 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6337 callerid_free(cs);
6338 ast_hangup(chan);
6339 goto quit;
6341 break;
6343 samples += res;
6345 if (p->cid_signalling == CID_SIG_V23_JP) {
6346 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
6347 } else {
6348 res = callerid_feed(cs, buf, res, AST_LAW(p));
6351 if (res < 0) {
6352 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
6353 break;
6354 } else if (res)
6355 break;
6356 else if (samples > (8000 * 10))
6357 break;
6360 if (res == 1) {
6361 callerid_get(cs, &name, &number, &flags);
6362 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
6365 if (p->cid_signalling == CID_SIG_V23_JP) {
6366 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6367 usleep(1);
6368 res = 4000;
6369 } else {
6371 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
6372 res = 2000;
6375 for (;;) {
6376 struct ast_frame *f;
6377 res = ast_waitfor(chan, res);
6378 if (res <= 0) {
6379 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
6380 "Exiting simple switch\n");
6381 ast_hangup(chan);
6382 goto quit;
6384 if (!(f = ast_read(chan))) {
6385 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
6386 ast_hangup(chan);
6387 goto quit;
6389 ast_frfree(f);
6390 if (chan->_state == AST_STATE_RING ||
6391 chan->_state == AST_STATE_RINGING)
6392 break; /* Got ring */
6395 /* We must have a ring by now, so, if configured, lets try to listen for
6396 * distinctive ringing */
6397 if (p->usedistinctiveringdetection == 1) {
6398 len = 0;
6399 distMatches = 0;
6400 /* Clear the current ring data array so we dont have old data in it. */
6401 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
6402 curRingData[receivedRingT] = 0;
6403 receivedRingT = 0;
6404 counter = 0;
6405 counter1 = 0;
6406 /* Check to see if context is what it should be, if not set to be. */
6407 if (strcmp(p->context,p->defcontext) != 0) {
6408 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
6409 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
6412 for (;;) {
6413 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6414 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6415 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6416 callerid_free(cs);
6417 ast_hangup(chan);
6418 goto quit;
6420 if (i & DAHDI_IOMUX_SIGEVENT) {
6421 res = dahdi_get_event(p->subs[index].dfd);
6422 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6423 res = 0;
6424 /* Let us detect distinctive ring */
6426 curRingData[receivedRingT] = p->ringt;
6428 if (p->ringt < p->ringt_base/2)
6429 break;
6430 /* Increment the ringT counter so we can match it against
6431 values in chan_dahdi.conf for distinctive ring */
6432 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6433 break;
6434 } else if (i & DAHDI_IOMUX_READ) {
6435 res = read(p->subs[index].dfd, buf, sizeof(buf));
6436 if (res < 0) {
6437 if (errno != ELAST) {
6438 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6439 callerid_free(cs);
6440 ast_hangup(chan);
6441 goto quit;
6443 break;
6445 if (p->ringt)
6446 p->ringt--;
6447 if (p->ringt == 1) {
6448 res = -1;
6449 break;
6453 if (option_verbose > 2)
6454 /* this only shows up if you have n of the dring patterns filled in */
6455 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
6457 for (counter = 0; counter < 3; counter++) {
6458 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6459 channel */
6460 distMatches = 0;
6461 for (counter1 = 0; counter1 < 3; counter1++) {
6462 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
6463 (p->drings.ringnum[counter].ring[counter1]-10)) {
6464 distMatches++;
6467 if (distMatches == 3) {
6468 /* The ring matches, set the context to whatever is for distinctive ring.. */
6469 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
6470 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
6471 if (option_verbose > 2)
6472 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
6473 break;
6477 /* Restore linear mode (if appropriate) for Caller*ID processing */
6478 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6479 #if 1
6480 restore_gains(p);
6481 #endif
6482 } else
6483 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
6484 } else {
6485 ast_log(LOG_WARNING, "Channel %s in prering "
6486 "state, but I have nothing to do. "
6487 "Terminating simple switch, should be "
6488 "restarted by the actual ring.\n",
6489 chan->name);
6490 ast_hangup(chan);
6491 goto quit;
6493 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
6494 /* FSK Bell202 callerID */
6495 cs = callerid_new(p->cid_signalling);
6496 if (cs) {
6497 #if 1
6498 bump_gains(p);
6499 #endif
6500 samples = 0;
6501 len = 0;
6502 distMatches = 0;
6503 /* Clear the current ring data array so we dont have old data in it. */
6504 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
6505 curRingData[receivedRingT] = 0;
6506 receivedRingT = 0;
6507 counter = 0;
6508 counter1 = 0;
6509 /* Check to see if context is what it should be, if not set to be. */
6510 if (strcmp(p->context,p->defcontext) != 0) {
6511 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
6512 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
6515 /* Take out of linear mode for Caller*ID processing */
6516 dahdi_setlinear(p->subs[index].dfd, 0);
6517 for (;;) {
6518 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6519 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6520 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6521 callerid_free(cs);
6522 ast_hangup(chan);
6523 goto quit;
6525 if (i & DAHDI_IOMUX_SIGEVENT) {
6526 res = dahdi_get_event(p->subs[index].dfd);
6527 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6528 /* If we get a PR event, they hung up while processing calerid */
6529 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
6530 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
6531 p->polarity = POLARITY_IDLE;
6532 callerid_free(cs);
6533 ast_hangup(chan);
6534 goto quit;
6536 res = 0;
6537 /* Let us detect callerid when the telco uses distinctive ring */
6539 curRingData[receivedRingT] = p->ringt;
6541 if (p->ringt < p->ringt_base/2)
6542 break;
6543 /* Increment the ringT counter so we can match it against
6544 values in chan_dahdi.conf for distinctive ring */
6545 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6546 break;
6547 } else if (i & DAHDI_IOMUX_READ) {
6548 res = read(p->subs[index].dfd, buf, sizeof(buf));
6549 if (res < 0) {
6550 if (errno != ELAST) {
6551 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6552 callerid_free(cs);
6553 ast_hangup(chan);
6554 goto quit;
6556 break;
6558 if (p->ringt)
6559 p->ringt--;
6560 if (p->ringt == 1) {
6561 res = -1;
6562 break;
6564 samples += res;
6565 res = callerid_feed(cs, buf, res, AST_LAW(p));
6566 if (res < 0) {
6567 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
6568 break;
6569 } else if (res)
6570 break;
6571 else if (samples > (8000 * 10))
6572 break;
6575 if (res == 1) {
6576 callerid_get(cs, &name, &number, &flags);
6577 if (option_debug)
6578 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
6580 if (distinctiveringaftercid == 1) {
6581 /* Clear the current ring data array so we dont have old data in it. */
6582 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
6583 curRingData[receivedRingT] = 0;
6585 receivedRingT = 0;
6586 if (option_verbose > 2)
6587 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
6588 for (;;) {
6589 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6590 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6591 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6592 callerid_free(cs);
6593 ast_hangup(chan);
6594 goto quit;
6596 if (i & DAHDI_IOMUX_SIGEVENT) {
6597 res = dahdi_get_event(p->subs[index].dfd);
6598 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6599 res = 0;
6600 /* Let us detect callerid when the telco uses distinctive ring */
6602 curRingData[receivedRingT] = p->ringt;
6604 if (p->ringt < p->ringt_base/2)
6605 break;
6606 /* Increment the ringT counter so we can match it against
6607 values in chan_dahdi.conf for distinctive ring */
6608 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6609 break;
6610 } else if (i & DAHDI_IOMUX_READ) {
6611 res = read(p->subs[index].dfd, buf, sizeof(buf));
6612 if (res < 0) {
6613 if (errno != ELAST) {
6614 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6615 callerid_free(cs);
6616 ast_hangup(chan);
6617 goto quit;
6619 break;
6621 if (p->ringt)
6622 p->ringt--;
6623 if (p->ringt == 1) {
6624 res = -1;
6625 break;
6630 if (p->usedistinctiveringdetection == 1) {
6631 if (option_verbose > 2)
6632 /* this only shows up if you have n of the dring patterns filled in */
6633 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
6635 for (counter = 0; counter < 3; counter++) {
6636 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6637 channel */
6638 if (option_verbose > 2)
6639 /* this only shows up if you have n of the dring patterns filled in */
6640 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
6641 p->drings.ringnum[counter].ring[0],
6642 p->drings.ringnum[counter].ring[1],
6643 p->drings.ringnum[counter].ring[2]);
6644 distMatches = 0;
6645 for (counter1 = 0; counter1 < 3; counter1++) {
6646 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
6647 (p->drings.ringnum[counter].ring[counter1]-10)) {
6648 distMatches++;
6651 if (distMatches == 3) {
6652 /* The ring matches, set the context to whatever is for distinctive ring.. */
6653 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
6654 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
6655 if (option_verbose > 2)
6656 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
6657 break;
6661 /* Restore linear mode (if appropriate) for Caller*ID processing */
6662 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6663 #if 1
6664 restore_gains(p);
6665 #endif
6666 if (res < 0) {
6667 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
6669 } else
6670 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
6672 else
6673 cs = NULL;
6675 if (number)
6676 ast_shrink_phone_number(number);
6677 ast_set_callerid(chan, number, name, number);
6679 if (smdi_msg)
6680 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
6682 if (cs)
6683 callerid_free(cs);
6685 ast_setstate(chan, AST_STATE_RING);
6686 chan->rings = 1;
6687 p->ringt = p->ringt_base;
6688 res = ast_pbx_run(chan);
6689 if (res) {
6690 ast_hangup(chan);
6691 ast_log(LOG_WARNING, "PBX exited non-zero\n");
6693 goto quit;
6694 default:
6695 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
6696 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6697 if (res < 0)
6698 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
6700 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6701 if (res < 0)
6702 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
6703 ast_hangup(chan);
6704 quit:
6705 ast_mutex_lock(&ss_thread_lock);
6706 ss_thread_count--;
6707 ast_cond_signal(&ss_thread_complete);
6708 ast_mutex_unlock(&ss_thread_lock);
6709 return NULL;
6712 /* destroy a DAHDI channel, identified by its number */
6713 static int dahdi_destroy_channel_bynum(int channel)
6715 struct dahdi_pvt *tmp = NULL;
6716 struct dahdi_pvt *prev = NULL;
6718 tmp = iflist;
6719 while (tmp) {
6720 if (tmp->channel == channel) {
6721 int x = DAHDI_FLASH;
6722 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
6723 destroy_channel(prev, tmp, 1);
6724 ast_module_unref(ast_module_info->self);
6725 return RESULT_SUCCESS;
6727 prev = tmp;
6728 tmp = tmp->next;
6730 return RESULT_FAILURE;
6733 static int handle_init_event(struct dahdi_pvt *i, int event)
6735 int res;
6736 pthread_t threadid;
6737 pthread_attr_t attr;
6738 struct ast_channel *chan;
6739 pthread_attr_init(&attr);
6740 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
6741 /* Handle an event on a given channel for the monitor thread. */
6742 switch (event) {
6743 case DAHDI_EVENT_NONE:
6744 case DAHDI_EVENT_BITSCHANGED:
6745 break;
6746 case DAHDI_EVENT_WINKFLASH:
6747 case DAHDI_EVENT_RINGOFFHOOK:
6748 if (i->inalarm) break;
6749 if (i->radio) break;
6750 /* Got a ring/answer. What kind of channel are we? */
6751 switch (i->sig) {
6752 case SIG_FXOLS:
6753 case SIG_FXOGS:
6754 case SIG_FXOKS:
6755 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6756 if (res && (errno == EBUSY))
6757 break;
6758 if (i->cidspill) {
6759 /* Cancel VMWI spill */
6760 free(i->cidspill);
6761 i->cidspill = NULL;
6763 if (i->immediate) {
6764 dahdi_enable_ec(i);
6765 /* The channel is immediately up. Start right away */
6766 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
6767 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
6768 if (!chan) {
6769 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
6770 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6771 if (res < 0)
6772 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6774 } else {
6775 /* Check for callerid, digits, etc */
6776 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
6777 if (chan) {
6778 if (has_voicemail(i))
6779 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
6780 else
6781 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
6782 if (res < 0)
6783 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
6784 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6785 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6786 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6787 if (res < 0)
6788 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6789 ast_hangup(chan);
6791 } else
6792 ast_log(LOG_WARNING, "Unable to create channel\n");
6794 break;
6795 case SIG_FXSLS:
6796 case SIG_FXSGS:
6797 case SIG_FXSKS:
6798 i->ringt = i->ringt_base;
6799 /* Fall through */
6800 case SIG_EMWINK:
6801 case SIG_FEATD:
6802 case SIG_FEATDMF:
6803 case SIG_FEATDMF_TA:
6804 case SIG_E911:
6805 case SIG_FGC_CAMA:
6806 case SIG_FGC_CAMAMF:
6807 case SIG_FEATB:
6808 case SIG_EM:
6809 case SIG_EM_E1:
6810 case SIG_SFWINK:
6811 case SIG_SF_FEATD:
6812 case SIG_SF_FEATDMF:
6813 case SIG_SF_FEATB:
6814 case SIG_SF:
6815 /* Check for callerid, digits, etc */
6816 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
6817 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6818 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6819 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6820 if (res < 0)
6821 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6822 ast_hangup(chan);
6823 } else if (!chan) {
6824 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
6826 break;
6827 default:
6828 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
6829 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6830 if (res < 0)
6831 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6832 return -1;
6834 break;
6835 case DAHDI_EVENT_NOALARM:
6836 i->inalarm = 0;
6837 if (!i->unknown_alarm) {
6838 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
6839 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
6840 "Channel: %d\r\n", i->channel);
6841 } else {
6842 i->unknown_alarm = 0;
6844 break;
6845 case DAHDI_EVENT_ALARM:
6846 i->inalarm = 1;
6847 res = get_alarms(i);
6848 handle_alarms(i, res);
6849 /* fall thru intentionally */
6850 case DAHDI_EVENT_ONHOOK:
6851 if (i->radio)
6852 break;
6853 /* Back on hook. Hang up. */
6854 switch (i->sig) {
6855 case SIG_FXOLS:
6856 case SIG_FXOGS:
6857 case SIG_FEATD:
6858 case SIG_FEATDMF:
6859 case SIG_FEATDMF_TA:
6860 case SIG_E911:
6861 case SIG_FGC_CAMA:
6862 case SIG_FGC_CAMAMF:
6863 case SIG_FEATB:
6864 case SIG_EM:
6865 case SIG_EM_E1:
6866 case SIG_EMWINK:
6867 case SIG_SF_FEATD:
6868 case SIG_SF_FEATDMF:
6869 case SIG_SF_FEATB:
6870 case SIG_SF:
6871 case SIG_SFWINK:
6872 case SIG_FXSLS:
6873 case SIG_FXSGS:
6874 case SIG_FXSKS:
6875 case SIG_GR303FXSKS:
6876 dahdi_disable_ec(i);
6877 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6878 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6879 break;
6880 case SIG_GR303FXOKS:
6881 case SIG_FXOKS:
6882 dahdi_disable_ec(i);
6883 /* Diddle the battery for the zhone */
6884 #ifdef ZHONE_HACK
6885 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6886 usleep(1);
6887 #endif
6888 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6889 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6890 break;
6891 case SIG_PRI:
6892 dahdi_disable_ec(i);
6893 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6894 break;
6895 default:
6896 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
6897 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6898 return -1;
6900 break;
6901 case DAHDI_EVENT_POLARITY:
6902 switch (i->sig) {
6903 case SIG_FXSLS:
6904 case SIG_FXSKS:
6905 case SIG_FXSGS:
6906 /* We have already got a PR before the channel was
6907 created, but it wasn't handled. We need polarity
6908 to be REV for remote hangup detection to work.
6909 At least in Spain */
6910 if (i->hanguponpolarityswitch)
6911 i->polarity = POLARITY_REV;
6913 if (i->cid_start == CID_START_POLARITY) {
6914 i->polarity = POLARITY_REV;
6915 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
6916 "CID detection on channel %d\n",
6917 i->channel);
6918 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
6919 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6920 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6923 break;
6924 default:
6925 ast_log(LOG_WARNING, "handle_init_event detected "
6926 "polarity reversal on non-FXO (SIG_FXS) "
6927 "interface %d\n", i->channel);
6929 break;
6930 case DAHDI_EVENT_REMOVED: /* destroy channel */
6931 ast_log(LOG_NOTICE,
6932 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
6933 i->channel);
6934 dahdi_destroy_channel_bynum(i->channel);
6935 break;
6937 pthread_attr_destroy(&attr);
6938 return 0;
6941 static void *do_monitor(void *data)
6943 int count, res, res2, spoint, pollres=0;
6944 struct dahdi_pvt *i;
6945 struct dahdi_pvt *last = NULL;
6946 time_t thispass = 0, lastpass = 0;
6947 int found;
6948 char buf[1024];
6949 struct pollfd *pfds=NULL;
6950 int lastalloc = -1;
6951 /* This thread monitors all the frame relay interfaces which are not yet in use
6952 (and thus do not have a separate thread) indefinitely */
6953 /* From here on out, we die whenever asked */
6954 #if 0
6955 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
6956 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
6957 return NULL;
6959 ast_log(LOG_DEBUG, "Monitor starting...\n");
6960 #endif
6961 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
6963 for (;;) {
6964 /* Lock the interface list */
6965 ast_mutex_lock(&iflock);
6966 if (!pfds || (lastalloc != ifcount)) {
6967 if (pfds) {
6968 free(pfds);
6969 pfds = NULL;
6971 if (ifcount) {
6972 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
6973 ast_mutex_unlock(&iflock);
6974 return NULL;
6977 lastalloc = ifcount;
6979 /* Build the stuff we're going to poll on, that is the socket of every
6980 dahdi_pvt that does not have an associated owner channel */
6981 count = 0;
6982 i = iflist;
6983 while (i) {
6984 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
6985 if (!i->owner && !i->subs[SUB_REAL].owner) {
6986 /* This needs to be watched, as it lacks an owner */
6987 pfds[count].fd = i->subs[SUB_REAL].dfd;
6988 pfds[count].events = POLLPRI;
6989 pfds[count].revents = 0;
6990 /* Message waiting or r2 channels also get watched for reading */
6991 if (i->cidspill)
6992 pfds[count].events |= POLLIN;
6993 count++;
6996 i = i->next;
6998 /* Okay, now that we know what to do, release the interface lock */
6999 ast_mutex_unlock(&iflock);
7001 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
7002 pthread_testcancel();
7003 /* Wait at least a second for something to happen */
7004 res = poll(pfds, count, 1000);
7005 pthread_testcancel();
7006 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
7008 /* Okay, poll has finished. Let's see what happened. */
7009 if (res < 0) {
7010 if ((errno != EAGAIN) && (errno != EINTR))
7011 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
7012 continue;
7014 /* Alright, lock the interface list again, and let's look and see what has
7015 happened */
7016 ast_mutex_lock(&iflock);
7017 found = 0;
7018 spoint = 0;
7019 lastpass = thispass;
7020 thispass = time(NULL);
7021 i = iflist;
7022 while (i) {
7023 if (thispass != lastpass) {
7024 if (!found && ((i == last) || ((i == iflist) && !last))) {
7025 last = i;
7026 if (last) {
7027 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
7028 (last->sig & __DAHDI_SIG_FXO)) {
7029 res = ast_app_has_voicemail(last->mailbox, NULL);
7030 if (last->msgstate != res) {
7031 int x;
7032 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
7033 x = DAHDI_FLUSH_BOTH;
7034 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
7035 if (res2)
7036 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
7037 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
7038 /* Turn on on hook transfer for 4 seconds */
7039 x = 4000;
7040 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
7041 last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
7042 last->cidpos = 0;
7043 last->msgstate = res;
7044 last->onhooktime = thispass;
7046 found ++;
7049 last = last->next;
7053 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
7054 if (i->radio && !i->owner)
7056 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
7057 if (res)
7059 if (option_debug)
7060 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
7061 /* Don't hold iflock while handling init events */
7062 ast_mutex_unlock(&iflock);
7063 handle_init_event(i, res);
7064 ast_mutex_lock(&iflock);
7066 i = i->next;
7067 continue;
7069 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
7070 if (pollres & POLLIN) {
7071 if (i->owner || i->subs[SUB_REAL].owner) {
7072 #ifdef HAVE_PRI
7073 if (!i->pri)
7074 #endif
7075 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
7076 i = i->next;
7077 continue;
7079 if (!i->cidspill) {
7080 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
7081 i = i->next;
7082 continue;
7084 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
7085 if (res > 0) {
7086 /* We read some number of bytes. Write an equal amount of data */
7087 if (res > i->cidlen - i->cidpos)
7088 res = i->cidlen - i->cidpos;
7089 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
7090 if (res2 > 0) {
7091 i->cidpos += res2;
7092 if (i->cidpos >= i->cidlen) {
7093 free(i->cidspill);
7094 i->cidspill = 0;
7095 i->cidpos = 0;
7096 i->cidlen = 0;
7098 } else {
7099 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
7100 i->msgstate = -1;
7102 } else {
7103 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
7106 if (pollres & POLLPRI) {
7107 if (i->owner || i->subs[SUB_REAL].owner) {
7108 #ifdef HAVE_PRI
7109 if (!i->pri)
7110 #endif
7111 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
7112 i = i->next;
7113 continue;
7115 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
7116 if (option_debug)
7117 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
7118 /* Don't hold iflock while handling init events */
7119 ast_mutex_unlock(&iflock);
7120 handle_init_event(i, res);
7121 ast_mutex_lock(&iflock);
7124 i=i->next;
7126 ast_mutex_unlock(&iflock);
7128 /* Never reached */
7129 return NULL;
7133 static int restart_monitor(void)
7135 pthread_attr_t attr;
7136 pthread_attr_init(&attr);
7137 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
7138 /* If we're supposed to be stopped -- stay stopped */
7139 if (monitor_thread == AST_PTHREADT_STOP)
7140 return 0;
7141 ast_mutex_lock(&monlock);
7142 if (monitor_thread == pthread_self()) {
7143 ast_mutex_unlock(&monlock);
7144 ast_log(LOG_WARNING, "Cannot kill myself\n");
7145 return -1;
7147 if (monitor_thread != AST_PTHREADT_NULL) {
7148 /* Wake up the thread */
7149 pthread_kill(monitor_thread, SIGURG);
7150 } else {
7151 /* Start a new monitor */
7152 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
7153 ast_mutex_unlock(&monlock);
7154 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
7155 pthread_attr_destroy(&attr);
7156 return -1;
7159 ast_mutex_unlock(&monlock);
7160 pthread_attr_destroy(&attr);
7161 return 0;
7164 #ifdef HAVE_PRI
7165 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
7167 int x;
7168 int trunkgroup;
7169 /* Get appropriate trunk group if there is one */
7170 trunkgroup = pris[*span].mastertrunkgroup;
7171 if (trunkgroup) {
7172 /* Select a specific trunk group */
7173 for (x = 0; x < NUM_SPANS; x++) {
7174 if (pris[x].trunkgroup == trunkgroup) {
7175 *span = x;
7176 return 0;
7179 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
7180 *span = -1;
7181 } else {
7182 if (pris[*span].trunkgroup) {
7183 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
7184 *span = -1;
7185 } else if (pris[*span].mastertrunkgroup) {
7186 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
7187 *span = -1;
7188 } else {
7189 if (si->totalchans == 31) {
7190 /* E1 */
7191 pris[*span].dchannels[0] = 16 + offset;
7192 } else if (si->totalchans == 24) {
7193 /* T1 or J1 */
7194 pris[*span].dchannels[0] = 24 + offset;
7195 } else if (si->totalchans == 3) {
7196 /* BRI */
7197 pris[*span].dchannels[0] = 3 + offset;
7198 } else {
7199 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);
7200 *span = -1;
7201 return 0;
7203 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
7204 pris[*span].offset = offset;
7205 pris[*span].span = *span + 1;
7208 return 0;
7211 static int pri_create_trunkgroup(int trunkgroup, int *channels)
7213 struct dahdi_spaninfo si;
7214 struct dahdi_params p;
7215 int fd;
7216 int span;
7217 int ospan=0;
7218 int x,y;
7219 for (x = 0; x < NUM_SPANS; x++) {
7220 if (pris[x].trunkgroup == trunkgroup) {
7221 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
7222 return -1;
7225 for (y = 0; y < NUM_DCHANS; y++) {
7226 if (!channels[y])
7227 break;
7228 memset(&si, 0, sizeof(si));
7229 memset(&p, 0, sizeof(p));
7230 #ifdef HAVE_ZAPTEL
7231 fd = open("/dev/zap/channel", O_RDWR);
7232 #else
7233 fd = open("/dev/dahdi/channel", O_RDWR);
7234 #endif
7235 if (fd < 0) {
7236 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
7237 return -1;
7239 x = channels[y];
7240 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
7241 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
7242 close(fd);
7243 return -1;
7245 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
7246 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
7247 return -1;
7249 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
7250 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
7251 close(fd);
7252 return -1;
7254 span = p.spanno - 1;
7255 if (pris[span].trunkgroup) {
7256 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
7257 close(fd);
7258 return -1;
7260 if (pris[span].pvts[0]) {
7261 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
7262 close(fd);
7263 return -1;
7265 if (!y) {
7266 pris[span].trunkgroup = trunkgroup;
7267 pris[span].offset = channels[y] - p.chanpos;
7268 ospan = span;
7270 pris[ospan].dchannels[y] = channels[y];
7271 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
7272 pris[span].span = span + 1;
7273 close(fd);
7275 return 0;
7278 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
7280 if (pris[span].mastertrunkgroup) {
7281 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);
7282 return -1;
7284 pris[span].mastertrunkgroup = trunkgroup;
7285 pris[span].prilogicalspan = logicalspan;
7286 return 0;
7289 #endif
7291 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
7293 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
7294 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
7295 char fn[80];
7296 #if 1
7297 struct dahdi_bufferinfo bi;
7298 #endif
7299 int res;
7300 int span=0;
7301 int here = 0;
7302 int x;
7303 struct dahdi_pvt **wlist;
7304 struct dahdi_pvt **wend;
7305 struct dahdi_params p;
7307 wlist = &iflist;
7308 wend = &ifend;
7310 #ifdef HAVE_PRI
7311 if (pri) {
7312 wlist = &pri->crvs;
7313 wend = &pri->crvend;
7315 #endif
7317 tmp2 = *wlist;
7318 prev = NULL;
7320 while (tmp2) {
7321 if (!tmp2->destroy) {
7322 if (tmp2->channel == channel) {
7323 tmp = tmp2;
7324 here = 1;
7325 break;
7327 if (tmp2->channel > channel) {
7328 break;
7331 prev = tmp2;
7332 tmp2 = tmp2->next;
7335 if (!here && reloading != 1) {
7336 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
7337 if (tmp)
7338 free(tmp);
7339 return NULL;
7341 ast_mutex_init(&tmp->lock);
7342 ifcount++;
7343 for (x = 0; x < 3; x++)
7344 tmp->subs[x].dfd = -1;
7345 tmp->channel = channel;
7348 if (tmp) {
7349 int chan_sig = conf->chan.sig;
7350 if (!here) {
7351 if ((channel != CHAN_PSEUDO) && !pri) {
7352 int count = 0;
7353 snprintf(fn, sizeof(fn), "%d", channel);
7354 /* Open non-blocking */
7355 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
7356 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 */
7357 usleep(1);
7358 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
7359 count++;
7361 /* Allocate a DAHDI structure */
7362 if (tmp->subs[SUB_REAL].dfd < 0) {
7363 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);
7364 destroy_dahdi_pvt(&tmp);
7365 return NULL;
7367 memset(&p, 0, sizeof(p));
7368 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
7369 if (res < 0) {
7370 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
7371 destroy_dahdi_pvt(&tmp);
7372 return NULL;
7374 if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
7375 ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(conf->chan.sig), sig2str(p.sigtype));
7376 destroy_dahdi_pvt(&tmp);
7377 return NULL;
7379 tmp->law = p.curlaw;
7380 tmp->span = p.spanno;
7381 span = p.spanno - 1;
7382 } else {
7383 if (channel == CHAN_PSEUDO)
7384 chan_sig = 0;
7385 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
7386 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
7387 return NULL;
7390 #ifdef HAVE_PRI
7391 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
7392 int offset;
7393 int myswitchtype;
7394 int matchesdchan;
7395 int x,y;
7396 offset = 0;
7397 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
7398 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
7399 destroy_dahdi_pvt(&tmp);
7400 return NULL;
7402 if (span >= NUM_SPANS) {
7403 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
7404 destroy_dahdi_pvt(&tmp);
7405 return NULL;
7406 } else {
7407 struct dahdi_spaninfo si;
7408 si.spanno = 0;
7409 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
7410 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
7411 destroy_dahdi_pvt(&tmp);
7412 return NULL;
7414 /* Store the logical span first based upon the real span */
7415 tmp->logicalspan = pris[span].prilogicalspan;
7416 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
7417 if (span < 0) {
7418 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
7419 destroy_dahdi_pvt(&tmp);
7420 return NULL;
7422 if (chan_sig == SIG_PRI)
7423 myswitchtype = conf->pri.switchtype;
7424 else
7425 myswitchtype = PRI_SWITCH_GR303_TMC;
7426 /* Make sure this isn't a d-channel */
7427 matchesdchan=0;
7428 for (x = 0; x < NUM_SPANS; x++) {
7429 for (y = 0; y < NUM_DCHANS; y++) {
7430 if (pris[x].dchannels[y] == tmp->channel) {
7431 matchesdchan = 1;
7432 break;
7436 offset = p.chanpos;
7437 if (!matchesdchan) {
7438 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
7439 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
7440 destroy_dahdi_pvt(&tmp);
7441 return NULL;
7443 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
7444 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
7445 destroy_dahdi_pvt(&tmp);
7446 return NULL;
7448 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
7449 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
7450 destroy_dahdi_pvt(&tmp);
7451 return NULL;
7453 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
7454 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
7455 destroy_dahdi_pvt(&tmp);
7456 return NULL;
7458 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
7459 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
7460 destroy_dahdi_pvt(&tmp);
7461 return NULL;
7463 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
7464 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
7465 destroy_dahdi_pvt(&tmp);
7466 return NULL;
7468 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
7469 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
7470 destroy_dahdi_pvt(&tmp);
7471 return NULL;
7473 if (pris[span].numchans >= MAX_CHANNELS) {
7474 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
7475 pris[span].trunkgroup);
7476 destroy_dahdi_pvt(&tmp);
7477 return NULL;
7479 pris[span].nodetype = conf->pri.nodetype;
7480 pris[span].switchtype = myswitchtype;
7481 pris[span].nsf = conf->pri.nsf;
7482 pris[span].dialplan = conf->pri.dialplan;
7483 pris[span].localdialplan = conf->pri.localdialplan;
7484 pris[span].pvts[pris[span].numchans++] = tmp;
7485 pris[span].minunused = conf->pri.minunused;
7486 pris[span].minidle = conf->pri.minidle;
7487 pris[span].overlapdial = conf->pri.overlapdial;
7488 #ifdef HAVE_PRI_INBANDDISCONNECT
7489 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
7490 #endif
7491 pris[span].facilityenable = conf->pri.facilityenable;
7492 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
7493 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
7494 ast_copy_string(pris[span].nocid, conf->pri.nocid, sizeof(pris[span].nocid));
7495 ast_copy_string(pris[span].withheldcid, conf->pri.withheldcid, sizeof(pris[span].withheldcid));
7496 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
7497 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
7498 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
7499 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
7500 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
7501 pris[span].resetinterval = conf->pri.resetinterval;
7503 tmp->pri = &pris[span];
7504 tmp->prioffset = offset;
7505 tmp->call = NULL;
7506 } else {
7507 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
7508 destroy_dahdi_pvt(&tmp);
7509 return NULL;
7512 } else {
7513 tmp->prioffset = 0;
7515 #endif
7516 } else {
7517 chan_sig = tmp->sig;
7518 memset(&p, 0, sizeof(p));
7519 if (tmp->subs[SUB_REAL].dfd > -1)
7520 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
7522 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
7523 switch (chan_sig) {
7524 case SIG_FXSKS:
7525 case SIG_FXSLS:
7526 case SIG_EM:
7527 case SIG_EM_E1:
7528 case SIG_EMWINK:
7529 case SIG_FEATD:
7530 case SIG_FEATDMF:
7531 case SIG_FEATDMF_TA:
7532 case SIG_FEATB:
7533 case SIG_E911:
7534 case SIG_SF:
7535 case SIG_SFWINK:
7536 case SIG_FGC_CAMA:
7537 case SIG_FGC_CAMAMF:
7538 case SIG_SF_FEATD:
7539 case SIG_SF_FEATDMF:
7540 case SIG_SF_FEATB:
7541 p.starttime = 250;
7542 break;
7545 if (tmp->radio) {
7546 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
7547 p.channo = channel;
7548 p.rxwinktime = 1;
7549 p.rxflashtime = 1;
7550 p.starttime = 1;
7551 p.debouncetime = 5;
7553 if (!tmp->radio) {
7554 p.channo = channel;
7555 /* Override timing settings based on config file */
7556 if (conf->timing.prewinktime >= 0)
7557 p.prewinktime = conf->timing.prewinktime;
7558 if (conf->timing.preflashtime >= 0)
7559 p.preflashtime = conf->timing.preflashtime;
7560 if (conf->timing.winktime >= 0)
7561 p.winktime = conf->timing.winktime;
7562 if (conf->timing.flashtime >= 0)
7563 p.flashtime = conf->timing.flashtime;
7564 if (conf->timing.starttime >= 0)
7565 p.starttime = conf->timing.starttime;
7566 if (conf->timing.rxwinktime >= 0)
7567 p.rxwinktime = conf->timing.rxwinktime;
7568 if (conf->timing.rxflashtime >= 0)
7569 p.rxflashtime = conf->timing.rxflashtime;
7570 if (conf->timing.debouncetime >= 0)
7571 p.debouncetime = conf->timing.debouncetime;
7574 /* dont set parms on a pseudo-channel (or CRV) */
7575 if (tmp->subs[SUB_REAL].dfd >= 0)
7577 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
7578 if (res < 0) {
7579 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
7580 destroy_dahdi_pvt(&tmp);
7581 return NULL;
7584 #if 1
7585 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
7586 memset(&bi, 0, sizeof(bi));
7587 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
7588 if (!res) {
7589 bi.txbufpolicy = conf->chan.buf_policy;
7590 bi.rxbufpolicy = conf->chan.buf_policy;
7591 bi.numbufs = conf->chan.buf_no;
7592 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
7593 if (res < 0) {
7594 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
7596 } else
7597 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
7599 #endif
7600 tmp->immediate = conf->chan.immediate;
7601 tmp->transfertobusy = conf->chan.transfertobusy;
7602 tmp->sig = chan_sig;
7603 tmp->outsigmod = conf->chan.outsigmod;
7604 tmp->ringt_base = ringt_base;
7605 tmp->firstradio = 0;
7606 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
7607 tmp->permcallwaiting = conf->chan.callwaiting;
7608 else
7609 tmp->permcallwaiting = 0;
7610 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
7611 tmp->destroy = 0;
7612 tmp->drings = drings;
7613 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
7614 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
7615 tmp->threewaycalling = conf->chan.threewaycalling;
7616 tmp->adsi = conf->chan.adsi;
7617 tmp->use_smdi = conf->chan.use_smdi;
7618 tmp->permhidecallerid = conf->chan.hidecallerid;
7619 tmp->callreturn = conf->chan.callreturn;
7620 tmp->echocancel = conf->chan.echocancel;
7621 tmp->echotraining = conf->chan.echotraining;
7622 tmp->pulse = conf->chan.pulse;
7623 if (tmp->echocancel)
7624 tmp->echocanbridged = conf->chan.echocanbridged;
7625 else {
7626 if (conf->chan.echocanbridged)
7627 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
7628 tmp->echocanbridged = 0;
7630 tmp->busydetect = conf->chan.busydetect;
7631 tmp->busycount = conf->chan.busycount;
7632 tmp->busy_tonelength = conf->chan.busy_tonelength;
7633 tmp->busy_quietlength = conf->chan.busy_quietlength;
7634 tmp->callprogress = conf->chan.callprogress;
7635 tmp->cancallforward = conf->chan.cancallforward;
7636 tmp->dtmfrelax = conf->chan.dtmfrelax;
7637 tmp->callwaiting = tmp->permcallwaiting;
7638 tmp->hidecallerid = tmp->permhidecallerid;
7639 tmp->channel = channel;
7640 tmp->stripmsd = conf->chan.stripmsd;
7641 tmp->use_callerid = conf->chan.use_callerid;
7642 tmp->cid_signalling = conf->chan.cid_signalling;
7643 tmp->cid_start = conf->chan.cid_start;
7644 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
7645 tmp->restrictcid = conf->chan.restrictcid;
7646 tmp->use_callingpres = conf->chan.use_callingpres;
7647 tmp->priindication_oob = conf->chan.priindication_oob;
7648 tmp->priexclusive = conf->chan.priexclusive;
7649 if (tmp->usedistinctiveringdetection) {
7650 if (!tmp->use_callerid) {
7651 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
7652 tmp->use_callerid = 1;
7656 if (tmp->cid_signalling == CID_SIG_SMDI) {
7657 if (!tmp->use_smdi) {
7658 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
7659 tmp->use_smdi = 1;
7662 if (tmp->use_smdi) {
7663 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
7664 if (!(tmp->smdi_iface)) {
7665 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
7666 tmp->use_smdi = 0;
7670 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
7671 tmp->amaflags = conf->chan.amaflags;
7672 if (!here) {
7673 tmp->confno = -1;
7674 tmp->propconfno = -1;
7676 tmp->canpark = conf->chan.canpark;
7677 tmp->transfer = conf->chan.transfer;
7678 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
7679 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
7680 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
7681 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
7682 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
7683 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
7684 tmp->cid_ton = 0;
7685 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
7686 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
7687 tmp->msgstate = -1;
7688 tmp->group = conf->chan.group;
7689 tmp->callgroup = conf->chan.callgroup;
7690 tmp->pickupgroup= conf->chan.pickupgroup;
7691 tmp->rxgain = conf->chan.rxgain;
7692 tmp->txgain = conf->chan.txgain;
7693 tmp->tonezone = conf->chan.tonezone;
7694 tmp->onhooktime = time(NULL);
7695 if (tmp->subs[SUB_REAL].dfd > -1) {
7696 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
7697 if (tmp->dsp)
7698 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
7699 update_conf(tmp);
7700 if (!here) {
7701 if (chan_sig != SIG_PRI)
7702 /* Hang it up to be sure it's good */
7703 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
7705 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
7706 #ifdef HAVE_PRI
7707 /* the dchannel is down so put the channel in alarm */
7708 if (tmp->pri && !pri_is_up(tmp->pri)) {
7709 tmp->inalarm = 1;
7711 #endif
7712 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
7713 tmp->inalarm = 1;
7714 handle_alarms(tmp, res);
7715 } else {
7716 /* yes, this looks strange... the unknown_alarm flag is only used to
7717 control whether an 'alarm cleared' message gets generated when we
7718 get an indication that the channel is no longer in alarm status.
7719 however, the channel *could* be in an alarm status that we aren't
7720 aware of (since get_alarms() only reports span alarms, not channel
7721 alarms). setting this flag will cause any potential 'alarm cleared'
7722 message to be suppressed, but if a real alarm occurs before that
7723 happens, this flag will get cleared by it and the situation will
7724 be normal.
7726 tmp->unknown_alarm = 1;
7730 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
7731 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
7732 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
7733 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
7736 if (tmp && !here) {
7737 /* nothing on the iflist */
7738 if (!*wlist) {
7739 *wlist = tmp;
7740 tmp->prev = NULL;
7741 tmp->next = NULL;
7742 *wend = tmp;
7743 } else {
7744 /* at least one member on the iflist */
7745 struct dahdi_pvt *working = *wlist;
7747 /* check if we maybe have to put it on the begining */
7748 if (working->channel > tmp->channel) {
7749 tmp->next = *wlist;
7750 tmp->prev = NULL;
7751 (*wlist)->prev = tmp;
7752 *wlist = tmp;
7753 } else {
7754 /* go through all the members and put the member in the right place */
7755 while (working) {
7756 /* in the middle */
7757 if (working->next) {
7758 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
7759 tmp->next = working->next;
7760 tmp->prev = working;
7761 working->next->prev = tmp;
7762 working->next = tmp;
7763 break;
7765 } else {
7766 /* the last */
7767 if (working->channel < tmp->channel) {
7768 working->next = tmp;
7769 tmp->next = NULL;
7770 tmp->prev = working;
7771 *wend = tmp;
7772 break;
7775 working = working->next;
7780 return tmp;
7783 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
7785 int res;
7786 struct dahdi_params par;
7788 /* First, check group matching */
7789 if (groupmatch) {
7790 if ((p->group & groupmatch) != groupmatch)
7791 return 0;
7792 *groupmatched = 1;
7794 /* Check to see if we have a channel match */
7795 if (channelmatch != -1) {
7796 if (p->channel != channelmatch)
7797 return 0;
7798 *channelmatched = 1;
7800 /* We're at least busy at this point */
7801 if (busy) {
7802 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
7803 *busy = 1;
7805 /* If do not disturb, definitely not */
7806 if (p->dnd)
7807 return 0;
7808 /* If guard time, definitely not */
7809 if (p->guardtime && (time(NULL) < p->guardtime))
7810 return 0;
7812 /* If no owner definitely available */
7813 if (!p->owner) {
7814 #ifdef HAVE_PRI
7815 /* Trust PRI */
7816 if (p->pri) {
7817 if (p->resetting || p->call)
7818 return 0;
7819 else
7820 return 1;
7822 #endif
7823 if (!(p->radio || (p->oprmode < 0)))
7825 if (!p->sig || (p->sig == SIG_FXSLS))
7826 return 1;
7827 /* Check hook state */
7828 if (p->subs[SUB_REAL].dfd > -1)
7829 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
7830 else {
7831 /* Assume not off hook on CVRS */
7832 res = 0;
7833 par.rxisoffhook = 0;
7835 if (res) {
7836 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
7837 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
7838 /* When "onhook" that means no battery on the line, and thus
7839 it is out of service..., if it's on a TDM card... If it's a channel
7840 bank, there is no telling... */
7841 if (par.rxbits > -1)
7842 return 1;
7843 if (par.rxisoffhook)
7844 return 1;
7845 else
7846 #ifdef DAHDI_CHECK_HOOKSTATE
7847 return 0;
7848 #else
7849 return 1;
7850 #endif
7851 } else if (par.rxisoffhook) {
7852 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
7853 /* Not available when the other end is off hook */
7854 return 0;
7857 return 1;
7860 /* If it's not an FXO, forget about call wait */
7861 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
7862 return 0;
7864 if (!p->callwaiting) {
7865 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
7866 return 0;
7869 if (p->subs[SUB_CALLWAIT].dfd > -1) {
7870 /* If there is already a call waiting call, then we can't take a second one */
7871 return 0;
7874 if ((p->owner->_state != AST_STATE_UP) &&
7875 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
7876 /* If the current call is not up, then don't allow the call */
7877 return 0;
7879 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
7880 /* Can't take a call wait when the three way calling hasn't been merged yet. */
7881 return 0;
7883 /* We're cool */
7884 return 1;
7887 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
7889 struct dahdi_pvt *p;
7890 struct dahdi_bufferinfo bi;
7891 int res;
7893 if ((p = ast_malloc(sizeof(*p)))) {
7894 memcpy(p, src, sizeof(struct dahdi_pvt));
7895 ast_mutex_init(&p->lock);
7896 #ifdef HAVE_ZAPTEL
7897 p->subs[SUB_REAL].dfd = dahdi_open("/dev/zap/pseudo");
7898 #else
7899 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
7900 #endif
7901 /* Allocate a DAHDI structure */
7902 if (p->subs[SUB_REAL].dfd < 0) {
7903 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
7904 destroy_dahdi_pvt(&p);
7905 return NULL;
7907 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
7908 if (!res) {
7909 bi.txbufpolicy = p->buf_policy;
7910 bi.rxbufpolicy = p->buf_policy;
7911 bi.numbufs = p->buf_no;
7912 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
7913 if (res < 0) {
7914 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
7916 } else
7917 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
7919 p->destroy = 1;
7920 p->next = iflist;
7921 p->prev = NULL;
7922 iflist = p;
7923 if (iflist->next)
7924 iflist->next->prev = p;
7925 return p;
7929 #ifdef HAVE_PRI
7930 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
7932 int x;
7933 if (backwards)
7934 x = pri->numchans;
7935 else
7936 x = 0;
7937 for (;;) {
7938 if (backwards && (x < 0))
7939 break;
7940 if (!backwards && (x >= pri->numchans))
7941 break;
7942 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
7943 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
7944 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
7945 return x;
7947 if (backwards)
7948 x--;
7949 else
7950 x++;
7952 return -1;
7954 #endif
7956 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
7958 ast_group_t groupmatch = 0;
7959 int channelmatch = -1;
7960 int roundrobin = 0;
7961 int callwait = 0;
7962 int busy = 0;
7963 struct dahdi_pvt *p;
7964 struct ast_channel *tmp = NULL;
7965 char *dest=NULL;
7966 int x;
7967 char *s;
7968 char opt=0;
7969 int res=0, y=0;
7970 int backwards = 0;
7971 #ifdef HAVE_PRI
7972 int crv;
7973 int bearer = -1;
7974 int trunkgroup;
7975 struct dahdi_pri *pri=NULL;
7976 #endif
7977 struct dahdi_pvt *exit, *start, *end;
7978 ast_mutex_t *lock;
7979 int channelmatched = 0;
7980 int groupmatched = 0;
7982 /* Assume we're locking the iflock */
7983 lock = &iflock;
7984 start = iflist;
7985 end = ifend;
7986 if (data) {
7987 dest = ast_strdupa((char *)data);
7988 } else {
7989 ast_log(LOG_WARNING, "Channel requested with no data\n");
7990 return NULL;
7992 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
7993 /* Retrieve the group number */
7994 char *stringp=NULL;
7995 stringp=dest + 1;
7996 s = strsep(&stringp, "/");
7997 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
7998 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
7999 return NULL;
8001 groupmatch = ((ast_group_t) 1 << x);
8002 if (toupper(dest[0]) == 'G') {
8003 if (dest[0] == 'G') {
8004 backwards = 1;
8005 p = ifend;
8006 } else
8007 p = iflist;
8008 } else {
8009 if (dest[0] == 'R') {
8010 backwards = 1;
8011 p = round_robin[x]?round_robin[x]->prev:ifend;
8012 if (!p)
8013 p = ifend;
8014 } else {
8015 p = round_robin[x]?round_robin[x]->next:iflist;
8016 if (!p)
8017 p = iflist;
8019 roundrobin = 1;
8021 } else {
8022 char *stringp=NULL;
8023 stringp=dest;
8024 s = strsep(&stringp, "/");
8025 p = iflist;
8026 if (!strcasecmp(s, "pseudo")) {
8027 /* Special case for pseudo */
8028 x = CHAN_PSEUDO;
8029 channelmatch = x;
8031 #ifdef HAVE_PRI
8032 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
8033 if ((trunkgroup < 1) || (crv < 1)) {
8034 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
8035 return NULL;
8037 res--;
8038 for (x = 0; x < NUM_SPANS; x++) {
8039 if (pris[x].trunkgroup == trunkgroup) {
8040 pri = pris + x;
8041 lock = &pri->lock;
8042 start = pri->crvs;
8043 end = pri->crvend;
8044 break;
8047 if (!pri) {
8048 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
8049 return NULL;
8051 channelmatch = crv;
8052 p = pris[x].crvs;
8054 #endif
8055 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
8056 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
8057 return NULL;
8058 } else {
8059 channelmatch = x;
8062 /* Search for an unowned channel */
8063 ast_mutex_lock(lock);
8064 exit = p;
8065 while (p && !tmp) {
8066 if (roundrobin)
8067 round_robin[x] = p;
8068 #if 0
8069 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
8070 #endif
8072 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
8073 if (option_debug)
8074 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
8075 if (p->inalarm)
8076 goto next;
8078 callwait = (p->owner != NULL);
8079 #ifdef HAVE_PRI
8080 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
8081 if (p->sig != SIG_FXSKS) {
8082 /* Gotta find an actual channel to use for this
8083 CRV if this isn't a callwait */
8084 bearer = pri_find_empty_chan(pri, 0);
8085 if (bearer < 0) {
8086 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
8087 p = NULL;
8088 break;
8090 pri_assign_bearer(p, pri, pri->pvts[bearer]);
8091 } else {
8092 if (alloc_sub(p, 0)) {
8093 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
8094 p = NULL;
8095 break;
8096 } else
8097 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
8098 p->pri = pri;
8101 #endif
8102 if (p->channel == CHAN_PSEUDO) {
8103 p = chandup(p);
8104 if (!p) {
8105 break;
8108 if (p->owner) {
8109 if (alloc_sub(p, SUB_CALLWAIT)) {
8110 p = NULL;
8111 break;
8114 p->outgoing = 1;
8115 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
8116 #ifdef HAVE_PRI
8117 if (p->bearer) {
8118 /* Log owner to bearer channel, too */
8119 p->bearer->owner = tmp;
8121 #endif
8122 /* Make special notes */
8123 if (res > 1) {
8124 if (opt == 'c') {
8125 /* Confirm answer */
8126 p->confirmanswer = 1;
8127 } else if (opt == 'r') {
8128 /* Distinctive ring */
8129 if (res < 3)
8130 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
8131 else
8132 p->distinctivering = y;
8133 } else if (opt == 'd') {
8134 /* If this is an ISDN call, make it digital */
8135 p->digital = 1;
8136 if (tmp)
8137 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
8138 } else {
8139 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
8142 /* Note if the call is a call waiting call */
8143 if (tmp && callwait)
8144 tmp->cdrflags |= AST_CDR_CALLWAIT;
8145 break;
8147 next:
8148 if (backwards) {
8149 p = p->prev;
8150 if (!p)
8151 p = end;
8152 } else {
8153 p = p->next;
8154 if (!p)
8155 p = start;
8157 /* stop when you roll to the one that we started from */
8158 if (p == exit)
8159 break;
8161 ast_mutex_unlock(lock);
8162 restart_monitor();
8163 if (callwait)
8164 *cause = AST_CAUSE_BUSY;
8165 else if (!tmp) {
8166 if (channelmatched) {
8167 if (busy)
8168 *cause = AST_CAUSE_BUSY;
8169 } else if (groupmatched) {
8170 *cause = AST_CAUSE_CONGESTION;
8174 return tmp;
8178 #ifdef HAVE_PRI
8179 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
8181 struct dahdi_pvt *p;
8182 p = pri->crvs;
8183 while (p) {
8184 if (p->channel == crv)
8185 return p;
8186 p = p->next;
8188 return NULL;
8192 static int pri_find_principle(struct dahdi_pri *pri, int channel)
8194 int x;
8195 int span = PRI_SPAN(channel);
8196 int spanfd;
8197 struct dahdi_params param;
8198 int principle = -1;
8199 int explicit = PRI_EXPLICIT(channel);
8200 channel = PRI_CHANNEL(channel);
8202 if (!explicit) {
8203 spanfd = pri_active_dchan_fd(pri);
8204 if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
8205 return -1;
8206 span = pris[param.spanno - 1].prilogicalspan;
8209 for (x = 0; x < pri->numchans; x++) {
8210 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
8211 principle = x;
8212 break;
8216 return principle;
8219 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
8221 int x;
8222 struct dahdi_pvt *crv;
8223 if (!c) {
8224 if (principle < 0)
8225 return -1;
8226 return principle;
8228 if ((principle > -1) &&
8229 (principle < pri->numchans) &&
8230 (pri->pvts[principle]) &&
8231 (pri->pvts[principle]->call == c))
8232 return principle;
8233 /* First, check for other bearers */
8234 for (x = 0; x < pri->numchans; x++) {
8235 if (!pri->pvts[x])
8236 continue;
8237 if (pri->pvts[x]->call == c) {
8238 /* Found our call */
8239 if (principle != x) {
8240 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
8242 if (option_verbose > 2)
8243 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
8244 old->channel, new->channel);
8245 if (new->owner) {
8246 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
8247 old->channel, new->channel, new->channel);
8248 return -1;
8250 /* Fix it all up now */
8251 new->owner = old->owner;
8252 old->owner = NULL;
8253 if (new->owner) {
8254 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
8255 new->owner->tech_pvt = new;
8256 new->owner->fds[0] = new->subs[SUB_REAL].dfd;
8257 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
8258 old->subs[SUB_REAL].owner = NULL;
8259 } else
8260 ast_log(LOG_WARNING, "Whoa, there's no owner, and we're having to fix up channel %d to channel %d\n", old->channel, new->channel);
8261 new->call = old->call;
8262 old->call = NULL;
8264 /* Copy any DSP that may be present */
8265 new->dsp = old->dsp;
8266 new->dsp_features = old->dsp_features;
8267 old->dsp = NULL;
8268 old->dsp_features = 0;
8270 return principle;
8273 /* Now check for a CRV with no bearer */
8274 crv = pri->crvs;
8275 while (crv) {
8276 if (crv->call == c) {
8277 /* This is our match... Perform some basic checks */
8278 if (crv->bearer)
8279 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
8280 else if (pri->pvts[principle]->owner)
8281 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
8282 else {
8283 /* Looks good. Drop the pseudo channel now, clear up the assignment, and
8284 wakeup the potential sleeper */
8285 dahdi_close_sub(crv, SUB_REAL);
8286 pri->pvts[principle]->call = crv->call;
8287 pri_assign_bearer(crv, pri, pri->pvts[principle]);
8288 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
8289 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
8290 pri->trunkgroup, crv->channel);
8291 wakeup_sub(crv, SUB_REAL, pri);
8293 return principle;
8295 crv = crv->next;
8297 ast_log(LOG_WARNING, "Call specified, but not found?\n");
8298 return -1;
8301 static void *do_idle_thread(void *vchan)
8303 struct ast_channel *chan = vchan;
8304 struct dahdi_pvt *pvt = chan->tech_pvt;
8305 struct ast_frame *f;
8306 char ex[80];
8307 /* Wait up to 30 seconds for an answer */
8308 int newms, ms = 30000;
8309 if (option_verbose > 2)
8310 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
8311 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
8312 if (ast_call(chan, ex, 0)) {
8313 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
8314 ast_hangup(chan);
8315 return NULL;
8317 while ((newms = ast_waitfor(chan, ms)) > 0) {
8318 f = ast_read(chan);
8319 if (!f) {
8320 /* Got hangup */
8321 break;
8323 if (f->frametype == AST_FRAME_CONTROL) {
8324 switch (f->subclass) {
8325 case AST_CONTROL_ANSWER:
8326 /* Launch the PBX */
8327 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
8328 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
8329 chan->priority = 1;
8330 if (option_verbose > 3)
8331 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
8332 ast_pbx_run(chan);
8333 /* It's already hungup, return immediately */
8334 return NULL;
8335 case AST_CONTROL_BUSY:
8336 if (option_verbose > 3)
8337 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
8338 break;
8339 case AST_CONTROL_CONGESTION:
8340 if (option_verbose > 3)
8341 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
8342 break;
8345 ast_frfree(f);
8346 ms = newms;
8348 /* Hangup the channel since nothing happend */
8349 ast_hangup(chan);
8350 return NULL;
8353 #ifndef PRI_RESTART
8354 #error "Upgrade your libpri"
8355 #endif
8356 static void dahdi_pri_message(struct pri *pri, char *s)
8358 int x, y;
8359 int dchan = -1, span = -1;
8360 int dchancount = 0;
8362 if (pri) {
8363 for (x = 0; x < NUM_SPANS; x++) {
8364 for (y = 0; y < NUM_DCHANS; y++) {
8365 if (pris[x].dchans[y])
8366 dchancount++;
8368 if (pris[x].dchans[y] == pri)
8369 dchan = y;
8371 if (dchan >= 0) {
8372 span = x;
8373 break;
8375 dchancount = 0;
8377 if ((dchan >= 0) && (span >= 0)) {
8378 if (dchancount > 1)
8379 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
8380 else
8381 ast_verbose("%s", s);
8382 } else
8383 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
8384 } else
8385 ast_verbose("%s", s);
8387 ast_mutex_lock(&pridebugfdlock);
8389 if (pridebugfd >= 0)
8390 write(pridebugfd, s, strlen(s));
8392 ast_mutex_unlock(&pridebugfdlock);
8395 static void dahdi_pri_error(struct pri *pri, char *s)
8397 int x, y;
8398 int dchan = -1, span = -1;
8399 int dchancount = 0;
8401 if (pri) {
8402 for (x = 0; x < NUM_SPANS; x++) {
8403 for (y = 0; y < NUM_DCHANS; y++) {
8404 if (pris[x].dchans[y])
8405 dchancount++;
8407 if (pris[x].dchans[y] == pri)
8408 dchan = y;
8410 if (dchan >= 0) {
8411 span = x;
8412 break;
8414 dchancount = 0;
8416 if ((dchan >= 0) && (span >= 0)) {
8417 if (dchancount > 1)
8418 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
8419 else
8420 ast_log(LOG_ERROR, "%s", s);
8421 } else
8422 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
8423 } else
8424 ast_log(LOG_ERROR, "%s", s);
8426 ast_mutex_lock(&pridebugfdlock);
8428 if (pridebugfd >= 0)
8429 write(pridebugfd, s, strlen(s));
8431 ast_mutex_unlock(&pridebugfdlock);
8434 static int pri_check_restart(struct dahdi_pri *pri)
8436 do {
8437 pri->resetpos++;
8438 } while ((pri->resetpos < pri->numchans) &&
8439 (!pri->pvts[pri->resetpos] ||
8440 pri->pvts[pri->resetpos]->call ||
8441 pri->pvts[pri->resetpos]->resetting));
8442 if (pri->resetpos < pri->numchans) {
8443 /* Mark the channel as resetting and restart it */
8444 pri->pvts[pri->resetpos]->resetting = 1;
8445 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
8446 } else {
8447 pri->resetting = 0;
8448 time(&pri->lastreset);
8450 return 0;
8453 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
8455 int x;
8456 int redo;
8457 ast_mutex_unlock(&pri->lock);
8458 ast_mutex_lock(&p->lock);
8459 do {
8460 redo = 0;
8461 for (x = 0; x < 3; x++) {
8462 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
8463 redo++;
8464 DEADLOCK_AVOIDANCE(&p->lock);
8466 if (p->subs[x].owner) {
8467 ast_queue_hangup(p->subs[x].owner);
8468 ast_mutex_unlock(&p->subs[x].owner->lock);
8471 } while (redo);
8472 ast_mutex_unlock(&p->lock);
8473 ast_mutex_lock(&pri->lock);
8474 return 0;
8477 static char * redirectingreason2str(int redirectingreason)
8479 switch (redirectingreason) {
8480 case 0:
8481 return "UNKNOWN";
8482 case 1:
8483 return "BUSY";
8484 case 2:
8485 return "NO_REPLY";
8486 case 0xF:
8487 return "UNCONDITIONAL";
8488 default:
8489 return "NOREDIRECT";
8493 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
8495 switch (plan) {
8496 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
8497 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
8498 break;
8499 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
8500 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
8501 break;
8502 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
8503 snprintf(buf, size, "%s%s", pri->localprefix, number);
8504 break;
8505 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
8506 snprintf(buf, size, "%s%s", pri->privateprefix, number);
8507 break;
8508 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
8509 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
8510 break;
8511 default: /* other Q.931 dialplan => don't twiddle with callingnum */
8512 snprintf(buf, size, "%s", number);
8513 break;
8517 static int dahdi_setlaw(int dfd, int law)
8519 int res;
8520 res = ioctl(dfd, DAHDI_SETLAW, &law);
8521 if (res)
8522 return res;
8523 return 0;
8526 static void *pri_dchannel(void *vpri)
8528 struct dahdi_pri *pri = vpri;
8529 pri_event *e;
8530 struct pollfd fds[NUM_DCHANS];
8531 int res;
8532 int chanpos = 0;
8533 int x;
8534 int haveidles;
8535 int activeidles;
8536 int nextidle = -1;
8537 struct ast_channel *c;
8538 struct timeval tv, lowest, *next;
8539 struct timeval lastidle = { 0, 0 };
8540 int doidling=0;
8541 char *cc;
8542 char idlen[80];
8543 struct ast_channel *idle;
8544 pthread_t p;
8545 time_t t;
8546 int i, which=-1;
8547 int numdchans;
8548 int cause=0;
8549 struct dahdi_pvt *crv;
8550 pthread_t threadid;
8551 pthread_attr_t attr;
8552 char ani2str[6];
8553 char plancallingnum[256];
8554 char plancallingani[256];
8555 char calledtonstr[10];
8557 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
8559 gettimeofday(&lastidle, NULL);
8560 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
8561 /* Need to do idle dialing, check to be sure though */
8562 cc = strchr(pri->idleext, '@');
8563 if (cc) {
8564 *cc = '\0';
8565 cc++;
8566 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
8567 #if 0
8568 /* Extensions may not be loaded yet */
8569 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
8570 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
8571 else
8572 #endif
8573 doidling = 1;
8574 } else
8575 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
8577 for (;;) {
8578 for (i = 0; i < NUM_DCHANS; i++) {
8579 if (!pri->dchannels[i])
8580 break;
8581 fds[i].fd = pri->fds[i];
8582 fds[i].events = POLLIN | POLLPRI;
8583 fds[i].revents = 0;
8585 numdchans = i;
8586 time(&t);
8587 ast_mutex_lock(&pri->lock);
8588 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
8589 if (pri->resetting && pri_is_up(pri)) {
8590 if (pri->resetpos < 0)
8591 pri_check_restart(pri);
8592 } else {
8593 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
8594 pri->resetting = 1;
8595 pri->resetpos = -1;
8599 /* Look for any idle channels if appropriate */
8600 if (doidling && pri_is_up(pri)) {
8601 nextidle = -1;
8602 haveidles = 0;
8603 activeidles = 0;
8604 for (x = pri->numchans; x >= 0; x--) {
8605 if (pri->pvts[x] && !pri->pvts[x]->owner &&
8606 !pri->pvts[x]->call) {
8607 if (haveidles < pri->minunused) {
8608 haveidles++;
8609 } else if (!pri->pvts[x]->resetting) {
8610 nextidle = x;
8611 break;
8613 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
8614 activeidles++;
8616 if (nextidle > -1) {
8617 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
8618 /* Don't create a new idle call more than once per second */
8619 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
8620 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
8621 if (idle) {
8622 pri->pvts[nextidle]->isidlecall = 1;
8623 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
8624 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
8625 dahdi_hangup(idle);
8627 } else
8628 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
8629 gettimeofday(&lastidle, NULL);
8631 } else if ((haveidles < pri->minunused) &&
8632 (activeidles > pri->minidle)) {
8633 /* Mark something for hangup if there is something
8634 that can be hungup */
8635 for (x = pri->numchans; x >= 0; x--) {
8636 /* find a candidate channel */
8637 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
8638 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8639 haveidles++;
8640 /* Stop if we have enough idle channels or
8641 can't spare any more active idle ones */
8642 if ((haveidles >= pri->minunused) ||
8643 (activeidles <= pri->minidle))
8644 break;
8649 /* Start with reasonable max */
8650 lowest = ast_tv(60, 0);
8651 for (i = 0; i < NUM_DCHANS; i++) {
8652 /* Find lowest available d-channel */
8653 if (!pri->dchannels[i])
8654 break;
8655 if ((next = pri_schedule_next(pri->dchans[i]))) {
8656 /* We need relative time here */
8657 tv = ast_tvsub(*next, ast_tvnow());
8658 if (tv.tv_sec < 0) {
8659 tv = ast_tv(0,0);
8661 if (doidling || pri->resetting) {
8662 if (tv.tv_sec > 1) {
8663 tv = ast_tv(1, 0);
8665 } else {
8666 if (tv.tv_sec > 60) {
8667 tv = ast_tv(60, 0);
8670 } else if (doidling || pri->resetting) {
8671 /* Make sure we stop at least once per second if we're
8672 monitoring idle channels */
8673 tv = ast_tv(1,0);
8674 } else {
8675 /* Don't poll for more than 60 seconds */
8676 tv = ast_tv(60, 0);
8678 if (!i || ast_tvcmp(tv, lowest) < 0) {
8679 lowest = tv;
8682 ast_mutex_unlock(&pri->lock);
8684 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
8685 pthread_testcancel();
8686 e = NULL;
8687 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
8688 pthread_testcancel();
8689 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
8691 ast_mutex_lock(&pri->lock);
8692 if (!res) {
8693 for (which = 0; which < NUM_DCHANS; which++) {
8694 if (!pri->dchans[which])
8695 break;
8696 /* Just a timeout, run the scheduler */
8697 e = pri_schedule_run(pri->dchans[which]);
8698 if (e)
8699 break;
8701 } else if (res > -1) {
8702 for (which = 0; which < NUM_DCHANS; which++) {
8703 if (!pri->dchans[which])
8704 break;
8705 if (fds[which].revents & POLLPRI) {
8706 /* Check for an event */
8707 x = 0;
8708 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
8709 if (x)
8710 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
8711 /* Keep track of alarm state */
8712 if (x == DAHDI_EVENT_ALARM) {
8713 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
8714 pri_find_dchan(pri);
8715 } else if (x == DAHDI_EVENT_NOALARM) {
8716 pri->dchanavail[which] |= DCHAN_NOTINALARM;
8717 pri_restart(pri->dchans[which]);
8720 if (option_debug)
8721 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
8722 } else if (fds[which].revents & POLLIN) {
8723 e = pri_check_event(pri->dchans[which]);
8725 if (e)
8726 break;
8728 } else if (errno != EINTR)
8729 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
8731 if (e) {
8732 if (pri->debug)
8733 pri_dump_event(pri->dchans[which], e);
8735 if (e->e != PRI_EVENT_DCHAN_DOWN) {
8736 if (!(pri->dchanavail[which] & DCHAN_UP)) {
8737 if (option_verbose > 1)
8738 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
8740 pri->dchanavail[which] |= DCHAN_UP;
8741 } else {
8742 if (pri->dchanavail[which] & DCHAN_UP) {
8743 if (option_verbose > 1)
8744 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
8746 pri->dchanavail[which] &= ~DCHAN_UP;
8749 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
8750 /* Must be an NFAS group that has the secondary dchan active */
8751 pri->pri = pri->dchans[which];
8753 switch (e->e) {
8754 case PRI_EVENT_DCHAN_UP:
8755 if (!pri->pri) pri_find_dchan(pri);
8757 /* Note presense of D-channel */
8758 time(&pri->lastreset);
8760 /* Restart in 5 seconds */
8761 if (pri->resetinterval > -1) {
8762 pri->lastreset -= pri->resetinterval;
8763 pri->lastreset += 5;
8765 pri->resetting = 0;
8766 /* Take the channels from inalarm condition */
8767 for (i = 0; i < pri->numchans; i++)
8768 if (pri->pvts[i]) {
8769 pri->pvts[i]->inalarm = 0;
8771 break;
8772 case PRI_EVENT_DCHAN_DOWN:
8773 pri_find_dchan(pri);
8774 if (!pri_is_up(pri)) {
8775 pri->resetting = 0;
8776 /* Hangup active channels and put them in alarm mode */
8777 for (i = 0; i < pri->numchans; i++) {
8778 struct dahdi_pvt *p = pri->pvts[i];
8779 if (p) {
8780 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
8781 /* T309 is not enabled : hangup calls when alarm occurs */
8782 if (p->call) {
8783 if (p->pri && p->pri->pri) {
8784 pri_hangup(p->pri->pri, p->call, -1);
8785 pri_destroycall(p->pri->pri, p->call);
8786 p->call = NULL;
8787 } else
8788 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
8790 if (p->realcall) {
8791 pri_hangup_all(p->realcall, pri);
8792 } else if (p->owner)
8793 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8795 p->inalarm = 1;
8799 break;
8800 case PRI_EVENT_RESTART:
8801 if (e->restart.channel > -1) {
8802 chanpos = pri_find_principle(pri, e->restart.channel);
8803 if (chanpos < 0)
8804 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
8805 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
8806 else {
8807 if (option_verbose > 2)
8808 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n",
8809 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
8810 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8811 if (pri->pvts[chanpos]->call) {
8812 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
8813 pri->pvts[chanpos]->call = NULL;
8815 /* Force soft hangup if appropriate */
8816 if (pri->pvts[chanpos]->realcall)
8817 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8818 else if (pri->pvts[chanpos]->owner)
8819 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8820 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8822 } else {
8823 if (option_verbose > 2)
8824 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
8825 for (x = 0; x < pri->numchans; x++)
8826 if (pri->pvts[x]) {
8827 ast_mutex_lock(&pri->pvts[x]->lock);
8828 if (pri->pvts[x]->call) {
8829 pri_destroycall(pri->pri, pri->pvts[x]->call);
8830 pri->pvts[x]->call = NULL;
8832 if (pri->pvts[chanpos]->realcall)
8833 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8834 else if (pri->pvts[x]->owner)
8835 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8836 ast_mutex_unlock(&pri->pvts[x]->lock);
8839 break;
8840 case PRI_EVENT_KEYPAD_DIGIT:
8841 chanpos = pri_find_principle(pri, e->digit.channel);
8842 if (chanpos < 0) {
8843 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
8844 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
8845 } else {
8846 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
8847 if (chanpos > -1) {
8848 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8849 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
8850 if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
8851 /* how to do that */
8852 int digitlen = strlen(e->digit.digits);
8853 char digit;
8854 int i;
8855 for (i = 0; i < digitlen; i++) {
8856 digit = e->digit.digits[i];
8858 struct ast_frame f = { AST_FRAME_DTMF, digit, };
8859 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
8863 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8866 break;
8868 case PRI_EVENT_INFO_RECEIVED:
8869 chanpos = pri_find_principle(pri, e->ring.channel);
8870 if (chanpos < 0) {
8871 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
8872 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8873 } else {
8874 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
8875 if (chanpos > -1) {
8876 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8877 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
8878 if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
8879 /* how to do that */
8880 int digitlen = strlen(e->ring.callednum);
8881 char digit;
8882 int i;
8883 for (i = 0; i < digitlen; i++) {
8884 digit = e->ring.callednum[i];
8886 struct ast_frame f = { AST_FRAME_DTMF, digit, };
8887 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
8891 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8894 break;
8895 case PRI_EVENT_RING:
8896 crv = NULL;
8897 if (e->ring.channel == -1)
8898 chanpos = pri_find_empty_chan(pri, 1);
8899 else
8900 chanpos = pri_find_principle(pri, e->ring.channel);
8901 /* if no channel specified find one empty */
8902 if (chanpos < 0) {
8903 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
8904 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8905 } else {
8906 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8907 if (pri->pvts[chanpos]->owner) {
8908 if (pri->pvts[chanpos]->call == e->ring.call) {
8909 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
8910 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8911 break;
8912 } else {
8913 /* This is where we handle initial glare */
8914 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
8915 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8916 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8917 chanpos = -1;
8920 if (chanpos > -1)
8921 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8923 if ((chanpos < 0) && (e->ring.flexible))
8924 chanpos = pri_find_empty_chan(pri, 1);
8925 if (chanpos > -1) {
8926 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8927 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
8928 /* Should be safe to lock CRV AFAIK while bearer is still locked */
8929 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
8930 if (crv)
8931 ast_mutex_lock(&crv->lock);
8932 if (!crv || crv->owner) {
8933 pri->pvts[chanpos]->call = NULL;
8934 if (crv) {
8935 if (crv->owner)
8936 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8937 ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
8938 } else
8939 ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
8940 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
8941 if (crv)
8942 ast_mutex_unlock(&crv->lock);
8943 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8944 break;
8947 pri->pvts[chanpos]->call = e->ring.call;
8948 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
8949 if (pri->pvts[chanpos]->use_callerid) {
8950 ast_shrink_phone_number(plancallingnum);
8951 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
8952 #ifdef PRI_ANI
8953 if (!ast_strlen_zero(e->ring.callingani)) {
8954 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
8955 ast_shrink_phone_number(plancallingani);
8956 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
8957 } else {
8958 pri->pvts[chanpos]->cid_ani[0] = '\0';
8960 #endif
8961 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
8962 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
8963 } else {
8964 pri->pvts[chanpos]->cid_num[0] = '\0';
8965 pri->pvts[chanpos]->cid_ani[0] = '\0';
8966 pri->pvts[chanpos]->cid_name[0] = '\0';
8967 pri->pvts[chanpos]->cid_ton = 0;
8969 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
8970 e->ring.redirectingnum, e->ring.callingplanrdnis);
8971 /* get callingpres */
8972 pri->pvts[chanpos]->cid_pres = e->ring.callingpres;
8973 switch (e->ring.callingpres) {
8974 case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
8975 case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
8976 case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
8977 case PRES_PROHIB_NETWORK_NUMBER:
8978 ast_copy_string(pri->pvts[chanpos]->cid_name, pri->withheldcid, sizeof(pri->pvts[chanpos]->cid_name));
8979 break;
8980 case PRES_NUMBER_NOT_AVAILABLE:
8981 ast_copy_string(pri->pvts[chanpos]->cid_name, pri->nocid, sizeof(pri->pvts[chanpos]->cid_name));
8982 break;
8984 /* If immediate=yes go to s|1 */
8985 if (pri->pvts[chanpos]->immediate) {
8986 if (option_verbose > 2)
8987 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
8988 pri->pvts[chanpos]->exten[0] = 's';
8989 pri->pvts[chanpos]->exten[1] = '\0';
8991 /* Get called number */
8992 else if (!ast_strlen_zero(e->ring.callednum)) {
8993 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
8994 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
8995 } else if (pri->overlapdial)
8996 pri->pvts[chanpos]->exten[0] = '\0';
8997 else {
8998 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
8999 pri->pvts[chanpos]->exten[0] = 's';
9000 pri->pvts[chanpos]->exten[1] = '\0';
9002 /* Set DNID on all incoming calls -- even immediate */
9003 if (!ast_strlen_zero(e->ring.callednum))
9004 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
9005 /* No number yet, but received "sending complete"? */
9006 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
9007 if (option_verbose > 2)
9008 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
9009 pri->pvts[chanpos]->exten[0] = 's';
9010 pri->pvts[chanpos]->exten[1] = '\0';
9012 /* Make sure extension exists (or in overlap dial mode, can exist) */
9013 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
9014 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
9015 /* Setup law */
9016 int law;
9017 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
9018 /* Set to audio mode at this point */
9019 law = 1;
9020 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
9021 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
9023 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
9024 law = DAHDI_LAW_ALAW;
9025 else
9026 law = DAHDI_LAW_MULAW;
9027 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
9028 if (res < 0)
9029 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
9030 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
9031 if (res < 0)
9032 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
9033 if (e->ring.complete || !pri->overlapdial) {
9034 /* Just announce proceeding */
9035 pri->pvts[chanpos]->proceeding = 1;
9036 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
9037 } else {
9038 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
9039 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
9040 else
9041 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
9043 /* Get the use_callingpres state */
9044 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
9046 /* Start PBX */
9047 if (!e->ring.complete && pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
9048 /* Release the PRI lock while we create the channel */
9049 ast_mutex_unlock(&pri->lock);
9050 if (crv) {
9051 /* Set bearer and such */
9052 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
9053 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
9054 pri->pvts[chanpos]->owner = &inuse;
9055 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
9056 } else {
9057 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
9060 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9062 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
9063 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
9065 if (e->ring.ani2 >= 0) {
9066 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
9067 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
9070 #ifdef SUPPORT_USERUSER
9071 if (!ast_strlen_zero(e->ring.useruserinfo)) {
9072 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
9074 #endif
9076 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
9077 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
9078 if (e->ring.redirectingreason >= 0)
9079 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
9081 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9082 ast_mutex_lock(&pri->lock);
9084 pthread_attr_init(&attr);
9085 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
9086 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
9087 if (option_verbose > 2)
9088 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
9089 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
9090 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
9091 } else {
9092 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
9093 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
9094 if (c)
9095 ast_hangup(c);
9096 else {
9097 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
9098 pri->pvts[chanpos]->call = NULL;
9101 pthread_attr_destroy(&attr);
9102 } else {
9103 ast_mutex_unlock(&pri->lock);
9104 /* Release PRI lock while we create the channel */
9105 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
9106 if (c) {
9107 char calledtonstr[10];
9109 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9111 if (e->ring.ani2 >= 0) {
9112 snprintf(ani2str, 5, "%d", e->ring.ani2);
9113 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
9116 #ifdef SUPPORT_USERUSER
9117 if (!ast_strlen_zero(e->ring.useruserinfo)) {
9118 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
9120 #endif
9122 if (e->ring.redirectingreason >= 0)
9123 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
9125 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
9126 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
9128 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9129 ast_mutex_lock(&pri->lock);
9131 if (option_verbose > 2)
9132 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
9133 plancallingnum, pri->pvts[chanpos]->exten,
9134 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
9135 dahdi_enable_ec(pri->pvts[chanpos]);
9136 } else {
9138 ast_mutex_lock(&pri->lock);
9140 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
9141 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
9142 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
9143 pri->pvts[chanpos]->call = NULL;
9146 } else {
9147 if (option_verbose > 2)
9148 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
9149 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
9150 pri->pvts[chanpos]->prioffset, pri->span);
9151 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
9152 pri->pvts[chanpos]->call = NULL;
9153 pri->pvts[chanpos]->exten[0] = '\0';
9155 if (crv)
9156 ast_mutex_unlock(&crv->lock);
9157 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9158 } else {
9159 if (e->ring.flexible)
9160 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
9161 else
9162 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
9164 break;
9165 case PRI_EVENT_RINGING:
9166 chanpos = pri_find_principle(pri, e->ringing.channel);
9167 if (chanpos < 0) {
9168 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
9169 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
9170 } else {
9171 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
9172 if (chanpos < 0) {
9173 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
9174 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
9175 } else {
9176 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9177 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
9178 dahdi_enable_ec(pri->pvts[chanpos]);
9179 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
9180 pri->pvts[chanpos]->alerting = 1;
9181 } else
9182 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
9183 #ifdef PRI_PROGRESS_MASK
9184 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9185 #else
9186 if (e->ringing.progress == 8) {
9187 #endif
9188 /* Now we can do call progress detection */
9189 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9190 /* RINGING detection isn't required because we got ALERTING signal */
9191 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
9192 pri->pvts[chanpos]->dsp_features = 0;
9196 #ifdef SUPPORT_USERUSER
9197 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
9198 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9199 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9200 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
9201 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9203 #endif
9205 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9208 break;
9209 case PRI_EVENT_PROGRESS:
9210 /* Get chan value if e->e is not PRI_EVNT_RINGING */
9211 chanpos = pri_find_principle(pri, e->proceeding.channel);
9212 if (chanpos > -1) {
9213 #ifdef PRI_PROGRESS_MASK
9214 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
9215 #else
9216 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
9217 #endif
9218 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
9220 if (e->proceeding.cause > -1) {
9221 if (option_verbose > 2)
9222 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
9224 /* Work around broken, out of spec USER_BUSY cause in a progress message */
9225 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
9226 if (pri->pvts[chanpos]->owner) {
9227 if (option_verbose > 2)
9228 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
9230 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
9231 f.subclass = AST_CONTROL_BUSY;
9236 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9237 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
9238 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
9239 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9240 #ifdef PRI_PROGRESS_MASK
9241 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9242 #else
9243 if (e->proceeding.progress == 8) {
9244 #endif
9245 /* Now we can do call progress detection */
9246 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9247 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9248 pri->pvts[chanpos]->dsp_features = 0;
9251 pri->pvts[chanpos]->progress = 1;
9252 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9255 break;
9256 case PRI_EVENT_PROCEEDING:
9257 chanpos = pri_find_principle(pri, e->proceeding.channel);
9258 if (chanpos > -1) {
9259 if (!pri->pvts[chanpos]->proceeding) {
9260 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
9262 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9263 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
9264 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
9265 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9266 #ifdef PRI_PROGRESS_MASK
9267 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9268 #else
9269 if (e->proceeding.progress == 8) {
9270 #endif
9271 /* Now we can do call progress detection */
9272 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9273 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9274 pri->pvts[chanpos]->dsp_features = 0;
9276 /* Bring voice path up */
9277 f.subclass = AST_CONTROL_PROGRESS;
9278 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9280 pri->pvts[chanpos]->proceeding = 1;
9281 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9284 break;
9285 case PRI_EVENT_FACNAME:
9286 chanpos = pri_find_principle(pri, e->facname.channel);
9287 if (chanpos < 0) {
9288 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
9289 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
9290 } else {
9291 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
9292 if (chanpos < 0) {
9293 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
9294 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
9295 } else {
9296 /* Re-use *69 field for PRI */
9297 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9298 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
9299 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
9300 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
9301 dahdi_enable_ec(pri->pvts[chanpos]);
9302 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9305 break;
9306 case PRI_EVENT_ANSWER:
9307 chanpos = pri_find_principle(pri, e->answer.channel);
9308 if (chanpos < 0) {
9309 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
9310 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
9311 } else {
9312 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
9313 if (chanpos < 0) {
9314 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
9315 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
9316 } else {
9317 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9318 /* Now we can do call progress detection */
9320 /* We changed this so it turns on the DSP no matter what... progress or no progress.
9321 * By this time, we need DTMF detection and other features that were previously disabled
9322 * -- Matt F */
9323 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9324 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9325 pri->pvts[chanpos]->dsp_features = 0;
9327 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
9328 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
9329 x = DAHDI_START;
9330 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
9331 if (res < 0) {
9332 if (errno != EINPROGRESS) {
9333 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
9336 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
9337 pri->pvts[chanpos]->dialing = 1;
9338 /* Send any "w" waited stuff */
9339 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
9340 if (res < 0) {
9341 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
9342 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
9343 } else
9344 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
9345 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
9346 } else if (pri->pvts[chanpos]->confirmanswer) {
9347 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
9348 } else {
9349 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
9350 /* Enable echo cancellation if it's not on already */
9351 dahdi_enable_ec(pri->pvts[chanpos]);
9354 #ifdef SUPPORT_USERUSER
9355 if (!ast_strlen_zero(e->answer.useruserinfo)) {
9356 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9357 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9358 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
9359 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9361 #endif
9363 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9366 break;
9367 case PRI_EVENT_HANGUP:
9368 chanpos = pri_find_principle(pri, e->hangup.channel);
9369 if (chanpos < 0) {
9370 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
9371 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9372 } else {
9373 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9374 if (chanpos > -1) {
9375 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9376 if (!pri->pvts[chanpos]->alreadyhungup) {
9377 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
9378 pri->pvts[chanpos]->alreadyhungup = 1;
9379 if (pri->pvts[chanpos]->realcall)
9380 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9381 else if (pri->pvts[chanpos]->owner) {
9382 /* Queue a BUSY instead of a hangup if our cause is appropriate */
9383 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
9384 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
9385 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9386 else {
9387 switch (e->hangup.cause) {
9388 case PRI_CAUSE_USER_BUSY:
9389 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
9390 break;
9391 case PRI_CAUSE_CALL_REJECTED:
9392 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
9393 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
9394 case PRI_CAUSE_SWITCH_CONGESTION:
9395 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
9396 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
9397 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
9398 break;
9399 default:
9400 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9404 if (option_verbose > 2)
9405 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
9406 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
9407 } else {
9408 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
9409 pri->pvts[chanpos]->call = NULL;
9411 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
9412 if (option_verbose > 2)
9413 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
9414 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9415 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
9416 pri->pvts[chanpos]->resetting = 1;
9418 if (e->hangup.aoc_units > -1)
9419 if (option_verbose > 2)
9420 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9421 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
9423 #ifdef SUPPORT_USERUSER
9424 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
9425 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9426 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9427 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9428 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9430 #endif
9432 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9433 } else {
9434 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
9435 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9438 break;
9439 #ifndef PRI_EVENT_HANGUP_REQ
9440 #error please update libpri
9441 #endif
9442 case PRI_EVENT_HANGUP_REQ:
9443 chanpos = pri_find_principle(pri, e->hangup.channel);
9444 if (chanpos < 0) {
9445 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
9446 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9447 } else {
9448 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9449 if (chanpos > -1) {
9450 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9451 if (pri->pvts[chanpos]->realcall)
9452 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9453 else if (pri->pvts[chanpos]->owner) {
9454 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
9455 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
9456 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9457 else {
9458 switch (e->hangup.cause) {
9459 case PRI_CAUSE_USER_BUSY:
9460 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
9461 break;
9462 case PRI_CAUSE_CALL_REJECTED:
9463 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
9464 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
9465 case PRI_CAUSE_SWITCH_CONGESTION:
9466 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
9467 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
9468 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
9469 break;
9470 default:
9471 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9474 if (option_verbose > 2)
9475 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
9476 if (e->hangup.aoc_units > -1)
9477 if (option_verbose > 2)
9478 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9479 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
9480 } else {
9481 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
9482 pri->pvts[chanpos]->call = NULL;
9484 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
9485 if (option_verbose > 2)
9486 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
9487 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9488 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
9489 pri->pvts[chanpos]->resetting = 1;
9492 #ifdef SUPPORT_USERUSER
9493 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
9494 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9495 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9496 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9497 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9499 #endif
9501 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9502 } else {
9503 ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9506 break;
9507 case PRI_EVENT_HANGUP_ACK:
9508 chanpos = pri_find_principle(pri, e->hangup.channel);
9509 if (chanpos < 0) {
9510 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
9511 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9512 } else {
9513 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9514 if (chanpos > -1) {
9515 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9516 pri->pvts[chanpos]->call = NULL;
9517 pri->pvts[chanpos]->resetting = 0;
9518 if (pri->pvts[chanpos]->owner) {
9519 if (option_verbose > 2)
9520 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9523 #ifdef SUPPORT_USERUSER
9524 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
9525 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9526 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9527 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9528 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9530 #endif
9532 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9535 break;
9536 case PRI_EVENT_CONFIG_ERR:
9537 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
9538 break;
9539 case PRI_EVENT_RESTART_ACK:
9540 chanpos = pri_find_principle(pri, e->restartack.channel);
9541 if (chanpos < 0) {
9542 /* Sometime switches (e.g. I421 / British Telecom) don't give us the
9543 channel number, so we have to figure it out... This must be why
9544 everybody resets exactly a channel at a time. */
9545 for (x = 0; x < pri->numchans; x++) {
9546 if (pri->pvts[x] && pri->pvts[x]->resetting) {
9547 chanpos = x;
9548 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9549 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
9550 pri->pvts[chanpos]->prioffset, pri->span);
9551 if (pri->pvts[chanpos]->realcall)
9552 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9553 else if (pri->pvts[chanpos]->owner) {
9554 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
9555 pri->pvts[chanpos]->prioffset, pri->span);
9556 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9558 pri->pvts[chanpos]->resetting = 0;
9559 if (option_verbose > 2)
9560 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
9561 pri->pvts[chanpos]->prioffset, pri->span);
9562 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9563 if (pri->resetting)
9564 pri_check_restart(pri);
9565 break;
9568 if (chanpos < 0) {
9569 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
9570 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
9572 } else {
9573 if (pri->pvts[chanpos]) {
9574 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9575 if (pri->pvts[chanpos]->realcall)
9576 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9577 else if (pri->pvts[chanpos]->owner) {
9578 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
9579 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
9580 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9582 pri->pvts[chanpos]->resetting = 0;
9583 if (option_verbose > 2)
9584 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
9585 pri->pvts[chanpos]->prioffset, pri->span);
9586 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9587 if (pri->resetting)
9588 pri_check_restart(pri);
9591 break;
9592 case PRI_EVENT_SETUP_ACK:
9593 chanpos = pri_find_principle(pri, e->setup_ack.channel);
9594 if (chanpos < 0) {
9595 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
9596 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
9597 } else {
9598 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
9599 if (chanpos > -1) {
9600 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9601 pri->pvts[chanpos]->setup_ack = 1;
9602 /* Send any queued digits */
9603 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
9604 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
9605 pri_information(pri->pri, pri->pvts[chanpos]->call,
9606 pri->pvts[chanpos]->dialdest[x]);
9608 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9609 } else
9610 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
9612 break;
9613 case PRI_EVENT_NOTIFY:
9614 chanpos = pri_find_principle(pri, e->notify.channel);
9615 if (chanpos < 0) {
9616 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
9617 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
9618 } else {
9619 struct ast_frame f = { AST_FRAME_CONTROL, };
9620 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9621 switch (e->notify.info) {
9622 case PRI_NOTIFY_REMOTE_HOLD:
9623 f.subclass = AST_CONTROL_HOLD;
9624 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9625 break;
9626 case PRI_NOTIFY_REMOTE_RETRIEVAL:
9627 f.subclass = AST_CONTROL_UNHOLD;
9628 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9629 break;
9631 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9633 break;
9634 default:
9635 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
9638 ast_mutex_unlock(&pri->lock);
9640 /* Never reached */
9641 return NULL;
9644 static int start_pri(struct dahdi_pri *pri)
9646 int res, x;
9647 struct dahdi_params p;
9648 struct dahdi_bufferinfo bi;
9649 struct dahdi_spaninfo si;
9650 int i;
9652 for (i = 0; i < NUM_DCHANS; i++) {
9653 if (!pri->dchannels[i])
9654 break;
9655 #ifdef HAVE_ZAPTEL
9656 pri->fds[i] = open("/dev/zap/channel", O_RDWR, 0600);
9657 #else
9658 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR, 0600);
9659 #endif
9660 x = pri->dchannels[i];
9661 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
9662 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
9663 return -1;
9665 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
9666 if (res) {
9667 dahdi_close_pri_fd(pri, i);
9668 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
9669 return -1;
9671 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
9672 dahdi_close_pri_fd(pri, i);
9673 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x);
9674 return -1;
9676 memset(&si, 0, sizeof(si));
9677 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
9678 if (res) {
9679 dahdi_close_pri_fd(pri, i);
9680 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
9682 if (!si.alarms)
9683 pri->dchanavail[i] |= DCHAN_NOTINALARM;
9684 else
9685 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
9686 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
9687 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
9688 bi.numbufs = 32;
9689 bi.bufsize = 1024;
9690 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
9691 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
9692 dahdi_close_pri_fd(pri, i);
9693 return -1;
9695 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
9696 /* Force overlap dial if we're doing GR-303! */
9697 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
9698 pri->overlapdial = 1;
9699 pri_set_overlapdial(pri->dchans[i],pri->overlapdial);
9700 #ifdef HAVE_PRI_INBANDDISCONNECT
9701 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
9702 #endif
9703 /* Enslave to master if appropriate */
9704 if (i)
9705 pri_enslave(pri->dchans[0], pri->dchans[i]);
9706 if (!pri->dchans[i]) {
9707 dahdi_close_pri_fd(pri, i);
9708 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
9709 return -1;
9711 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
9712 pri_set_nsf(pri->dchans[i], pri->nsf);
9713 #ifdef PRI_GETSET_TIMERS
9714 for (x = 0; x < PRI_MAX_TIMERS; x++) {
9715 if (pritimers[x] != 0)
9716 pri_set_timer(pri->dchans[i], x, pritimers[x]);
9718 #endif
9720 /* Assume primary is the one we use */
9721 pri->pri = pri->dchans[0];
9722 pri->resetpos = -1;
9723 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
9724 for (i = 0; i < NUM_DCHANS; i++) {
9725 if (!pri->dchannels[i])
9726 break;
9727 dahdi_close_pri_fd(pri, i);
9729 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
9730 return -1;
9732 return 0;
9735 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
9737 int which, span;
9738 char *ret = NULL;
9740 if (pos != rpos)
9741 return ret;
9743 for (which = span = 0; span < NUM_SPANS; span++) {
9744 if (pris[span].pri && ++which > state) {
9745 asprintf(&ret, "%d", span + 1); /* user indexes start from 1 */
9746 break;
9749 return ret;
9752 static char *complete_span_4(const char *line, const char *word, int pos, int state)
9754 return complete_span_helper(line,word,pos,state,3);
9757 static char *complete_span_5(const char *line, const char *word, int pos, int state)
9759 return complete_span_helper(line,word,pos,state,4);
9762 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
9764 int myfd;
9766 if (!strncasecmp(argv[1], "set", 3)) {
9767 if (argc < 5)
9768 return RESULT_SHOWUSAGE;
9770 if (ast_strlen_zero(argv[4]))
9771 return RESULT_SHOWUSAGE;
9773 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
9774 if (myfd < 0) {
9775 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
9776 return RESULT_SUCCESS;
9779 ast_mutex_lock(&pridebugfdlock);
9781 if (pridebugfd >= 0)
9782 close(pridebugfd);
9784 pridebugfd = myfd;
9785 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
9787 ast_mutex_unlock(&pridebugfdlock);
9789 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
9790 } else {
9791 /* Assume it is unset */
9792 ast_mutex_lock(&pridebugfdlock);
9793 close(pridebugfd);
9794 pridebugfd = -1;
9795 ast_cli(fd, "PRI debug output to file disabled\n");
9796 ast_mutex_unlock(&pridebugfdlock);
9799 return RESULT_SUCCESS;
9802 #ifdef HAVE_PRI_VERSION
9803 static int handle_pri_version(int fd, int agc, char *argv[]) {
9804 ast_cli(fd, "libpri version: %s\n", pri_get_version());
9805 return RESULT_SUCCESS;
9807 #endif
9809 static int handle_pri_debug(int fd, int argc, char *argv[])
9811 int span;
9812 int x;
9813 if (argc < 4) {
9814 return RESULT_SHOWUSAGE;
9816 span = atoi(argv[3]);
9817 if ((span < 1) || (span > NUM_SPANS)) {
9818 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
9819 return RESULT_SUCCESS;
9821 if (!pris[span-1].pri) {
9822 ast_cli(fd, "No PRI running on span %d\n", span);
9823 return RESULT_SUCCESS;
9825 for (x = 0; x < NUM_DCHANS; x++) {
9826 if (pris[span-1].dchans[x])
9827 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
9828 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
9829 PRI_DEBUG_Q921_STATE);
9831 ast_cli(fd, "Enabled debugging on span %d\n", span);
9832 return RESULT_SUCCESS;
9837 static int handle_pri_no_debug(int fd, int argc, char *argv[])
9839 int span;
9840 int x;
9841 if (argc < 5)
9842 return RESULT_SHOWUSAGE;
9843 span = atoi(argv[4]);
9844 if ((span < 1) || (span > NUM_SPANS)) {
9845 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
9846 return RESULT_SUCCESS;
9848 if (!pris[span-1].pri) {
9849 ast_cli(fd, "No PRI running on span %d\n", span);
9850 return RESULT_SUCCESS;
9852 for (x = 0; x < NUM_DCHANS; x++) {
9853 if (pris[span-1].dchans[x])
9854 pri_set_debug(pris[span-1].dchans[x], 0);
9856 ast_cli(fd, "Disabled debugging on span %d\n", span);
9857 return RESULT_SUCCESS;
9860 static int handle_pri_really_debug(int fd, int argc, char *argv[])
9862 int span;
9863 int x;
9864 if (argc < 5)
9865 return RESULT_SHOWUSAGE;
9866 span = atoi(argv[4]);
9867 if ((span < 1) || (span > NUM_SPANS)) {
9868 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
9869 return RESULT_SUCCESS;
9871 if (!pris[span-1].pri) {
9872 ast_cli(fd, "No PRI running on span %d\n", span);
9873 return RESULT_SUCCESS;
9875 for (x = 0; x < NUM_DCHANS; x++) {
9876 if (pris[span-1].dchans[x])
9877 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
9878 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
9879 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
9881 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
9882 return RESULT_SUCCESS;
9885 static void build_status(char *s, size_t len, int status, int active)
9887 if (!s || len < 1) {
9888 return;
9890 s[0] = '\0';
9891 if (status & DCHAN_PROVISIONED)
9892 strncat(s, "Provisioned, ", len - strlen(s) - 1);
9893 if (!(status & DCHAN_NOTINALARM))
9894 strncat(s, "In Alarm, ", len - strlen(s) - 1);
9895 if (status & DCHAN_UP)
9896 strncat(s, "Up", len - strlen(s) - 1);
9897 else
9898 strncat(s, "Down", len - strlen(s) - 1);
9899 if (active)
9900 strncat(s, ", Active", len - strlen(s) - 1);
9901 else
9902 strncat(s, ", Standby", len - strlen(s) - 1);
9903 s[len - 1] = '\0';
9906 static int handle_pri_show_spans(int fd, int argc, char *argv[])
9908 int span;
9909 int x;
9910 char status[256];
9911 if (argc != 3)
9912 return RESULT_SHOWUSAGE;
9914 for (span = 0; span < NUM_SPANS; span++) {
9915 if (pris[span].pri) {
9916 for (x = 0; x < NUM_DCHANS; x++) {
9917 if (pris[span].dchannels[x]) {
9918 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
9919 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
9924 return RESULT_SUCCESS;
9927 static int handle_pri_show_span(int fd, int argc, char *argv[])
9929 int span;
9930 int x;
9931 char status[256];
9932 if (argc < 4)
9933 return RESULT_SHOWUSAGE;
9934 span = atoi(argv[3]);
9935 if ((span < 1) || (span > NUM_SPANS)) {
9936 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
9937 return RESULT_SUCCESS;
9939 if (!pris[span-1].pri) {
9940 ast_cli(fd, "No PRI running on span %d\n", span);
9941 return RESULT_SUCCESS;
9943 for (x = 0; x < NUM_DCHANS; x++) {
9944 if (pris[span-1].dchannels[x]) {
9945 #ifdef PRI_DUMP_INFO_STR
9946 char *info_str = NULL;
9947 #endif
9948 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
9949 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
9950 ast_cli(fd, "Status: %s\n", status);
9951 #ifdef PRI_DUMP_INFO_STR
9952 info_str = pri_dump_info_str(pris[span-1].pri);
9953 if (info_str) {
9954 ast_cli(fd, "%s", info_str);
9955 free(info_str);
9957 #else
9958 pri_dump_info(pris[span-1].pri);
9959 #endif
9960 ast_cli(fd, "\n");
9963 return RESULT_SUCCESS;
9966 static int handle_pri_show_debug(int fd, int argc, char *argv[])
9968 int x;
9969 int span;
9970 int count=0;
9971 int debug=0;
9973 for (span = 0; span < NUM_SPANS; span++) {
9974 if (pris[span].pri) {
9975 for (x = 0; x < NUM_DCHANS; x++) {
9976 debug = 0;
9977 if (pris[span].dchans[x]) {
9978 debug = pri_get_debug(pris[span].dchans[x]);
9979 ast_cli(fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
9980 count++;
9986 ast_mutex_lock(&pridebugfdlock);
9987 if (pridebugfd >= 0)
9988 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
9989 ast_mutex_unlock(&pridebugfdlock);
9991 if (!count)
9992 ast_cli(fd, "No debug set or no PRI running\n");
9993 return RESULT_SUCCESS;
9996 static const char pri_debug_help[] =
9997 "Usage: pri debug span <span>\n"
9998 " Enables debugging on a given PRI span\n";
10000 static const char pri_no_debug_help[] =
10001 "Usage: pri no debug span <span>\n"
10002 " Disables debugging on a given PRI span\n";
10004 static const char pri_really_debug_help[] =
10005 "Usage: pri intensive debug span <span>\n"
10006 " Enables debugging down to the Q.921 level\n";
10008 static const char pri_show_span_help[] =
10009 "Usage: pri show span <span>\n"
10010 " Displays PRI Information on a given PRI span\n";
10012 static const char pri_show_spans_help[] =
10013 "Usage: pri show spans\n"
10014 " Displays PRI Information\n";
10016 static struct ast_cli_entry dahdi_pri_cli[] = {
10017 { { "pri", "debug", "span", NULL },
10018 handle_pri_debug, "Enables PRI debugging on a span",
10019 pri_debug_help, complete_span_4 },
10021 { { "pri", "no", "debug", "span", NULL },
10022 handle_pri_no_debug, "Disables PRI debugging on a span",
10023 pri_no_debug_help, complete_span_5 },
10025 { { "pri", "intense", "debug", "span", NULL },
10026 handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
10027 pri_really_debug_help, complete_span_5 },
10029 { { "pri", "show", "spans", NULL },
10030 handle_pri_show_spans, "Displays PRI Information",
10031 pri_show_spans_help },
10033 { { "pri", "show", "span", NULL },
10034 handle_pri_show_span, "Displays PRI Information",
10035 pri_show_span_help, complete_span_4 },
10037 { { "pri", "show", "debug", NULL },
10038 handle_pri_show_debug, "Displays current PRI debug settings" },
10040 { { "pri", "set", "debug", "file", NULL },
10041 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
10043 { { "pri", "unset", "debug", "file", NULL },
10044 handle_pri_set_debug_file, "Ends PRI debug output to file" },
10046 #ifdef HAVE_PRI_VERSION
10047 { { "pri", "show", "version", NULL },
10048 handle_pri_version, "Displays version of libpri" },
10049 #endif
10052 #endif /* HAVE_PRI */
10054 static int dahdi_destroy_channel(int fd, int argc, char **argv)
10056 int channel;
10058 if (argc != 4)
10059 return RESULT_SHOWUSAGE;
10061 channel = atoi(argv[3]);
10063 return dahdi_destroy_channel_bynum(channel);
10066 static void dahdi_softhangup_all(void)
10068 struct dahdi_pvt *p;
10069 retry:
10070 ast_mutex_lock(&iflock);
10071 for (p = iflist; p; p = p->next) {
10072 ast_mutex_lock(&p->lock);
10073 if (p->owner && !p->restartpending) {
10074 if (ast_channel_trylock(p->owner)) {
10075 if (option_debug > 2)
10076 ast_verbose("Avoiding deadlock\n");
10077 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
10078 ast_mutex_unlock(&p->lock);
10079 ast_mutex_unlock(&iflock);
10080 goto retry;
10082 if (option_debug > 2)
10083 ast_verbose("Softhanging up on %s\n", p->owner->name);
10084 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
10085 p->restartpending = 1;
10086 num_restart_pending++;
10087 ast_channel_unlock(p->owner);
10089 ast_mutex_unlock(&p->lock);
10091 ast_mutex_unlock(&iflock);
10094 static int setup_dahdi(int reload);
10095 static int dahdi_restart(void)
10097 #if defined(HAVE_PRI)
10098 int i, j;
10099 #endif
10100 int cancel_code;
10101 struct dahdi_pvt *p;
10103 ast_mutex_lock(&restart_lock);
10105 if (option_verbose)
10106 ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
10107 dahdi_softhangup_all();
10108 if (option_verbose > 3)
10109 ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
10111 #if defined(HAVE_PRI)
10112 for (i = 0; i < NUM_SPANS; i++) {
10113 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
10114 cancel_code = pthread_cancel(pris[i].master);
10115 pthread_kill(pris[i].master, SIGURG);
10116 if (option_debug > 3)
10117 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
10118 pthread_join(pris[i].master, NULL);
10119 if (option_debug > 3)
10120 ast_verbose("Joined thread of span %d\n", i);
10123 #endif
10125 ast_mutex_lock(&monlock);
10126 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10127 cancel_code = pthread_cancel(monitor_thread);
10128 pthread_kill(monitor_thread, SIGURG);
10129 if (option_debug > 3)
10130 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
10131 pthread_join(monitor_thread, NULL);
10132 if (option_debug > 3)
10133 ast_verbose("Joined monitor thread\n");
10135 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
10137 ast_mutex_lock(&ss_thread_lock);
10138 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
10139 int x = DAHDI_FLASH;
10140 if (option_debug > 2)
10141 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
10143 for (p = iflist; p; p = p->next) {
10144 if (p->owner)
10145 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
10147 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
10150 /* ensure any created channels before monitor threads were stopped are hungup */
10151 dahdi_softhangup_all();
10152 if (option_verbose > 3)
10153 ast_verbose("Final softhangup of all DAHDI channels complete.\n");
10154 destroy_all_channels();
10155 if (option_debug)
10156 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
10158 ast_mutex_unlock(&monlock);
10160 #ifdef HAVE_PRI
10161 for (i = 0; i < NUM_SPANS; i++) {
10162 for (j = 0; j < NUM_DCHANS; j++)
10163 dahdi_close_pri_fd(&(pris[i]), j);
10166 memset(pris, 0, sizeof(pris));
10167 for (i = 0; i < NUM_SPANS; i++) {
10168 ast_mutex_init(&pris[i].lock);
10169 pris[i].offset = -1;
10170 pris[i].master = AST_PTHREADT_NULL;
10171 for (j = 0; j < NUM_DCHANS; j++)
10172 pris[i].fds[j] = -1;
10174 pri_set_error(dahdi_pri_error);
10175 pri_set_message(dahdi_pri_message);
10176 #endif
10178 if (setup_dahdi(2) != 0) {
10179 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
10180 ast_mutex_unlock(&ss_thread_lock);
10181 return 1;
10183 ast_mutex_unlock(&ss_thread_lock);
10184 ast_mutex_unlock(&restart_lock);
10185 return 0;
10188 static int dahdi_restart_cmd(int fd, int argc, char **argv)
10190 if (argc != 2) {
10191 return RESULT_SHOWUSAGE;
10194 if (dahdi_restart() != 0)
10195 return RESULT_FAILURE;
10196 return RESULT_SUCCESS;
10199 static int dahdi_show_channels(int fd, int argc, char **argv)
10201 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10202 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10203 struct dahdi_pvt *tmp = NULL;
10204 char tmps[20] = "";
10205 ast_mutex_t *lock;
10206 struct dahdi_pvt *start;
10207 #ifdef HAVE_PRI
10208 int trunkgroup;
10209 struct dahdi_pri *pri = NULL;
10210 int x;
10211 #endif
10213 lock = &iflock;
10214 start = iflist;
10216 #ifdef HAVE_PRI
10217 if (argc == 4) {
10218 if ((trunkgroup = atoi(argv[3])) < 1)
10219 return RESULT_SHOWUSAGE;
10220 for (x = 0; x < NUM_SPANS; x++) {
10221 if (pris[x].trunkgroup == trunkgroup) {
10222 pri = pris + x;
10223 break;
10226 if (pri) {
10227 start = pri->crvs;
10228 lock = &pri->lock;
10229 } else {
10230 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10231 return RESULT_FAILURE;
10233 } else
10234 #endif
10235 if (argc != 3)
10236 return RESULT_SHOWUSAGE;
10238 ast_mutex_lock(lock);
10239 #ifdef HAVE_PRI
10240 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
10241 #else
10242 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
10243 #endif
10245 tmp = start;
10246 while (tmp) {
10247 if (tmp->channel > 0) {
10248 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
10249 } else
10250 ast_copy_string(tmps, "pseudo", sizeof(tmps));
10251 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
10252 tmp = tmp->next;
10254 ast_mutex_unlock(lock);
10255 return RESULT_SUCCESS;
10256 #undef FORMAT
10257 #undef FORMAT2
10260 static int dahdi_show_channel(int fd, int argc, char **argv)
10262 int channel;
10263 struct dahdi_pvt *tmp = NULL;
10264 struct dahdi_confinfo ci;
10265 struct dahdi_params ps;
10266 int x;
10267 ast_mutex_t *lock;
10268 struct dahdi_pvt *start;
10269 #ifdef HAVE_PRI
10270 char *c;
10271 int trunkgroup;
10272 struct dahdi_pri *pri=NULL;
10273 #endif
10275 lock = &iflock;
10276 start = iflist;
10278 if (argc != 4)
10279 return RESULT_SHOWUSAGE;
10280 #ifdef HAVE_PRI
10281 if ((c = strchr(argv[3], ':'))) {
10282 if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
10283 return RESULT_SHOWUSAGE;
10284 if ((trunkgroup < 1) || (channel < 1))
10285 return RESULT_SHOWUSAGE;
10286 for (x = 0; x < NUM_SPANS; x++) {
10287 if (pris[x].trunkgroup == trunkgroup) {
10288 pri = pris + x;
10289 break;
10292 if (pri) {
10293 start = pri->crvs;
10294 lock = &pri->lock;
10295 } else {
10296 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10297 return RESULT_FAILURE;
10299 } else
10300 #endif
10301 channel = atoi(argv[3]);
10303 ast_mutex_lock(lock);
10304 tmp = start;
10305 while (tmp) {
10306 if (tmp->channel == channel) {
10307 #ifdef HAVE_PRI
10308 if (pri)
10309 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
10310 else
10311 #endif
10312 ast_cli(fd, "Channel: %d\n", tmp->channel);
10313 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
10314 ast_cli(fd, "Span: %d\n", tmp->span);
10315 ast_cli(fd, "Extension: %s\n", tmp->exten);
10316 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
10317 ast_cli(fd, "Context: %s\n", tmp->context);
10318 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
10319 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
10320 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
10321 ast_cli(fd, "Destroy: %d\n", tmp->destroy);
10322 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
10323 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
10324 ast_cli(fd, "Radio: %d\n", tmp->radio);
10325 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
10326 ast_cli(fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
10327 ast_cli(fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? tmp->subs[SUB_CALLWAIT].owner->name : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
10328 ast_cli(fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? tmp->subs[SUB_THREEWAY].owner->name : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
10329 ast_cli(fd, "Confno: %d\n", tmp->confno);
10330 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
10331 ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
10332 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
10333 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
10334 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
10335 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
10336 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
10337 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
10338 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
10339 if (tmp->master)
10340 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
10341 for (x = 0; x < MAX_SLAVES; x++) {
10342 if (tmp->slaves[x])
10343 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
10345 #ifdef HAVE_PRI
10346 if (tmp->pri) {
10347 ast_cli(fd, "PRI Flags: ");
10348 if (tmp->resetting)
10349 ast_cli(fd, "Resetting ");
10350 if (tmp->call)
10351 ast_cli(fd, "Call ");
10352 if (tmp->bearer)
10353 ast_cli(fd, "Bearer ");
10354 ast_cli(fd, "\n");
10355 if (tmp->logicalspan)
10356 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
10357 else
10358 ast_cli(fd, "PRI Logical Span: Implicit\n");
10361 #endif
10362 memset(&ci, 0, sizeof(ci));
10363 ps.channo = tmp->channel;
10364 if (tmp->subs[SUB_REAL].dfd > -1) {
10365 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
10366 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
10368 #ifdef DAHDI_GETCONFMUTE
10369 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
10370 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
10372 #endif
10373 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
10374 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
10375 } else {
10376 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
10379 ast_mutex_unlock(lock);
10380 return RESULT_SUCCESS;
10382 tmp = tmp->next;
10385 ast_cli(fd, "Unable to find given channel %d\n", channel);
10386 ast_mutex_unlock(lock);
10387 return RESULT_FAILURE;
10390 static char dahdi_show_cadences_usage[] =
10391 "Usage: dahdi show cadences\n"
10392 " Shows all cadences currently defined\n";
10394 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
10396 int i, j;
10397 for (i = 0; i < num_cadence; i++) {
10398 char output[1024];
10399 char tmp[16], tmp2[64];
10400 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
10401 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
10403 for (j = 0; j < 16; j++) {
10404 if (cadences[i].ringcadence[j] == 0)
10405 break;
10406 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10407 if (cidrings[i] * 2 - 1 == j)
10408 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10409 else
10410 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10411 if (j != 0)
10412 strncat(output, ",", sizeof(output) - strlen(output) - 1);
10413 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10415 ast_cli(fd,"%s\n",output);
10417 return 0;
10420 /* Based on irqmiss.c */
10421 static int dahdi_show_status(int fd, int argc, char *argv[]) {
10422 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10423 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10425 int span;
10426 int res;
10427 char alarms[50];
10429 int ctl;
10430 struct dahdi_spaninfo s;
10432 #ifdef HAVE_ZAPTEL
10433 if ((ctl = open("/dev/zap/ctl", O_RDWR)) < 0) {
10434 ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
10435 ast_cli(fd, "No Zaptel interface found.\n");
10436 return RESULT_FAILURE;
10438 #else
10439 if ((ctl = open("/dev/dahdi/ctl", O_RDWR)) < 0) {
10440 ast_log(LOG_WARNING, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
10441 ast_cli(fd, "No DAHDI interface found.\n");
10442 return RESULT_FAILURE;
10444 #endif
10445 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10447 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
10448 s.spanno = span;
10449 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
10450 if (res) {
10451 continue;
10453 alarms[0] = '\0';
10454 if (s.alarms > 0) {
10455 if (s.alarms & DAHDI_ALARM_BLUE)
10456 strcat(alarms, "BLU/");
10457 if (s.alarms & DAHDI_ALARM_YELLOW)
10458 strcat(alarms, "YEL/");
10459 if (s.alarms & DAHDI_ALARM_RED)
10460 strcat(alarms, "RED/");
10461 if (s.alarms & DAHDI_ALARM_LOOPBACK)
10462 strcat(alarms, "LB/");
10463 if (s.alarms & DAHDI_ALARM_RECOVER)
10464 strcat(alarms, "REC/");
10465 if (s.alarms & DAHDI_ALARM_NOTOPEN)
10466 strcat(alarms, "NOP/");
10467 if (!strlen(alarms))
10468 strcat(alarms, "UUU/");
10469 if (strlen(alarms)) {
10470 /* Strip trailing / */
10471 alarms[strlen(alarms) - 1] = '\0';
10473 } else {
10474 if (s.numchans)
10475 strcpy(alarms, "OK");
10476 else
10477 strcpy(alarms, "UNCONFIGURED");
10480 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10482 close(ctl);
10484 return RESULT_SUCCESS;
10485 #undef FORMAT
10486 #undef FORMAT2
10489 static char show_channels_usage[] =
10490 "Usage: dahdi show channels\n"
10491 " Shows a list of available channels\n";
10493 static char show_channel_usage[] =
10494 "Usage: dahdi show channel <chan num>\n"
10495 " Detailed information about a given channel\n";
10497 static char dahdi_show_status_usage[] =
10498 "Usage: dahdi show status\n"
10499 " Shows a list of DAHDI cards with status\n";
10501 static char destroy_channel_usage[] =
10502 "Usage: dahdi destroy channel <chan num>\n"
10503 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
10505 static char dahdi_restart_usage[] =
10506 "Usage: dahdi restart\n"
10507 " Restarts the DAHDI channels: destroys them all and then\n"
10508 " re-reads them from chan_dahdi.conf.\n"
10509 " Note that this will STOP any running CALL on DAHDI channels.\n"
10512 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
10513 { "zap", "show", "cadences", NULL },
10514 handle_dahdi_show_cadences, NULL,
10515 NULL };
10517 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
10518 { "zap", "show", "channels", NULL },
10519 dahdi_show_channels, NULL,
10520 NULL };
10522 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
10523 { "zap", "show", "channel", NULL },
10524 dahdi_show_channel, NULL,
10525 NULL };
10527 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
10528 { "zap", "destroy", "channel", NULL },
10529 dahdi_destroy_channel, NULL,
10530 NULL };
10532 static struct ast_cli_entry cli_zap_restart_deprecated = {
10533 { "zap", "restart", NULL },
10534 dahdi_restart_cmd, NULL,
10535 NULL };
10537 static struct ast_cli_entry cli_zap_show_status_deprecated = {
10538 { "zap", "show", "status", NULL },
10539 dahdi_show_status, NULL,
10540 NULL };
10542 static struct ast_cli_entry dahdi_cli[] = {
10543 { { "dahdi", "show", "cadences", NULL },
10544 handle_dahdi_show_cadences, "List cadences",
10545 dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
10547 { { "dahdi", "show", "channels", NULL},
10548 dahdi_show_channels, "Show active DAHDI channels",
10549 show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
10551 { { "dahdi", "show", "channel", NULL},
10552 dahdi_show_channel, "Show information on a channel",
10553 show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
10555 { { "dahdi", "destroy", "channel", NULL},
10556 dahdi_destroy_channel, "Destroy a channel",
10557 destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
10559 { { "dahdi", "restart", NULL},
10560 dahdi_restart_cmd, "Fully restart DAHDI channels",
10561 dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
10563 { { "dahdi", "show", "status", NULL},
10564 dahdi_show_status, "Show all DAHDI cards status",
10565 dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
10568 #define TRANSFER 0
10569 #define HANGUP 1
10571 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
10573 if (p) {
10574 switch (mode) {
10575 case TRANSFER:
10576 p->fake_event = DAHDI_EVENT_WINKFLASH;
10577 break;
10578 case HANGUP:
10579 p->fake_event = DAHDI_EVENT_ONHOOK;
10580 break;
10581 default:
10582 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
10585 return 0;
10587 static struct dahdi_pvt *find_channel(int channel)
10589 struct dahdi_pvt *p = iflist;
10590 while (p) {
10591 if (p->channel == channel) {
10592 break;
10594 p = p->next;
10596 return p;
10599 #define local_astman_ack(s, m, msg, zap) do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0)
10600 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
10602 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
10604 struct dahdi_pvt *p = NULL;
10605 const char *channel = local_astman_header(m, "Channel", zap_mode);
10607 if (ast_strlen_zero(channel)) {
10608 astman_send_error(s, m, "No channel specified");
10609 return 0;
10611 if (!(p = find_channel(atoi(channel)))) {
10612 astman_send_error(s, m, "No such channel");
10613 return 0;
10615 p->dnd = dnd;
10616 local_astman_ack(s, m, "DND", zap_mode);
10618 return 0;
10621 static int zap_action_dndon(struct mansession *s, const struct message *m)
10623 return __action_dnd(s, m, 1, 1);
10626 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
10628 return __action_dnd(s, m, 0, 1);
10631 static int zap_action_dndoff(struct mansession *s, const struct message *m)
10633 return __action_dnd(s, m, 1, 0);
10636 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
10638 return __action_dnd(s, m, 0, 0);
10641 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
10643 struct dahdi_pvt *p = NULL;
10644 const char *channel = local_astman_header(m, "Channel", zap_mode);
10646 if (ast_strlen_zero(channel)) {
10647 astman_send_error(s, m, "No channel specified");
10648 return 0;
10650 if (!(p = find_channel(atoi(channel)))) {
10651 astman_send_error(s, m, "No such channel");
10652 return 0;
10654 dahdi_fake_event(p,TRANSFER);
10655 local_astman_ack(s, m, "Transfer", zap_mode);
10657 return 0;
10660 static int zap_action_transfer(struct mansession *s, const struct message *m)
10662 return __action_transfer(s, m, 1);
10665 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
10667 return __action_transfer(s, m, 0);
10670 static int __action_transferhangup(struct mansession *s, const struct message *m, int zap_mode)
10672 struct dahdi_pvt *p = NULL;
10673 const char *channel = local_astman_header(m, "Channel", zap_mode);
10675 if (ast_strlen_zero(channel)) {
10676 astman_send_error(s, m, "No channel specified");
10677 return 0;
10679 if (!(p = find_channel(atoi(channel)))) {
10680 astman_send_error(s, m, "No such channel");
10681 return 0;
10683 dahdi_fake_event(p, HANGUP);
10684 local_astman_ack(s, m, "Hangup", zap_mode);
10685 return 0;
10688 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
10690 return __action_transferhangup(s, m, 1);
10693 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
10695 return __action_transferhangup(s, m, 0);
10698 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
10700 struct dahdi_pvt *p = NULL;
10701 const char *channel = local_astman_header(m, "Channel", zap_mode);
10702 const char *number = astman_get_header(m, "Number");
10703 int i;
10705 if (ast_strlen_zero(channel)) {
10706 astman_send_error(s, m, "No channel specified");
10707 return 0;
10709 if (ast_strlen_zero(number)) {
10710 astman_send_error(s, m, "No number specified");
10711 return 0;
10713 if (!(p = find_channel(atoi(channel)))) {
10714 astman_send_error(s, m, "No such channel");
10715 return 0;
10717 if (!p->owner) {
10718 astman_send_error(s, m, "Channel does not have an owner");
10719 return 0;
10721 for (i = 0; i < strlen(number); i++) {
10722 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
10724 dahdi_queue_frame(p, &f, NULL);
10726 local_astman_ack(s, m, "DialOffHook", zap_mode);
10728 return 0;
10731 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
10733 return __action_dialoffhook(s, m, 1);
10736 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
10738 return __action_dialoffhook(s, m, 0);
10741 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
10743 struct dahdi_pvt *tmp = NULL;
10744 const char *id = astman_get_header(m, "ActionID");
10745 char idText[256] = "";
10747 local_astman_ack(s, m, " channel status will follow", zap_mode);
10748 if (!ast_strlen_zero(id))
10749 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
10751 ast_mutex_lock(&iflock);
10753 tmp = iflist;
10754 while (tmp) {
10755 if (tmp->channel > 0) {
10756 int alarm = get_alarms(tmp);
10757 astman_append(s,
10758 "Event: %sShowChannels\r\n"
10759 "Channel: %d\r\n"
10760 "Signalling: %s\r\n"
10761 "Context: %s\r\n"
10762 "DND: %s\r\n"
10763 "Alarm: %s\r\n"
10764 "%s"
10765 "\r\n",
10766 dahdi_chan_name,
10767 tmp->channel, sig2str(tmp->sig), tmp->context,
10768 tmp->dnd ? "Enabled" : "Disabled",
10769 alarm2str(alarm), idText);
10772 tmp = tmp->next;
10775 ast_mutex_unlock(&iflock);
10777 astman_append(s,
10778 "Event: %sShowChannelsComplete\r\n"
10779 "%s"
10780 "\r\n",
10781 dahdi_chan_name,
10782 idText);
10783 return 0;
10786 static int zap_action_showchannels(struct mansession *s, const struct message *m)
10788 return __action_showchannels(s, m, 1);
10791 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
10793 return __action_showchannels(s, m, 0);
10796 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
10798 if (dahdi_restart() != 0) {
10799 if (zap_mode) {
10800 astman_send_error(s, m, "Failed to restart Zap");
10801 } else {
10802 astman_send_error(s, m, "Failed to restart DAHDI");
10804 return 1;
10806 local_astman_ack(s, m, "Restart: Success", zap_mode);
10807 return 0;
10810 static int zap_action_restart(struct mansession *s, const struct message *m)
10812 return __action_restart(s, m, 1);
10815 static int dahdi_action_restart(struct mansession *s, const struct message *m)
10817 return __action_restart(s, m, 0);
10820 #define local_astman_unregister(a) do { \
10821 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
10822 ast_manager_unregister("DAHDI" a); \
10824 ast_manager_unregister("Zap" a); \
10825 } while (0)
10827 static int __unload_module(void)
10829 struct dahdi_pvt *p;
10831 #ifdef HAVE_PRI
10832 int i, j;
10833 for (i = 0; i < NUM_SPANS; i++) {
10834 if (pris[i].master != AST_PTHREADT_NULL)
10835 pthread_cancel(pris[i].master);
10837 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
10839 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
10840 ast_unregister_application(dahdi_send_keypad_facility_app);
10842 ast_unregister_application(zap_send_keypad_facility_app);
10843 #endif
10844 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
10845 local_astman_unregister("DialOffHook");
10846 local_astman_unregister("Hangup");
10847 local_astman_unregister("Transfer");
10848 local_astman_unregister("DNDoff");
10849 local_astman_unregister("DNDon");
10850 local_astman_unregister("ShowChannels");
10851 local_astman_unregister("Restart");
10852 ast_channel_unregister(chan_tech);
10853 ast_mutex_lock(&iflock);
10854 /* Hangup all interfaces if they have an owner */
10855 p = iflist;
10856 while (p) {
10857 if (p->owner)
10858 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
10859 p = p->next;
10861 ast_mutex_unlock(&iflock);
10862 ast_mutex_lock(&monlock);
10863 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10864 pthread_cancel(monitor_thread);
10865 pthread_kill(monitor_thread, SIGURG);
10866 pthread_join(monitor_thread, NULL);
10868 monitor_thread = AST_PTHREADT_STOP;
10869 ast_mutex_unlock(&monlock);
10871 destroy_all_channels();
10872 #ifdef HAVE_PRI
10873 for (i = 0; i < NUM_SPANS; i++) {
10874 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
10875 pthread_join(pris[i].master, NULL);
10876 for (j = 0; j < NUM_DCHANS; j++) {
10877 dahdi_close_pri_fd(&(pris[i]), j);
10880 #endif
10881 ast_cond_destroy(&ss_thread_complete);
10882 return 0;
10885 static int unload_module(void)
10887 #ifdef HAVE_PRI
10888 int y;
10889 for (y = 0; y < NUM_SPANS; y++)
10890 ast_mutex_destroy(&pris[y].lock);
10891 #endif
10892 return __unload_module();
10895 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
10897 char *c, *chan;
10898 int x, start, finish;
10899 struct dahdi_pvt *tmp;
10900 #ifdef HAVE_PRI
10901 struct dahdi_pri *pri;
10902 int trunkgroup, y;
10903 #endif
10905 if ((reload == 0) && (conf->chan.sig < 0)) {
10906 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
10907 return -1;
10910 c = ast_strdupa(value);
10912 #ifdef HAVE_PRI
10913 pri = NULL;
10914 if (iscrv) {
10915 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
10916 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
10917 return -1;
10919 if (trunkgroup < 1) {
10920 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
10921 return -1;
10923 c += y;
10924 for (y = 0; y < NUM_SPANS; y++) {
10925 if (pris[y].trunkgroup == trunkgroup) {
10926 pri = pris + y;
10927 break;
10930 if (!pri) {
10931 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
10932 return -1;
10935 #endif
10937 while ((chan = strsep(&c, ","))) {
10938 if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
10939 /* Range */
10940 } else if (sscanf(chan, "%d", &start)) {
10941 /* Just one */
10942 finish = start;
10943 } else if (!strcasecmp(chan, "pseudo")) {
10944 finish = start = CHAN_PSEUDO;
10945 if (found_pseudo)
10946 *found_pseudo = 1;
10947 } else {
10948 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
10949 return -1;
10951 if (finish < start) {
10952 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
10953 x = finish;
10954 finish = start;
10955 start = x;
10958 for (x = start; x <= finish; x++) {
10959 #ifdef HAVE_PRI
10960 tmp = mkintf(x, conf, pri, reload);
10961 #else
10962 tmp = mkintf(x, conf, NULL, reload);
10963 #endif
10965 if (tmp) {
10966 if (option_verbose > 2) {
10967 #ifdef HAVE_PRI
10968 if (pri)
10969 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
10970 else
10971 #endif
10972 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
10974 } else {
10975 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
10976 (reload == 1) ? "reconfigure" : "register", value);
10977 return -1;
10982 return 0;
10985 /** The length of the parameters list of 'dahdichan'.
10986 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
10987 #define MAX_CHANLIST_LEN 80
10988 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
10990 struct dahdi_pvt *tmp;
10991 int y;
10992 int found_pseudo = 0;
10993 char dahdichan[MAX_CHANLIST_LEN] = {};
10995 for (; v; v = v->next) {
10996 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
10997 continue;
10999 /* Create the interface list */
11000 if (!strcasecmp(v->name, "channel")
11001 #ifdef HAVE_PRI
11002 || !strcasecmp(v->name, "crv")
11003 #endif
11005 int iscrv;
11006 if (skipchannels)
11007 continue;
11008 iscrv = !strcasecmp(v->name, "crv");
11009 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
11010 return -1;
11011 } else if (!strcasecmp(v->name, "buffers")) {
11012 int res;
11013 char policy[8] = "";
11014 res = sscanf(v->value, "%d,%s", &confp->chan.buf_no, policy);
11015 if (res != 2) {
11016 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
11017 confp->chan.buf_no = numbufs;
11018 continue;
11020 if (confp->chan.buf_no < 0)
11021 confp->chan.buf_no = numbufs;
11022 if (!strcasecmp(policy, "full")) {
11023 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
11024 } else if (!strcasecmp(policy, "half")) {
11025 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE /* TODO: change to HALF_FULL */;
11026 } else if (!strcasecmp(policy, "immediate")) {
11027 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
11028 } else {
11029 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
11031 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
11032 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
11033 if (v->name[0] == 'z' || v->name[0] == 'Z') {
11034 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
11036 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
11037 if (ast_true(v->value))
11038 confp->chan.usedistinctiveringdetection = 1;
11039 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
11040 if (ast_true(v->value))
11041 distinctiveringaftercid = 1;
11042 } else if (!strcasecmp(v->name, "dring1context")) {
11043 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
11044 } else if (!strcasecmp(v->name, "dring2context")) {
11045 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
11046 } else if (!strcasecmp(v->name, "dring3context")) {
11047 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
11048 } else if (!strcasecmp(v->name, "dring1")) {
11049 sscanf(v->value, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
11050 } else if (!strcasecmp(v->name, "dring2")) {
11051 sscanf(v->value, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
11052 } else if (!strcasecmp(v->name, "dring3")) {
11053 sscanf(v->value, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
11054 } else if (!strcasecmp(v->name, "usecallerid")) {
11055 confp->chan.use_callerid = ast_true(v->value);
11056 } else if (!strcasecmp(v->name, "cidsignalling")) {
11057 if (!strcasecmp(v->value, "bell"))
11058 confp->chan.cid_signalling = CID_SIG_BELL;
11059 else if (!strcasecmp(v->value, "v23"))
11060 confp->chan.cid_signalling = CID_SIG_V23;
11061 else if (!strcasecmp(v->value, "dtmf"))
11062 confp->chan.cid_signalling = CID_SIG_DTMF;
11063 else if (!strcasecmp(v->value, "smdi"))
11064 confp->chan.cid_signalling = CID_SIG_SMDI;
11065 else if (!strcasecmp(v->value, "v23_jp"))
11066 confp->chan.cid_signalling = CID_SIG_V23_JP;
11067 else if (ast_true(v->value))
11068 confp->chan.cid_signalling = CID_SIG_BELL;
11069 } else if (!strcasecmp(v->name, "cidstart")) {
11070 if (!strcasecmp(v->value, "ring"))
11071 confp->chan.cid_start = CID_START_RING;
11072 else if (!strcasecmp(v->value, "polarity"))
11073 confp->chan.cid_start = CID_START_POLARITY;
11074 else if (ast_true(v->value))
11075 confp->chan.cid_start = CID_START_RING;
11076 } else if (!strcasecmp(v->name, "threewaycalling")) {
11077 confp->chan.threewaycalling = ast_true(v->value);
11078 } else if (!strcasecmp(v->name, "cancallforward")) {
11079 confp->chan.cancallforward = ast_true(v->value);
11080 } else if (!strcasecmp(v->name, "relaxdtmf")) {
11081 if (ast_true(v->value))
11082 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
11083 else
11084 confp->chan.dtmfrelax = 0;
11085 } else if (!strcasecmp(v->name, "mailbox")) {
11086 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
11087 } else if (!strcasecmp(v->name, "hasvoicemail")) {
11088 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
11089 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
11091 } else if (!strcasecmp(v->name, "adsi")) {
11092 confp->chan.adsi = ast_true(v->value);
11093 } else if (!strcasecmp(v->name, "usesmdi")) {
11094 confp->chan.use_smdi = ast_true(v->value);
11095 } else if (!strcasecmp(v->name, "smdiport")) {
11096 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
11097 } else if (!strcasecmp(v->name, "transfer")) {
11098 confp->chan.transfer = ast_true(v->value);
11099 } else if (!strcasecmp(v->name, "canpark")) {
11100 confp->chan.canpark = ast_true(v->value);
11101 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
11102 confp->chan.echocanbridged = ast_true(v->value);
11103 } else if (!strcasecmp(v->name, "busydetect")) {
11104 confp->chan.busydetect = ast_true(v->value);
11105 } else if (!strcasecmp(v->name, "busycount")) {
11106 confp->chan.busycount = atoi(v->value);
11107 } else if (!strcasecmp(v->name, "busypattern")) {
11108 if (sscanf(v->value, "%d,%d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
11109 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength\n");
11111 } else if (!strcasecmp(v->name, "callprogress")) {
11112 if (ast_true(v->value))
11113 confp->chan.callprogress |= 1;
11114 else
11115 confp->chan.callprogress &= ~1;
11116 } else if (!strcasecmp(v->name, "faxdetect")) {
11117 if (!strcasecmp(v->value, "incoming")) {
11118 confp->chan.callprogress |= 4;
11119 confp->chan.callprogress &= ~2;
11120 } else if (!strcasecmp(v->value, "outgoing")) {
11121 confp->chan.callprogress &= ~4;
11122 confp->chan.callprogress |= 2;
11123 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
11124 confp->chan.callprogress |= 6;
11125 else
11126 confp->chan.callprogress &= ~6;
11127 } else if (!strcasecmp(v->name, "echocancel")) {
11128 if (!ast_strlen_zero(v->value)) {
11129 y = atoi(v->value);
11130 } else
11131 y = 0;
11132 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
11133 confp->chan.echocancel = y;
11134 else {
11135 confp->chan.echocancel = ast_true(v->value);
11136 if (confp->chan.echocancel)
11137 confp->chan.echocancel=128;
11139 } else if (!strcasecmp(v->name, "echotraining")) {
11140 if (sscanf(v->value, "%d", &y) == 1) {
11141 if ((y < 10) || (y > 4000)) {
11142 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);
11143 } else {
11144 confp->chan.echotraining = y;
11146 } else if (ast_true(v->value)) {
11147 confp->chan.echotraining = 400;
11148 } else
11149 confp->chan.echotraining = 0;
11150 } else if (!strcasecmp(v->name, "hidecallerid")) {
11151 confp->chan.hidecallerid = ast_true(v->value);
11152 } else if (!strcasecmp(v->name, "hidecalleridname")) {
11153 confp->chan.hidecalleridname = ast_true(v->value);
11154 } else if (!strcasecmp(v->name, "pulsedial")) {
11155 confp->chan.pulse = ast_true(v->value);
11156 } else if (!strcasecmp(v->name, "callreturn")) {
11157 confp->chan.callreturn = ast_true(v->value);
11158 } else if (!strcasecmp(v->name, "callwaiting")) {
11159 confp->chan.callwaiting = ast_true(v->value);
11160 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
11161 confp->chan.callwaitingcallerid = ast_true(v->value);
11162 } else if (!strcasecmp(v->name, "context")) {
11163 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
11164 } else if (!strcasecmp(v->name, "language")) {
11165 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
11166 } else if (!strcasecmp(v->name, "progzone")) {
11167 ast_copy_string(progzone, v->value, sizeof(progzone));
11168 } else if (!strcasecmp(v->name, "mohinterpret")
11169 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
11170 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
11171 } else if (!strcasecmp(v->name, "mohsuggest")) {
11172 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
11173 } else if (!strcasecmp(v->name, "stripmsd")) {
11174 confp->chan.stripmsd = atoi(v->value);
11175 } else if (!strcasecmp(v->name, "jitterbuffers")) {
11176 numbufs = atoi(v->value);
11177 } else if (!strcasecmp(v->name, "group")) {
11178 confp->chan.group = ast_get_group(v->value);
11179 } else if (!strcasecmp(v->name, "callgroup")) {
11180 confp->chan.callgroup = ast_get_group(v->value);
11181 } else if (!strcasecmp(v->name, "pickupgroup")) {
11182 confp->chan.pickupgroup = ast_get_group(v->value);
11183 } else if (!strcasecmp(v->name, "immediate")) {
11184 confp->chan.immediate = ast_true(v->value);
11185 } else if (!strcasecmp(v->name, "transfertobusy")) {
11186 confp->chan.transfertobusy = ast_true(v->value);
11187 } else if (!strcasecmp(v->name, "rxgain")) {
11188 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
11189 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
11191 } else if (!strcasecmp(v->name, "txgain")) {
11192 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
11193 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
11195 } else if (!strcasecmp(v->name, "tonezone")) {
11196 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
11197 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
11199 } else if (!strcasecmp(v->name, "callerid")) {
11200 if (!strcasecmp(v->value, "asreceived")) {
11201 confp->chan.cid_num[0] = '\0';
11202 confp->chan.cid_name[0] = '\0';
11203 } else {
11204 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
11206 } else if (!strcasecmp(v->name, "fullname")) {
11207 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
11208 } else if (!strcasecmp(v->name, "cid_number")) {
11209 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
11210 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
11211 confp->chan.dahditrcallerid = ast_true(v->value);
11212 if (strstr(v->name, "zap")) {
11213 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
11215 } else if (!strcasecmp(v->name, "restrictcid")) {
11216 confp->chan.restrictcid = ast_true(v->value);
11217 } else if (!strcasecmp(v->name, "usecallingpres")) {
11218 confp->chan.use_callingpres = ast_true(v->value);
11219 } else if (!strcasecmp(v->name, "accountcode")) {
11220 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
11221 } else if (!strcasecmp(v->name, "amaflags")) {
11222 y = ast_cdr_amaflags2int(v->value);
11223 if (y < 0)
11224 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
11225 else
11226 confp->chan.amaflags = y;
11227 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
11228 confp->chan.polarityonanswerdelay = atoi(v->value);
11229 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
11230 confp->chan.answeronpolarityswitch = ast_true(v->value);
11231 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
11232 confp->chan.hanguponpolarityswitch = ast_true(v->value);
11233 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
11234 confp->chan.sendcalleridafter = atoi(v->value);
11235 } else if (reload != 1){
11236 if (!strcasecmp(v->name, "signalling")) {
11237 confp->chan.outsigmod = -1;
11238 if (!strcasecmp(v->value, "em")) {
11239 confp->chan.sig = SIG_EM;
11240 } else if (!strcasecmp(v->value, "em_e1")) {
11241 confp->chan.sig = SIG_EM_E1;
11242 } else if (!strcasecmp(v->value, "em_w")) {
11243 confp->chan.sig = SIG_EMWINK;
11244 confp->chan.radio = 0;
11245 } else if (!strcasecmp(v->value, "fxs_ls")) {
11246 confp->chan.sig = SIG_FXSLS;
11247 confp->chan.radio = 0;
11248 } else if (!strcasecmp(v->value, "fxs_gs")) {
11249 confp->chan.sig = SIG_FXSGS;
11250 confp->chan.radio = 0;
11251 } else if (!strcasecmp(v->value, "fxs_ks")) {
11252 confp->chan.sig = SIG_FXSKS;
11253 confp->chan.radio = 0;
11254 } else if (!strcasecmp(v->value, "fxo_ls")) {
11255 confp->chan.sig = SIG_FXOLS;
11256 confp->chan.radio = 0;
11257 } else if (!strcasecmp(v->value, "fxo_gs")) {
11258 confp->chan.sig = SIG_FXOGS;
11259 confp->chan.radio = 0;
11260 } else if (!strcasecmp(v->value, "fxo_ks")) {
11261 confp->chan.sig = SIG_FXOKS;
11262 confp->chan.radio = 0;
11263 } else if (!strcasecmp(v->value, "fxs_rx")) {
11264 confp->chan.sig = SIG_FXSKS;
11265 confp->chan.radio = 1;
11266 } else if (!strcasecmp(v->value, "fxo_rx")) {
11267 confp->chan.sig = SIG_FXOLS;
11268 confp->chan.radio = 1;
11269 } else if (!strcasecmp(v->value, "fxs_tx")) {
11270 confp->chan.sig = SIG_FXSLS;
11271 confp->chan.radio = 1;
11272 } else if (!strcasecmp(v->value, "fxo_tx")) {
11273 confp->chan.sig = SIG_FXOGS;
11274 confp->chan.radio = 1;
11275 } else if (!strcasecmp(v->value, "em_rx")) {
11276 confp->chan.sig = SIG_EM;
11277 confp->chan.radio = 1;
11278 } else if (!strcasecmp(v->value, "em_tx")) {
11279 confp->chan.sig = SIG_EM;
11280 confp->chan.radio = 1;
11281 } else if (!strcasecmp(v->value, "em_rxtx")) {
11282 confp->chan.sig = SIG_EM;
11283 confp->chan.radio = 2;
11284 } else if (!strcasecmp(v->value, "em_txrx")) {
11285 confp->chan.sig = SIG_EM;
11286 confp->chan.radio = 2;
11287 } else if (!strcasecmp(v->value, "sf")) {
11288 confp->chan.sig = SIG_SF;
11289 confp->chan.radio = 0;
11290 } else if (!strcasecmp(v->value, "sf_w")) {
11291 confp->chan.sig = SIG_SFWINK;
11292 confp->chan.radio = 0;
11293 } else if (!strcasecmp(v->value, "sf_featd")) {
11294 confp->chan.sig = SIG_FEATD;
11295 confp->chan.radio = 0;
11296 } else if (!strcasecmp(v->value, "sf_featdmf")) {
11297 confp->chan.sig = SIG_FEATDMF;
11298 confp->chan.radio = 0;
11299 } else if (!strcasecmp(v->value, "sf_featb")) {
11300 confp->chan.sig = SIG_SF_FEATB;
11301 confp->chan.radio = 0;
11302 } else if (!strcasecmp(v->value, "sf")) {
11303 confp->chan.sig = SIG_SF;
11304 confp->chan.radio = 0;
11305 } else if (!strcasecmp(v->value, "sf_rx")) {
11306 confp->chan.sig = SIG_SF;
11307 confp->chan.radio = 1;
11308 } else if (!strcasecmp(v->value, "sf_tx")) {
11309 confp->chan.sig = SIG_SF;
11310 confp->chan.radio = 1;
11311 } else if (!strcasecmp(v->value, "sf_rxtx")) {
11312 confp->chan.sig = SIG_SF;
11313 confp->chan.radio = 2;
11314 } else if (!strcasecmp(v->value, "sf_txrx")) {
11315 confp->chan.sig = SIG_SF;
11316 confp->chan.radio = 2;
11317 } else if (!strcasecmp(v->value, "featd")) {
11318 confp->chan.sig = SIG_FEATD;
11319 confp->chan.radio = 0;
11320 } else if (!strcasecmp(v->value, "featdmf")) {
11321 confp->chan.sig = SIG_FEATDMF;
11322 confp->chan.radio = 0;
11323 } else if (!strcasecmp(v->value, "featdmf_ta")) {
11324 confp->chan.sig = SIG_FEATDMF_TA;
11325 confp->chan.radio = 0;
11326 } else if (!strcasecmp(v->value, "e911")) {
11327 confp->chan.sig = SIG_E911;
11328 confp->chan.radio = 0;
11329 } else if (!strcasecmp(v->value, "fgccama")) {
11330 confp->chan.sig = SIG_FGC_CAMA;
11331 confp->chan.radio = 0;
11332 } else if (!strcasecmp(v->value, "fgccamamf")) {
11333 confp->chan.sig = SIG_FGC_CAMAMF;
11334 confp->chan.radio = 0;
11335 } else if (!strcasecmp(v->value, "featb")) {
11336 confp->chan.sig = SIG_FEATB;
11337 confp->chan.radio = 0;
11338 #ifdef HAVE_PRI
11339 } else if (!strcasecmp(v->value, "pri_net")) {
11340 confp->chan.radio = 0;
11341 confp->chan.sig = SIG_PRI;
11342 confp->pri.nodetype = PRI_NETWORK;
11343 } else if (!strcasecmp(v->value, "pri_cpe")) {
11344 confp->chan.sig = SIG_PRI;
11345 confp->chan.radio = 0;
11346 confp->pri.nodetype = PRI_CPE;
11347 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
11348 confp->chan.sig = SIG_GR303FXOKS;
11349 confp->chan.radio = 0;
11350 confp->pri.nodetype = PRI_NETWORK;
11351 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
11352 confp->chan.sig = SIG_GR303FXSKS;
11353 confp->chan.radio = 0;
11354 confp->pri.nodetype = PRI_CPE;
11355 #endif
11356 } else {
11357 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11359 } else if (!strcasecmp(v->name, "outsignalling")) {
11360 if (!strcasecmp(v->value, "em")) {
11361 confp->chan.outsigmod = SIG_EM;
11362 } else if (!strcasecmp(v->value, "em_e1")) {
11363 confp->chan.outsigmod = SIG_EM_E1;
11364 } else if (!strcasecmp(v->value, "em_w")) {
11365 confp->chan.outsigmod = SIG_EMWINK;
11366 } else if (!strcasecmp(v->value, "sf")) {
11367 confp->chan.outsigmod = SIG_SF;
11368 } else if (!strcasecmp(v->value, "sf_w")) {
11369 confp->chan.outsigmod = SIG_SFWINK;
11370 } else if (!strcasecmp(v->value, "sf_featd")) {
11371 confp->chan.outsigmod = SIG_FEATD;
11372 } else if (!strcasecmp(v->value, "sf_featdmf")) {
11373 confp->chan.outsigmod = SIG_FEATDMF;
11374 } else if (!strcasecmp(v->value, "sf_featb")) {
11375 confp->chan.outsigmod = SIG_SF_FEATB;
11376 } else if (!strcasecmp(v->value, "sf")) {
11377 confp->chan.outsigmod = SIG_SF;
11378 } else if (!strcasecmp(v->value, "featd")) {
11379 confp->chan.outsigmod = SIG_FEATD;
11380 } else if (!strcasecmp(v->value, "featdmf")) {
11381 confp->chan.outsigmod = SIG_FEATDMF;
11382 } else if (!strcasecmp(v->value, "featdmf_ta")) {
11383 confp->chan.outsigmod = SIG_FEATDMF_TA;
11384 } else if (!strcasecmp(v->value, "e911")) {
11385 confp->chan.outsigmod = SIG_E911;
11386 } else if (!strcasecmp(v->value, "fgccama")) {
11387 confp->chan.outsigmod = SIG_FGC_CAMA;
11388 } else if (!strcasecmp(v->value, "fgccamamf")) {
11389 confp->chan.outsigmod = SIG_FGC_CAMAMF;
11390 } else if (!strcasecmp(v->value, "featb")) {
11391 confp->chan.outsigmod = SIG_FEATB;
11392 } else {
11393 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11395 #ifdef HAVE_PRI
11396 } else if (!strcasecmp(v->name, "pridialplan")) {
11397 if (!strcasecmp(v->value, "national")) {
11398 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
11399 } else if (!strcasecmp(v->value, "unknown")) {
11400 confp->pri.dialplan = PRI_UNKNOWN + 1;
11401 } else if (!strcasecmp(v->value, "private")) {
11402 confp->pri.dialplan = PRI_PRIVATE + 1;
11403 } else if (!strcasecmp(v->value, "international")) {
11404 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
11405 } else if (!strcasecmp(v->value, "local")) {
11406 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
11407 } else if (!strcasecmp(v->value, "dynamic")) {
11408 confp->pri.dialplan = -1;
11409 } else {
11410 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11412 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
11413 if (!strcasecmp(v->value, "national")) {
11414 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
11415 } else if (!strcasecmp(v->value, "unknown")) {
11416 confp->pri.localdialplan = PRI_UNKNOWN + 1;
11417 } else if (!strcasecmp(v->value, "private")) {
11418 confp->pri.localdialplan = PRI_PRIVATE + 1;
11419 } else if (!strcasecmp(v->value, "international")) {
11420 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
11421 } else if (!strcasecmp(v->value, "local")) {
11422 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
11423 } else if (!strcasecmp(v->value, "dynamic")) {
11424 confp->pri.localdialplan = -1;
11425 } else {
11426 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11428 } else if (!strcasecmp(v->name, "switchtype")) {
11429 if (!strcasecmp(v->value, "national"))
11430 confp->pri.switchtype = PRI_SWITCH_NI2;
11431 else if (!strcasecmp(v->value, "ni1"))
11432 confp->pri.switchtype = PRI_SWITCH_NI1;
11433 else if (!strcasecmp(v->value, "dms100"))
11434 confp->pri.switchtype = PRI_SWITCH_DMS100;
11435 else if (!strcasecmp(v->value, "4ess"))
11436 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
11437 else if (!strcasecmp(v->value, "5ess"))
11438 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
11439 else if (!strcasecmp(v->value, "euroisdn"))
11440 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
11441 else if (!strcasecmp(v->value, "qsig"))
11442 confp->pri.switchtype = PRI_SWITCH_QSIG;
11443 else {
11444 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
11445 return -1;
11447 } else if (!strcasecmp(v->name, "nsf")) {
11448 if (!strcasecmp(v->value, "sdn"))
11449 confp->pri.nsf = PRI_NSF_SDN;
11450 else if (!strcasecmp(v->value, "megacom"))
11451 confp->pri.nsf = PRI_NSF_MEGACOM;
11452 else if (!strcasecmp(v->value, "tollfreemegacom"))
11453 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
11454 else if (!strcasecmp(v->value, "accunet"))
11455 confp->pri.nsf = PRI_NSF_ACCUNET;
11456 else if (!strcasecmp(v->value, "none"))
11457 confp->pri.nsf = PRI_NSF_NONE;
11458 else {
11459 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
11460 confp->pri.nsf = PRI_NSF_NONE;
11462 } else if (!strcasecmp(v->name, "priindication")) {
11463 if (!strcasecmp(v->value, "outofband"))
11464 confp->chan.priindication_oob = 1;
11465 else if (!strcasecmp(v->value, "inband"))
11466 confp->chan.priindication_oob = 0;
11467 else
11468 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11469 v->value, v->lineno);
11470 } else if (!strcasecmp(v->name, "priexclusive")) {
11471 confp->chan.priexclusive = ast_true(v->value);
11472 } else if (!strcasecmp(v->name, "internationalprefix")) {
11473 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
11474 } else if (!strcasecmp(v->name, "nationalprefix")) {
11475 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
11476 } else if (!strcasecmp(v->name, "localprefix")) {
11477 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
11478 } else if (!strcasecmp(v->name, "privateprefix")) {
11479 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
11480 } else if (!strcasecmp(v->name, "unknownprefix")) {
11481 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
11482 } else if (!strcasecmp(v->name, "nocid")) {
11483 ast_copy_string(confp->pri.nocid, v->value, sizeof(confp->pri.nocid));
11484 } else if (!strcasecmp(v->name, "withheldcid")) {
11485 ast_copy_string(confp->pri.withheldcid, v->value, sizeof(confp->pri.withheldcid));
11486 } else if (!strcasecmp(v->name, "resetinterval")) {
11487 if (!strcasecmp(v->value, "never"))
11488 confp->pri.resetinterval = -1;
11489 else if (atoi(v->value) >= 60)
11490 confp->pri.resetinterval = atoi(v->value);
11491 else
11492 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11493 v->value, v->lineno);
11494 } else if (!strcasecmp(v->name, "minunused")) {
11495 confp->pri.minunused = atoi(v->value);
11496 } else if (!strcasecmp(v->name, "minidle")) {
11497 confp->pri.minidle = atoi(v->value);
11498 } else if (!strcasecmp(v->name, "idleext")) {
11499 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
11500 } else if (!strcasecmp(v->name, "idledial")) {
11501 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
11502 } else if (!strcasecmp(v->name, "overlapdial")) {
11503 confp->pri.overlapdial = ast_true(v->value);
11504 #ifdef HAVE_PRI_INBANDDISCONNECT
11505 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
11506 confp->pri.inbanddisconnect = ast_true(v->value);
11507 #endif
11508 } else if (!strcasecmp(v->name, "pritimer")) {
11509 #ifdef PRI_GETSET_TIMERS
11510 char *timerc, *c;
11511 int timer, timeridx;
11512 c = v->value;
11513 timerc = strsep(&c, ",");
11514 if (timerc) {
11515 timer = atoi(c);
11516 if (!timer)
11517 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc);
11518 else {
11519 if ((timeridx = pri_timer2idx(timerc)) >= 0)
11520 pritimers[timeridx] = timer;
11521 else
11522 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc);
11524 } else
11525 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value);
11527 } else if (!strcasecmp(v->name, "facilityenable")) {
11528 confp->pri.facilityenable = ast_true(v->value);
11529 #endif /* PRI_GETSET_TIMERS */
11530 #endif /* HAVE_PRI */
11531 } else if (!strcasecmp(v->name, "cadence")) {
11532 /* setup to scan our argument */
11533 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11534 int i;
11535 struct dahdi_ring_cadence new_cadence;
11536 int cid_location = -1;
11537 int firstcadencepos = 0;
11538 char original_args[80];
11539 int cadence_is_ok = 1;
11541 ast_copy_string(original_args, v->value, sizeof(original_args));
11542 /* 16 cadences allowed (8 pairs) */
11543 element_count = sscanf(v->value, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &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]);
11545 /* Cadence must be even (on/off) */
11546 if (element_count % 2 == 1) {
11547 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
11548 cadence_is_ok = 0;
11551 /* Ring cadences cannot be negative */
11552 for (i = 0; i < element_count; i++) {
11553 if (c[i] == 0) {
11554 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
11555 cadence_is_ok = 0;
11556 break;
11557 } else if (c[i] < 0) {
11558 if (i % 2 == 1) {
11559 /* Silence duration, negative possibly okay */
11560 if (cid_location == -1) {
11561 cid_location = i;
11562 c[i] *= -1;
11563 } else {
11564 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
11565 cadence_is_ok = 0;
11566 break;
11568 } else {
11569 if (firstcadencepos == 0) {
11570 firstcadencepos = i; /* only recorded to avoid duplicate specification */
11571 /* duration will be passed negative to the DAHDI driver */
11572 } else {
11573 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
11574 cadence_is_ok = 0;
11575 break;
11581 /* Substitute our scanned cadence */
11582 for (i = 0; i < 16; i++) {
11583 new_cadence.ringcadence[i] = c[i];
11586 if (cadence_is_ok) {
11587 /* ---we scanned it without getting annoyed; now some sanity checks--- */
11588 if (element_count < 2) {
11589 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
11590 } else {
11591 if (cid_location == -1) {
11592 /* user didn't say; default to first pause */
11593 cid_location = 1;
11594 } else {
11595 /* convert element_index to cidrings value */
11596 cid_location = (cid_location + 1) / 2;
11598 /* ---we like their cadence; try to install it--- */
11599 if (!user_has_defined_cadences++)
11600 /* this is the first user-defined cadence; clear the default user cadences */
11601 num_cadence = 0;
11602 if ((num_cadence+1) >= NUM_CADENCE_MAX)
11603 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
11604 else {
11605 cadences[num_cadence] = new_cadence;
11606 cidrings[num_cadence++] = cid_location;
11607 if (option_verbose > 2)
11608 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
11612 } else if (!strcasecmp(v->name, "ringtimeout")) {
11613 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
11614 } else if (!strcasecmp(v->name, "prewink")) {
11615 confp->timing.prewinktime = atoi(v->value);
11616 } else if (!strcasecmp(v->name, "preflash")) {
11617 confp->timing.preflashtime = atoi(v->value);
11618 } else if (!strcasecmp(v->name, "wink")) {
11619 confp->timing.winktime = atoi(v->value);
11620 } else if (!strcasecmp(v->name, "flash")) {
11621 confp->timing.flashtime = atoi(v->value);
11622 } else if (!strcasecmp(v->name, "start")) {
11623 confp->timing.starttime = atoi(v->value);
11624 } else if (!strcasecmp(v->name, "rxwink")) {
11625 confp->timing.rxwinktime = atoi(v->value);
11626 } else if (!strcasecmp(v->name, "rxflash")) {
11627 confp->timing.rxflashtime = atoi(v->value);
11628 } else if (!strcasecmp(v->name, "debounce")) {
11629 confp->timing.debouncetime = atoi(v->value);
11630 } else if (!strcasecmp(v->name, "toneduration")) {
11631 int toneduration;
11632 int ctlfd;
11633 int res;
11634 struct dahdi_dialparams dps;
11636 #ifdef HAVE_ZAPTEL
11637 ctlfd = open("/dev/zap/ctl", O_RDWR);
11638 #else
11639 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
11640 #endif
11642 if (ctlfd == -1) {
11643 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration\n");
11644 return -1;
11647 toneduration = atoi(v->value);
11648 if (toneduration > -1) {
11649 memset(&dps, 0, sizeof(dps));
11651 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
11652 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
11653 if (res < 0) {
11654 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
11655 return -1;
11658 close(ctlfd);
11659 } else if (!strcasecmp(v->name, "defaultcic")) {
11660 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
11661 } else if (!strcasecmp(v->name, "defaultozz")) {
11662 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
11664 } else if (!skipchannels)
11665 ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
11667 if (dahdichan[0]) {
11668 /* The user has set 'dahdichan' */
11669 /*< \todo pass proper line number instead of 0 */
11670 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
11671 return -1;
11674 /*< \todo why check for the pseudo in the per-channel section.
11675 * Any actual use for manual setup of the pseudo channel? */
11676 if (!found_pseudo && reload == 0) {
11677 /* Make sure pseudo isn't a member of any groups if
11678 we're automatically making it. */
11680 confp->chan.group = 0;
11681 confp->chan.callgroup = 0;
11682 confp->chan.pickupgroup = 0;
11684 tmp = mkintf(CHAN_PSEUDO, confp, NULL, reload);
11686 if (tmp) {
11687 if (option_verbose > 2)
11688 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
11689 } else {
11690 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
11693 return 0;
11696 static int setup_dahdi(int reload)
11698 struct ast_config *cfg;
11699 struct ast_variable *v;
11700 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
11701 int res;
11703 #ifdef HAVE_PRI
11704 char *c;
11705 int spanno;
11706 int i, x;
11707 int logicalspan;
11708 int trunkgroup;
11709 int dchannels[NUM_DCHANS];
11710 #endif
11712 #ifdef HAVE_ZAPTEL
11713 int load_from_zapata_conf = 1;
11714 #else
11715 int load_from_zapata_conf = (dahdi_chan_mode == CHAN_ZAP_MODE);
11716 #endif
11718 if (load_from_zapata_conf) {
11719 if (!(cfg = ast_config_load("zapata.conf"))) {
11720 ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
11721 return 0;
11723 } else {
11724 if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
11725 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
11726 return 0;
11730 /* It's a little silly to lock it, but we mind as well just to be sure */
11731 ast_mutex_lock(&iflock);
11732 #ifdef HAVE_PRI
11733 if (reload != 1) {
11734 /* Process trunkgroups first */
11735 v = ast_variable_browse(cfg, "trunkgroups");
11736 while (v) {
11737 if (!strcasecmp(v->name, "trunkgroup")) {
11738 trunkgroup = atoi(v->value);
11739 if (trunkgroup > 0) {
11740 if ((c = strchr(v->value, ','))) {
11741 i = 0;
11742 memset(dchannels, 0, sizeof(dchannels));
11743 while (c && (i < NUM_DCHANS)) {
11744 dchannels[i] = atoi(c + 1);
11745 if (dchannels[i] < 0) {
11746 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);
11747 } else
11748 i++;
11749 c = strchr(c + 1, ',');
11751 if (i) {
11752 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
11753 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);
11754 } else if (option_verbose > 1)
11755 ast_verbose(VERBOSE_PREFIX_2 "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
11756 } else
11757 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11758 } else
11759 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11760 } else
11761 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
11762 } else if (!strcasecmp(v->name, "spanmap")) {
11763 spanno = atoi(v->value);
11764 if (spanno > 0) {
11765 if ((c = strchr(v->value, ','))) {
11766 trunkgroup = atoi(c + 1);
11767 if (trunkgroup > 0) {
11768 if ((c = strchr(c + 1, ',')))
11769 logicalspan = atoi(c + 1);
11770 else
11771 logicalspan = 0;
11772 if (logicalspan >= 0) {
11773 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
11774 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11775 } else if (option_verbose > 1)
11776 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11777 } else
11778 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);
11779 } else
11780 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
11781 } else
11782 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
11783 } else
11784 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
11785 } else {
11786 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
11788 v = v->next;
11791 #endif
11793 /* Copy the default jb config over global_jbconf */
11794 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
11796 v = ast_variable_browse(cfg, "channels");
11797 res = process_dahdi(&conf, "", v, reload, 0);
11798 ast_mutex_unlock(&iflock);
11799 ast_config_destroy(cfg);
11800 if (res)
11801 return res;
11802 cfg = ast_config_load("users.conf");
11803 if (cfg) {
11804 char *cat;
11805 const char *chans;
11806 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
11807 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
11808 if (!strcasecmp(cat, "general"))
11809 continue;
11810 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
11811 if (!ast_strlen_zero(chans)) {
11812 struct dahdi_chan_conf sect_conf;
11813 memcpy(&sect_conf, &conf, sizeof(sect_conf));
11815 process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
11818 ast_config_destroy(cfg);
11820 #ifdef HAVE_PRI
11821 if (reload != 1) {
11822 for (x = 0; x < NUM_SPANS; x++) {
11823 if (pris[x].pvts[0]) {
11824 if (start_pri(pris + x)) {
11825 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
11826 return -1;
11827 } else if (option_verbose > 1)
11828 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
11832 #endif
11833 /* And start the monitor for the first time */
11834 restart_monitor();
11835 return 0;
11838 #define local_astman_register(a, b, c, d) do { \
11839 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
11840 ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
11842 ast_manager_register("Zap" a, b, zap_ ## c, d); \
11843 } while (0)
11845 static int load_module(void)
11847 int res;
11849 #ifdef HAVE_PRI
11850 int y,i;
11851 memset(pris, 0, sizeof(pris));
11852 for (y = 0; y < NUM_SPANS; y++) {
11853 ast_mutex_init(&pris[y].lock);
11854 pris[y].offset = -1;
11855 pris[y].master = AST_PTHREADT_NULL;
11856 for (i = 0; i < NUM_DCHANS; i++)
11857 pris[y].fds[i] = -1;
11859 pri_set_error(dahdi_pri_error);
11860 pri_set_message(dahdi_pri_message);
11861 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11862 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
11863 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
11865 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
11866 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
11867 #endif
11868 if ((res = setup_dahdi(0))) {
11869 return AST_MODULE_LOAD_DECLINE;
11871 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11872 chan_tech = &dahdi_tech;
11873 } else {
11874 chan_tech = &zap_tech;
11876 if (ast_channel_register(chan_tech)) {
11877 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
11878 __unload_module();
11879 return -1;
11881 #ifdef HAVE_PRI
11882 ast_string_field_init(&inuse, 16);
11883 ast_string_field_set(&inuse, name, "GR-303InUse");
11884 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
11885 #endif
11886 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
11888 memset(round_robin, 0, sizeof(round_robin));
11889 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
11890 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
11891 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
11892 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
11893 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
11894 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
11895 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
11897 ast_cond_init(&ss_thread_complete, NULL);
11899 return res;
11902 static int dahdi_sendtext(struct ast_channel *c, const char *text)
11904 #define END_SILENCE_LEN 400
11905 #define HEADER_MS 50
11906 #define TRAILER_MS 5
11907 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11908 #define ASCII_BYTES_PER_CHAR 80
11910 unsigned char *buf,*mybuf;
11911 struct dahdi_pvt *p = c->tech_pvt;
11912 struct pollfd fds[1];
11913 int size,res,fd,len,x;
11914 int bytes=0;
11915 /* Initial carrier (imaginary) */
11916 float cr = 1.0;
11917 float ci = 0.0;
11918 float scont = 0.0;
11919 int index;
11921 index = dahdi_get_index(c, p, 0);
11922 if (index < 0) {
11923 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
11924 return -1;
11926 if (!text[0]) return(0); /* if nothing to send, dont */
11927 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */
11928 if (p->mate)
11929 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
11930 else
11931 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
11932 if (!buf)
11933 return -1;
11934 mybuf = buf;
11935 if (p->mate) {
11936 int codec = AST_LAW(p);
11937 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
11938 PUT_CLID_MARKMS;
11940 /* Put actual message */
11941 for (x = 0; text[x]; x++) {
11942 PUT_CLID(text[x]);
11944 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
11945 PUT_CLID_MARKMS;
11947 len = bytes;
11948 buf = mybuf;
11949 } else {
11950 len = tdd_generate(p->tdd, buf, text);
11951 if (len < 1) {
11952 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
11953 free(mybuf);
11954 return -1;
11957 memset(buf + len, 0x7f, END_SILENCE_LEN);
11958 len += END_SILENCE_LEN;
11959 fd = p->subs[index].dfd;
11960 while (len) {
11961 if (ast_check_hangup(c)) {
11962 free(mybuf);
11963 return -1;
11965 size = len;
11966 if (size > READ_SIZE)
11967 size = READ_SIZE;
11968 fds[0].fd = fd;
11969 fds[0].events = POLLOUT | POLLPRI;
11970 fds[0].revents = 0;
11971 res = poll(fds, 1, -1);
11972 if (!res) {
11973 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
11974 continue;
11976 /* if got exception */
11977 if (fds[0].revents & POLLPRI) {
11978 ast_free(mybuf);
11979 return -1;
11981 if (!(fds[0].revents & POLLOUT)) {
11982 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
11983 continue;
11985 res = write(fd, buf, size);
11986 if (res != size) {
11987 if (res == -1) {
11988 free(mybuf);
11989 return -1;
11991 if (option_debug)
11992 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
11993 break;
11995 len -= size;
11996 buf += size;
11998 free(mybuf);
11999 return(0);
12003 static int reload(void)
12005 int res = 0;
12007 res = setup_dahdi(1);
12008 if (res) {
12009 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
12010 return -1;
12012 return 0;
12015 /* This is a workaround so that menuselect displays a proper description
12016 * AST_MODULE_INFO(, , "DAHDI Telephony"
12019 #ifdef DAHDI_PRI
12020 #define tdesc "DAHDI Telephony w/PRI"
12021 #else
12022 #define tdesc "DAHDI Telephony"
12023 #endif
12025 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
12026 .load = load_module,
12027 .unload = unload_module,
12028 .reload = reload,