The CDRfix4/5/6 omnibus cdr fixes.
[asterisk-bristuff.git] / channels / chan_dahdi.c
blobaab01c51121a7b2c88705ecc0bcc2a180500bbf5
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 #if !defined(DAHDI_SIG_EM_E1) || (defined(HAVE_PRI) && !defined(DAHDI_SIG_HARDHDLC))
120 #error "Your DAHDI is too old. Please update"
121 #endif
123 #ifndef DAHDI_TONEDETECT
124 /* Work around older code with no tone detect */
125 #define DAHDI_EVENT_DTMFDOWN 0
126 #define DAHDI_EVENT_DTMFUP 0
127 #endif
129 /* define this to send PRI user-user information elements */
130 #undef SUPPORT_USERUSER
132 /*!
133 * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
134 * the user hangs up to reset the state machine so ring works properly.
135 * This is used to be able to support kewlstart by putting the zhone in
136 * groundstart mode since their forward disconnect supervision is entirely
137 * broken even though their documentation says it isn't and their support
138 * is entirely unwilling to provide any assistance with their channel banks
139 * even though their web site says they support their products for life.
141 /* #define ZHONE_HACK */
143 /*! \note
144 * Define if you want to check the hook state for an FXO (FXS signalled) interface
145 * before dialing on it. Certain FXO interfaces always think they're out of
146 * service with this method however.
148 /* #define DAHDI_CHECK_HOOKSTATE */
150 /*! \brief Typically, how many rings before we should send Caller*ID */
151 #define DEFAULT_CIDRINGS 1
153 #define CHANNEL_PSEUDO -12
155 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
157 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
158 #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))
160 static const char tdesc[] = "DAHDI Telephony Driver"
161 #ifdef HAVE_PRI
162 " w/PRI"
163 #endif
166 static const char config[] = "chan_dahdi.conf";
168 #define SIG_EM DAHDI_SIG_EM
169 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
170 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
171 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
172 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
173 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
174 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
175 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
176 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
177 #define SIG_FXSLS DAHDI_SIG_FXSLS
178 #define SIG_FXSGS DAHDI_SIG_FXSGS
179 #define SIG_FXSKS DAHDI_SIG_FXSKS
180 #define SIG_FXOLS DAHDI_SIG_FXOLS
181 #define SIG_FXOGS DAHDI_SIG_FXOGS
182 #define SIG_FXOKS DAHDI_SIG_FXOKS
183 #define SIG_PRI DAHDI_SIG_CLEAR
184 #define SIG_SF DAHDI_SIG_SF
185 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
186 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
187 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
188 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
189 #define SIG_EM_E1 DAHDI_SIG_EM_E1
190 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
191 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
193 #define NUM_SPANS 32
194 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
195 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
197 #define CHAN_PSEUDO -2
199 #define DCHAN_PROVISIONED (1 << 0)
200 #define DCHAN_NOTINALARM (1 << 1)
201 #define DCHAN_UP (1 << 2)
203 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
205 static char defaultcic[64] = "";
206 static char defaultozz[64] = "";
208 static char progzone[10] = "";
210 static int distinctiveringaftercid = 0;
212 static int numbufs = 4;
214 #ifdef HAVE_PRI
215 static struct ast_channel inuse;
216 #ifdef PRI_GETSET_TIMERS
217 static int pritimers[PRI_MAX_TIMERS];
218 #endif
219 static int pridebugfd = -1;
220 static char pridebugfilename[1024] = "";
221 #endif
223 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
224 static int firstdigittimeout = 16000;
226 /*! \brief How long to wait for following digits (FXO logic) */
227 static int gendigittimeout = 8000;
229 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
230 static int matchdigittimeout = 3000;
232 /*! \brief Protect the interface list (of dahdi_pvt's) */
233 AST_MUTEX_DEFINE_STATIC(iflock);
236 static int ifcount = 0;
238 #ifdef HAVE_PRI
239 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
240 #endif
242 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
243 when it's doing something critical. */
244 AST_MUTEX_DEFINE_STATIC(monlock);
246 /*! \brief This is the thread for the monitor which checks for input on the channels
247 which are not currently in use. */
248 static pthread_t monitor_thread = AST_PTHREADT_NULL;
250 static int restart_monitor(void);
252 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);
254 static int dahdi_sendtext(struct ast_channel *c, const char *text);
256 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
257 static inline int dahdi_get_event(int fd)
259 int j;
260 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
261 return -1;
262 return j;
265 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
266 static inline int dahdi_wait_event(int fd)
268 int i, j = 0;
269 i = DAHDI_IOMUX_SIGEVENT;
270 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
271 return -1;
272 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
273 return -1;
274 return j;
277 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
278 #define READ_SIZE 160
280 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
281 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
283 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) /*!< 300 ms */
284 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
285 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) /*!< 500 ms */
286 #define MIN_MS_SINCE_FLASH ( (2000) ) /*!< 2000 ms */
287 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
289 struct dahdi_pvt;
291 static int ringt_base = DEFAULT_RINGT;
293 #ifdef HAVE_PRI
295 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
296 #define PRI_CHANNEL(p) ((p) & 0xff)
297 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
298 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
300 struct dahdi_pri {
301 pthread_t master; /*!< Thread of master */
302 ast_mutex_t lock; /*!< Mutex */
303 char idleext[AST_MAX_EXTENSION]; /*!< Where to idle extra calls */
304 char idlecontext[AST_MAX_CONTEXT]; /*!< What context to use for idle */
305 char idledial[AST_MAX_EXTENSION]; /*!< What to dial before dumping */
306 int minunused; /*!< Min # of channels to keep empty */
307 int minidle; /*!< Min # of "idling" calls to keep active */
308 int nodetype; /*!< Node type */
309 int switchtype; /*!< Type of switch to emulate */
310 int nsf; /*!< Network-Specific Facilities */
311 int dialplan; /*!< Dialing plan */
312 int localdialplan; /*!< Local dialing plan */
313 char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
314 char nationalprefix[10]; /*!< area access code ('0' for european dialplans) */
315 char localprefix[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
316 char privateprefix[20]; /*!< for private dialplans */
317 char unknownprefix[20]; /*!< for unknown dialplans */
318 int dchannels[NUM_DCHANS]; /*!< What channel are the dchannels on */
319 int trunkgroup; /*!< What our trunkgroup is */
320 int mastertrunkgroup; /*!< What trunk group is our master */
321 int prilogicalspan; /*!< Logical span number within trunk group */
322 int numchans; /*!< Num of channels we represent */
323 int overlapdial; /*!< In overlap dialing mode */
324 int facilityenable; /*!< Enable facility IEs */
325 struct pri *dchans[NUM_DCHANS]; /*!< Actual d-channels */
326 int dchanavail[NUM_DCHANS]; /*!< Whether each channel is available */
327 struct pri *pri; /*!< Currently active D-channel */
328 int debug;
329 int fds[NUM_DCHANS]; /*!< FD's for d-channels */
330 int offset;
331 int span;
332 int resetting;
333 int resetpos;
334 time_t lastreset; /*!< time when unused channels were last reset */
335 long resetinterval; /*!< Interval (in seconds) for resetting unused channels */
336 struct dahdi_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
337 struct dahdi_pvt *crvs; /*!< Member CRV structs */
338 struct dahdi_pvt *crvend; /*!< Pointer to end of CRV structs */
342 static struct dahdi_pri pris[NUM_SPANS];
344 #if 0
345 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
346 #else
347 #define DEFAULT_PRI_DEBUG 0
348 #endif
350 static inline void pri_rel(struct dahdi_pri *pri)
352 ast_mutex_unlock(&pri->lock);
355 #else
356 /*! Shut up the compiler */
357 struct dahdi_pri;
358 #endif
360 #define SUB_REAL 0 /*!< Active call */
361 #define SUB_CALLWAIT 1 /*!< Call-Waiting call on hold */
362 #define SUB_THREEWAY 2 /*!< Three-way call */
364 /* Polarity states */
365 #define POLARITY_IDLE 0
366 #define POLARITY_REV 1
369 static struct dahdi_distRings drings;
371 struct distRingData {
372 int ring[3];
374 struct ringContextData {
375 char contextData[AST_MAX_CONTEXT];
377 struct dahdi_distRings {
378 struct distRingData ringnum[3];
379 struct ringContextData ringContext[3];
382 static char *subnames[] = {
383 "Real",
384 "Callwait",
385 "Threeway"
388 struct dahdi_subchannel {
389 int dfd;
390 struct ast_channel *owner;
391 int chan;
392 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
393 struct ast_frame f; /*!< One frame for each channel. How did this ever work before? */
394 unsigned int needringing:1;
395 unsigned int needbusy:1;
396 unsigned int needcongestion:1;
397 unsigned int needcallerid:1;
398 unsigned int needanswer:1;
399 unsigned int needflash:1;
400 unsigned int needhold:1;
401 unsigned int needunhold:1;
402 unsigned int linear:1;
403 unsigned int inthreeway:1;
404 DAHDI_CONFINFO curconf;
407 #define CONF_USER_REAL (1 << 0)
408 #define CONF_USER_THIRDCALL (1 << 1)
410 #define MAX_SLAVES 4
412 static struct dahdi_pvt {
413 ast_mutex_t lock;
414 struct ast_channel *owner; /*!< Our current active owner (if applicable) */
415 /*!< Up to three channels can be associated with this call */
417 struct dahdi_subchannel sub_unused; /*!< Just a safety precaution */
418 struct dahdi_subchannel subs[3]; /*!< Sub-channels */
419 DAHDI_CONFINFO saveconf; /*!< Saved conference info */
421 struct dahdi_pvt *slaves[MAX_SLAVES]; /*!< Slave to us (follows our conferencing) */
422 struct dahdi_pvt *master; /*!< Master to us (we follow their conferencing) */
423 int inconference; /*!< If our real should be in the conference */
425 int sig; /*!< Signalling style */
426 int radio; /*!< radio type */
427 int outsigmod; /*!< Outbound Signalling style (modifier) */
428 int oprmode; /*!< "Operator Services" mode */
429 struct dahdi_pvt *oprpeer; /*!< "Operator Services" peer tech_pvt ptr */
430 float rxgain;
431 float txgain;
432 int tonezone; /*!< tone zone for this chan, or -1 for default */
433 struct dahdi_pvt *next; /*!< Next channel in list */
434 struct dahdi_pvt *prev; /*!< Prev channel in list */
436 /* flags */
437 unsigned int adsi:1;
438 unsigned int answeronpolarityswitch:1;
439 unsigned int busydetect:1;
440 unsigned int callreturn:1;
441 unsigned int callwaiting:1;
442 unsigned int callwaitingcallerid:1;
443 unsigned int cancallforward:1;
444 unsigned int canpark:1;
445 unsigned int confirmanswer:1; /*!< Wait for '#' to confirm answer */
446 unsigned int destroy:1;
447 unsigned int didtdd:1; /*!< flag to say its done it once */
448 unsigned int dialednone:1;
449 unsigned int dialing:1;
450 unsigned int digital:1;
451 unsigned int dnd:1;
452 unsigned int echobreak:1;
453 unsigned int echocanbridged:1;
454 unsigned int echocanon:1;
455 unsigned int faxhandled:1; /*!< Has a fax tone already been handled? */
456 unsigned int firstradio:1;
457 unsigned int hanguponpolarityswitch:1;
458 unsigned int hardwaredtmf:1;
459 unsigned int hidecallerid:1;
460 unsigned int hidecalleridname:1; /*!< Hide just the name not the number for legacy PBX use */
461 unsigned int ignoredtmf:1;
462 unsigned int immediate:1; /*!< Answer before getting digits? */
463 unsigned int inalarm:1;
464 unsigned int unknown_alarm:1;
465 unsigned int mate:1; /*!< flag to say its in MATE mode */
466 unsigned int outgoing:1;
467 unsigned int overlapdial:1;
468 unsigned int permcallwaiting:1;
469 unsigned int permhidecallerid:1; /*!< Whether to hide our outgoing caller ID or not */
470 unsigned int priindication_oob:1;
471 unsigned int priexclusive:1;
472 unsigned int pulse:1;
473 unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */
474 unsigned int restrictcid:1; /*!< Whether restrict the callerid -> only send ANI */
475 unsigned int threewaycalling:1;
476 unsigned int transfer:1;
477 unsigned int use_callerid:1; /*!< Whether or not to use caller id on this channel */
478 unsigned int use_callingpres:1; /*!< Whether to use the callingpres the calling switch sends */
479 unsigned int usedistinctiveringdetection:1;
480 unsigned int dahditrcallerid:1; /*!< should we use the callerid from incoming call on dahdi transfer or not */
481 unsigned int transfertobusy:1; /*!< allow flash-transfers to busy channels */
482 #if defined(HAVE_PRI)
483 unsigned int alerting:1;
484 unsigned int alreadyhungup:1;
485 unsigned int isidlecall:1;
486 unsigned int proceeding:1;
487 unsigned int progress:1;
488 unsigned int resetting:1;
489 unsigned int setup_ack:1;
490 #endif
491 unsigned int use_smdi:1; /* Whether to use SMDI on this channel */
492 struct ast_smdi_interface *smdi_iface; /* The serial port to listen for SMDI data on */
494 struct dahdi_distRings drings;
496 char context[AST_MAX_CONTEXT];
497 char defcontext[AST_MAX_CONTEXT];
498 char exten[AST_MAX_EXTENSION];
499 char language[MAX_LANGUAGE];
500 char mohinterpret[MAX_MUSICCLASS];
501 char mohsuggest[MAX_MUSICCLASS];
502 #ifdef PRI_ANI
503 char cid_ani[AST_MAX_EXTENSION];
504 #endif
505 char cid_num[AST_MAX_EXTENSION];
506 int cid_ton; /*!< Type Of Number (TON) */
507 char cid_name[AST_MAX_EXTENSION];
508 char lastcid_num[AST_MAX_EXTENSION];
509 char lastcid_name[AST_MAX_EXTENSION];
510 char *origcid_num; /*!< malloced original callerid */
511 char *origcid_name; /*!< malloced original callerid */
512 char callwait_num[AST_MAX_EXTENSION];
513 char callwait_name[AST_MAX_EXTENSION];
514 char rdnis[AST_MAX_EXTENSION];
515 char dnid[AST_MAX_EXTENSION];
516 ast_group_t group;
517 int law;
518 int confno; /*!< Our conference */
519 int confusers; /*!< Who is using our conference */
520 int propconfno; /*!< Propagated conference number */
521 ast_group_t callgroup;
522 ast_group_t pickupgroup;
523 int channel; /*!< Channel Number or CRV */
524 int span; /*!< Span number */
525 time_t guardtime; /*!< Must wait this much time before using for new call */
526 int cid_signalling; /*!< CID signalling type bell202 or v23 */
527 int cid_start; /*!< CID start indicator, polarity or ring */
528 int callingpres; /*!< The value of callling presentation that we're going to use when placing a PRI call */
529 int callwaitingrepeat; /*!< How many samples to wait before repeating call waiting */
530 int cidcwexpire; /*!< When to expire our muting for CID/CW */
531 unsigned char *cidspill;
532 int cidpos;
533 int cidlen;
534 int ringt;
535 int ringt_base;
536 int stripmsd;
537 int callwaitcas;
538 int callwaitrings;
539 int echocancel;
540 int echotraining;
541 char echorest[20];
542 int busycount;
543 int busy_tonelength;
544 int busy_quietlength;
545 int callprogress;
546 struct timeval flashtime; /*!< Last flash-hook time */
547 struct ast_dsp *dsp;
548 int cref; /*!< Call reference number */
549 DAHDI_DIAL_OPERATION dop;
550 int whichwink; /*!< SIG_FEATDMF_TA Which wink are we on? */
551 char finaldial[64];
552 char accountcode[AST_MAX_ACCOUNT_CODE]; /*!< Account code */
553 int amaflags; /*!< AMA Flags */
554 struct tdd_state *tdd; /*!< TDD flag */
555 char call_forward[AST_MAX_EXTENSION];
556 char mailbox[AST_MAX_EXTENSION];
557 char dialdest[256];
558 int onhooktime;
559 int msgstate;
560 int distinctivering; /*!< Which distinctivering to use */
561 int cidrings; /*!< Which ring to deliver CID on */
562 int dtmfrelax; /*!< whether to run in relaxed DTMF mode */
563 int fake_event;
564 int polarityonanswerdelay;
565 struct timeval polaritydelaytv;
566 int sendcalleridafter;
567 #ifdef HAVE_PRI
568 struct dahdi_pri *pri;
569 struct dahdi_pvt *bearer;
570 struct dahdi_pvt *realcall;
571 q931_call *call;
572 int prioffset;
573 int logicalspan;
574 #endif
575 int polarity;
576 int dsp_features;
577 char begindigit;
578 } *iflist = NULL, *ifend = NULL;
580 /*! \brief Channel configuration from chan_dahdi.conf .
581 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
582 * Generally there is a field here for every possible configuration item.
584 * The state of fields is saved along the parsing and whenever a 'channel'
585 * statement is reached, the current dahdi_chan_conf is used to configure the
586 * channel (struct dahdi_pvt)
588 * @seealso dahdi_chan_init for the default values.
590 struct dahdi_chan_conf {
591 struct dahdi_pvt chan;
592 #ifdef HAVE_PRI
593 struct dahdi_pri pri;
594 #endif
595 DAHDI_PARAMS timing;
597 char smdi_port[SMDI_MAX_FILENAME_LEN];
600 /** returns a new dahdi_chan_conf with default values (by-value) */
601 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
602 /* recall that if a field is not included here it is initialized
603 * to 0 or equivalent
605 struct dahdi_chan_conf conf = {
606 #ifdef HAVE_PRI
607 .pri = {
608 .nsf = PRI_NSF_NONE,
609 .switchtype = PRI_SWITCH_NI2,
610 .dialplan = PRI_NATIONAL_ISDN + 1,
611 .localdialplan = PRI_NATIONAL_ISDN + 1,
612 .nodetype = PRI_CPE,
614 .minunused = 2,
615 .idleext = "",
616 .idledial = "",
617 .internationalprefix = "",
618 .nationalprefix = "",
619 .localprefix = "",
620 .privateprefix = "",
621 .unknownprefix = "",
623 .resetinterval = 3600
625 #endif
626 .chan = {
627 .context = "default",
628 .cid_num = "",
629 .cid_name = "",
630 .mohinterpret = "default",
631 .mohsuggest = "",
632 .transfertobusy = 1,
634 .cid_signalling = CID_SIG_BELL,
635 .cid_start = CID_START_RING,
636 .dahditrcallerid = 0,
637 .use_callerid = 1,
638 .sig = -1,
639 .outsigmod = -1,
641 .tonezone = -1,
643 .echocancel = 1,
645 .busycount = 3,
647 .accountcode = "",
649 .mailbox = "",
652 .polarityonanswerdelay = 600,
654 .sendcalleridafter = DEFAULT_CIDRINGS
656 .timing = {
657 .prewinktime = -1,
658 .preflashtime = -1,
659 .winktime = -1,
660 .flashtime = -1,
661 .starttime = -1,
662 .rxwinktime = -1,
663 .rxflashtime = -1,
664 .debouncetime = -1
666 .smdi_port = "/dev/ttyS0",
669 return conf;
673 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
674 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
675 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
676 static int dahdi_sendtext(struct ast_channel *c, const char *text);
677 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
678 static int dahdi_hangup(struct ast_channel *ast);
679 static int dahdi_answer(struct ast_channel *ast);
680 static struct ast_frame *dahdi_read(struct ast_channel *ast);
681 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
682 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
683 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
684 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
685 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
686 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len);
688 static const struct ast_channel_tech dahdi_tech = {
689 .type = "DAHDI",
690 .description = tdesc,
691 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
692 .requester = dahdi_request,
693 .send_digit_begin = dahdi_digit_begin,
694 .send_digit_end = dahdi_digit_end,
695 .send_text = dahdi_sendtext,
696 .call = dahdi_call,
697 .hangup = dahdi_hangup,
698 .answer = dahdi_answer,
699 .read = dahdi_read,
700 .write = dahdi_write,
701 .bridge = dahdi_bridge,
702 .exception = dahdi_exception,
703 .indicate = dahdi_indicate,
704 .fixup = dahdi_fixup,
705 .setoption = dahdi_setoption,
706 .func_channel_read = dahdi_func_read,
709 #ifdef HAVE_PRI
710 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
711 #else
712 #define GET_CHANNEL(p) ((p)->channel)
713 #endif
715 struct dahdi_pvt *round_robin[32];
717 #ifdef HAVE_PRI
718 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
720 int res;
721 /* Grab the lock first */
722 do {
723 res = ast_mutex_trylock(&pri->lock);
724 if (res) {
725 DEADLOCK_AVOIDANCE(&pvt->lock);
727 } while (res);
728 /* Then break the poll */
729 pthread_kill(pri->master, SIGURG);
730 return 0;
732 #endif
734 #define NUM_CADENCE_MAX 25
735 static int num_cadence = 4;
736 static int user_has_defined_cadences = 0;
738 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
739 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
740 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
741 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
742 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
745 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
746 * is 1, the second pause is 2 and so on.
749 static int cidrings[NUM_CADENCE_MAX] = {
750 2, /*!< Right after first long ring */
751 4, /*!< Right after long part */
752 3, /*!< After third chirp */
753 2, /*!< Second spell */
756 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
757 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
759 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
760 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
762 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
764 int res;
765 if (p->subs[0].owner == ast)
766 res = 0;
767 else if (p->subs[1].owner == ast)
768 res = 1;
769 else if (p->subs[2].owner == ast)
770 res = 2;
771 else {
772 res = -1;
773 if (!nullok)
774 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
776 return res;
779 #ifdef HAVE_PRI
780 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
781 #else
782 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
783 #endif
785 #ifdef HAVE_PRI
786 if (pri)
787 ast_mutex_unlock(&pri->lock);
788 #endif
789 for (;;) {
790 if (p->subs[a].owner) {
791 if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
792 DEADLOCK_AVOIDANCE(&p->lock);
793 } else {
794 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
795 ast_mutex_unlock(&p->subs[a].owner->lock);
796 break;
798 } else
799 break;
801 #ifdef HAVE_PRI
802 if (pri)
803 ast_mutex_lock(&pri->lock);
804 #endif
807 #ifdef HAVE_PRI
808 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
809 #else
810 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)
811 #endif
813 /* We must unlock the PRI to avoid the possibility of a deadlock */
814 #ifdef HAVE_PRI
815 if (pri)
816 ast_mutex_unlock(&pri->lock);
817 #endif
818 for (;;) {
819 if (p->owner) {
820 if (ast_mutex_trylock(&p->owner->lock)) {
821 DEADLOCK_AVOIDANCE(&p->lock);
822 } else {
823 ast_queue_frame(p->owner, f);
824 ast_mutex_unlock(&p->owner->lock);
825 break;
827 } else
828 break;
830 #ifdef HAVE_PRI
831 if (pri)
832 ast_mutex_lock(&pri->lock);
833 #endif
836 static int restore_gains(struct dahdi_pvt *p);
838 static void swap_subs(struct dahdi_pvt *p, int a, int b)
840 int tchan;
841 int tinthreeway;
842 struct ast_channel *towner;
844 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
846 tchan = p->subs[a].chan;
847 towner = p->subs[a].owner;
848 tinthreeway = p->subs[a].inthreeway;
850 p->subs[a].chan = p->subs[b].chan;
851 p->subs[a].owner = p->subs[b].owner;
852 p->subs[a].inthreeway = p->subs[b].inthreeway;
854 p->subs[b].chan = tchan;
855 p->subs[b].owner = towner;
856 p->subs[b].inthreeway = tinthreeway;
858 if (p->subs[a].owner)
859 p->subs[a].owner->fds[0] = p->subs[a].dfd;
860 if (p->subs[b].owner)
861 p->subs[b].owner->fds[0] = p->subs[b].dfd;
862 wakeup_sub(p, a, NULL);
863 wakeup_sub(p, b, NULL);
866 static int dahdi_open(char *fn)
868 int fd;
869 int isnum;
870 int chan = 0;
871 int bs;
872 int x;
873 isnum = 1;
874 for (x = 0; x < strlen(fn); x++) {
875 if (!isdigit(fn[x])) {
876 isnum = 0;
877 break;
880 if (isnum) {
881 chan = atoi(fn);
882 if (chan < 1) {
883 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
884 return -1;
886 #ifdef HAVE_ZAPTEL
887 fn = "/dev/zap/channel";
888 #else
889 fn = "/dev/dahdi/channel";
890 #endif
892 fd = open(fn, O_RDWR | O_NONBLOCK);
893 if (fd < 0) {
894 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
895 return -1;
897 if (chan) {
898 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
899 x = errno;
900 close(fd);
901 errno = x;
902 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
903 return -1;
906 bs = READ_SIZE;
907 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
908 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
909 x = errno;
910 close(fd);
911 errno = x;
912 return -1;
914 return fd;
917 static void dahdi_close(int fd)
919 if (fd > 0)
920 close(fd);
923 static int dahdi_setlinear(int dfd, int linear)
925 int res;
926 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
927 if (res)
928 return res;
929 return 0;
933 static int alloc_sub(struct dahdi_pvt *p, int x)
935 DAHDI_BUFFERINFO bi;
936 int res;
937 if (p->subs[x].dfd < 0) {
938 #ifdef HAVE_ZAPTEL
939 p->subs[x].dfd = dahdi_open("/dev/zap/pseudo");
940 #else
941 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
942 #endif
943 if (p->subs[x].dfd > -1) {
944 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
945 if (!res) {
946 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
947 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
948 bi.numbufs = numbufs;
949 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
950 if (res < 0) {
951 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
953 } else
954 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
955 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
956 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
957 dahdi_close(p->subs[x].dfd);
958 p->subs[x].dfd = -1;
959 return -1;
961 if (option_debug)
962 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
963 return 0;
964 } else
965 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
966 return -1;
968 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
969 return -1;
972 static int unalloc_sub(struct dahdi_pvt *p, int x)
974 if (!x) {
975 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
976 return -1;
978 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
979 if (p->subs[x].dfd > -1) {
980 dahdi_close(p->subs[x].dfd);
982 p->subs[x].dfd = -1;
983 p->subs[x].linear = 0;
984 p->subs[x].chan = 0;
985 p->subs[x].owner = NULL;
986 p->subs[x].inthreeway = 0;
987 p->polarity = POLARITY_IDLE;
988 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
989 return 0;
992 static int digit_to_dtmfindex(char digit)
994 if (isdigit(digit))
995 return DAHDI_TONE_DTMF_BASE + (digit - '0');
996 else if (digit >= 'A' && digit <= 'D')
997 return DAHDI_TONE_DTMF_A + (digit - 'A');
998 else if (digit >= 'a' && digit <= 'd')
999 return DAHDI_TONE_DTMF_A + (digit - 'a');
1000 else if (digit == '*')
1001 return DAHDI_TONE_DTMF_s;
1002 else if (digit == '#')
1003 return DAHDI_TONE_DTMF_p;
1004 else
1005 return -1;
1008 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
1010 struct dahdi_pvt *pvt;
1011 int index;
1012 int dtmf = -1;
1014 pvt = chan->tech_pvt;
1016 ast_mutex_lock(&pvt->lock);
1018 index = dahdi_get_index(chan, pvt, 0);
1020 if ((index != SUB_REAL) || !pvt->owner)
1021 goto out;
1023 #ifdef HAVE_PRI
1024 if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
1025 if (pvt->setup_ack) {
1026 if (!pri_grab(pvt, pvt->pri)) {
1027 pri_information(pvt->pri->pri, pvt->call, digit);
1028 pri_rel(pvt->pri);
1029 } else
1030 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
1031 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
1032 int res;
1033 ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
1034 res = strlen(pvt->dialdest);
1035 pvt->dialdest[res++] = digit;
1036 pvt->dialdest[res] = '\0';
1038 goto out;
1040 #endif
1041 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
1042 goto out;
1044 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
1045 int res;
1046 DAHDI_DIAL_OPERATION zo = {
1047 .op = DAHDI_DIAL_OP_APPEND,
1048 .dialstr[0] = 'T',
1049 .dialstr[1] = digit,
1050 .dialstr[2] = 0,
1052 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
1053 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
1054 else
1055 pvt->dialing = 1;
1056 } else {
1057 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
1058 pvt->dialing = 1;
1059 pvt->begindigit = digit;
1062 out:
1063 ast_mutex_unlock(&pvt->lock);
1065 return 0;
1068 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
1070 struct dahdi_pvt *pvt;
1071 int res = 0;
1072 int index;
1073 int x;
1075 pvt = chan->tech_pvt;
1077 ast_mutex_lock(&pvt->lock);
1079 index = dahdi_get_index(chan, pvt, 0);
1081 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
1082 goto out;
1084 #ifdef HAVE_PRI
1085 /* This means that the digit was already sent via PRI signalling */
1086 if (pvt->sig == SIG_PRI && !pvt->begindigit)
1087 goto out;
1088 #endif
1090 if (pvt->begindigit) {
1091 x = -1;
1092 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
1093 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
1094 pvt->dialing = 0;
1095 pvt->begindigit = 0;
1098 out:
1099 ast_mutex_unlock(&pvt->lock);
1101 return res;
1104 static char *events[] = {
1105 "No event",
1106 "On hook",
1107 "Ring/Answered",
1108 "Wink/Flash",
1109 "Alarm",
1110 "No more alarm",
1111 "HDLC Abort",
1112 "HDLC Overrun",
1113 "HDLC Bad FCS",
1114 "Dial Complete",
1115 "Ringer On",
1116 "Ringer Off",
1117 "Hook Transition Complete",
1118 "Bits Changed",
1119 "Pulse Start",
1120 "Timer Expired",
1121 "Timer Ping",
1122 "Polarity Reversal",
1123 "Ring Begin",
1126 static struct {
1127 int alarm;
1128 char *name;
1129 } alarms[] = {
1130 { DAHDI_ALARM_RED, "Red Alarm" },
1131 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
1132 { DAHDI_ALARM_BLUE, "Blue Alarm" },
1133 { DAHDI_ALARM_RECOVER, "Recovering" },
1134 { DAHDI_ALARM_LOOPBACK, "Loopback" },
1135 { DAHDI_ALARM_NOTOPEN, "Not Open" },
1136 { DAHDI_ALARM_NONE, "None" },
1139 static char *alarm2str(int alarm)
1141 int x;
1142 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
1143 if (alarms[x].alarm & alarm)
1144 return alarms[x].name;
1146 return alarm ? "Unknown Alarm" : "No Alarm";
1149 static char *event2str(int event)
1151 static char buf[256];
1152 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
1153 return events[event];
1154 sprintf(buf, "Event %d", event); /* safe */
1155 return buf;
1158 #ifdef HAVE_PRI
1159 static char *dialplan2str(int dialplan)
1161 if (dialplan == -1) {
1162 return("Dynamically set dialplan in ISDN");
1164 return (pri_plan2str(dialplan));
1166 #endif
1168 static char *dahdi_sig2str(int sig)
1170 static char buf[256];
1171 switch (sig) {
1172 case SIG_EM:
1173 return "E & M Immediate";
1174 case SIG_EMWINK:
1175 return "E & M Wink";
1176 case SIG_EM_E1:
1177 return "E & M E1";
1178 case SIG_FEATD:
1179 return "Feature Group D (DTMF)";
1180 case SIG_FEATDMF:
1181 return "Feature Group D (MF)";
1182 case SIG_FEATDMF_TA:
1183 return "Feature Groud D (MF) Tandem Access";
1184 case SIG_FEATB:
1185 return "Feature Group B (MF)";
1186 case SIG_E911:
1187 return "E911 (MF)";
1188 case SIG_FGC_CAMA:
1189 return "FGC/CAMA (Dialpulse)";
1190 case SIG_FGC_CAMAMF:
1191 return "FGC/CAMA (MF)";
1192 case SIG_FXSLS:
1193 return "FXS Loopstart";
1194 case SIG_FXSGS:
1195 return "FXS Groundstart";
1196 case SIG_FXSKS:
1197 return "FXS Kewlstart";
1198 case SIG_FXOLS:
1199 return "FXO Loopstart";
1200 case SIG_FXOGS:
1201 return "FXO Groundstart";
1202 case SIG_FXOKS:
1203 return "FXO Kewlstart";
1204 case SIG_PRI:
1205 return "ISDN PRI";
1206 case SIG_SF:
1207 return "SF (Tone) Immediate";
1208 case SIG_SFWINK:
1209 return "SF (Tone) Wink";
1210 case SIG_SF_FEATD:
1211 return "SF (Tone) with Feature Group D (DTMF)";
1212 case SIG_SF_FEATDMF:
1213 return "SF (Tone) with Feature Group D (MF)";
1214 case SIG_SF_FEATB:
1215 return "SF (Tone) with Feature Group B (MF)";
1216 case SIG_GR303FXOKS:
1217 return "GR-303 with FXOKS";
1218 case SIG_GR303FXSKS:
1219 return "GR-303 with FXSKS";
1220 case 0:
1221 return "Pseudo";
1222 default:
1223 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
1224 return buf;
1228 #define sig2str dahdi_sig2str
1230 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
1232 /* If the conference already exists, and we're already in it
1233 don't bother doing anything */
1234 DAHDI_CONFINFO zi;
1236 memset(&zi, 0, sizeof(zi));
1237 zi.chan = 0;
1239 if (slavechannel > 0) {
1240 /* If we have only one slave, do a digital mon */
1241 zi.confmode = DAHDI_CONF_DIGITALMON;
1242 zi.confno = slavechannel;
1243 } else {
1244 if (!index) {
1245 /* Real-side and pseudo-side both participate in conference */
1246 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
1247 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
1248 } else
1249 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
1250 zi.confno = p->confno;
1252 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
1253 return 0;
1254 if (c->dfd < 0)
1255 return 0;
1256 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
1257 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
1258 return -1;
1260 if (slavechannel < 1) {
1261 p->confno = zi.confno;
1263 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1264 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
1265 return 0;
1268 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
1270 /* If they're listening to our channel, they're ours */
1271 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
1272 return 1;
1273 /* If they're a talker on our (allocated) conference, they're ours */
1274 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
1275 return 1;
1276 return 0;
1279 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
1281 DAHDI_CONFINFO zi;
1282 if (/* Can't delete if there's no dfd */
1283 (c->dfd < 0) ||
1284 /* Don't delete from the conference if it's not our conference */
1285 !isourconf(p, c)
1286 /* Don't delete if we don't think it's conferenced at all (implied) */
1287 ) return 0;
1288 memset(&zi, 0, sizeof(zi));
1289 zi.chan = 0;
1290 zi.confno = 0;
1291 zi.confmode = 0;
1292 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
1293 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
1294 return -1;
1296 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
1297 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1298 return 0;
1301 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
1303 int x;
1304 int useslavenative;
1305 struct dahdi_pvt *slave = NULL;
1306 /* Start out optimistic */
1307 useslavenative = 1;
1308 /* Update conference state in a stateless fashion */
1309 for (x = 0; x < 3; x++) {
1310 /* Any three-way calling makes slave native mode *definitely* out
1311 of the question */
1312 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
1313 useslavenative = 0;
1315 /* If we don't have any 3-way calls, check to see if we have
1316 precisely one slave */
1317 if (useslavenative) {
1318 for (x = 0; x < MAX_SLAVES; x++) {
1319 if (p->slaves[x]) {
1320 if (slave) {
1321 /* Whoops already have a slave! No
1322 slave native and stop right away */
1323 slave = NULL;
1324 useslavenative = 0;
1325 break;
1326 } else {
1327 /* We have one slave so far */
1328 slave = p->slaves[x];
1333 /* If no slave, slave native definitely out */
1334 if (!slave)
1335 useslavenative = 0;
1336 else if (slave->law != p->law) {
1337 useslavenative = 0;
1338 slave = NULL;
1340 if (out)
1341 *out = slave;
1342 return useslavenative;
1345 static int reset_conf(struct dahdi_pvt *p)
1347 DAHDI_CONFINFO zi;
1348 memset(&zi, 0, sizeof(zi));
1349 p->confno = -1;
1350 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
1351 if (p->subs[SUB_REAL].dfd > -1) {
1352 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
1353 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
1355 return 0;
1358 static int update_conf(struct dahdi_pvt *p)
1360 int needconf = 0;
1361 int x;
1362 int useslavenative;
1363 struct dahdi_pvt *slave = NULL;
1365 useslavenative = isslavenative(p, &slave);
1366 /* Start with the obvious, general stuff */
1367 for (x = 0; x < 3; x++) {
1368 /* Look for three way calls */
1369 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
1370 conf_add(p, &p->subs[x], x, 0);
1371 needconf++;
1372 } else {
1373 conf_del(p, &p->subs[x], x);
1376 /* If we have a slave, add him to our conference now. or DAX
1377 if this is slave native */
1378 for (x = 0; x < MAX_SLAVES; x++) {
1379 if (p->slaves[x]) {
1380 if (useslavenative)
1381 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
1382 else {
1383 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
1384 needconf++;
1388 /* If we're supposed to be in there, do so now */
1389 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
1390 if (useslavenative)
1391 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
1392 else {
1393 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
1394 needconf++;
1397 /* If we have a master, add ourselves to his conference */
1398 if (p->master) {
1399 if (isslavenative(p->master, NULL)) {
1400 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
1401 } else {
1402 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
1405 if (!needconf) {
1406 /* Nobody is left (or should be left) in our conference.
1407 Kill it. */
1408 p->confno = -1;
1410 if (option_debug)
1411 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
1412 return 0;
1415 static void dahdi_enable_ec(struct dahdi_pvt *p)
1417 int x;
1418 int res;
1419 if (!p)
1420 return;
1421 if (p->echocanon) {
1422 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
1423 return;
1425 if (p->digital) {
1426 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
1427 return;
1429 if (p->echocancel) {
1430 if (p->sig == SIG_PRI) {
1431 x = 1;
1432 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
1433 if (res)
1434 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
1436 x = p->echocancel;
1437 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
1438 if (res)
1439 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
1440 else {
1441 p->echocanon = 1;
1442 if (option_debug)
1443 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
1445 } else if (option_debug)
1446 ast_log(LOG_DEBUG, "No echo cancellation requested\n");
1449 static void dahdi_train_ec(struct dahdi_pvt *p)
1451 int x;
1452 int res;
1453 if (p && p->echocancel && p->echotraining) {
1454 x = p->echotraining;
1455 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
1456 if (res)
1457 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
1458 else {
1459 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
1461 } else
1462 ast_log(LOG_DEBUG, "No echo training requested\n");
1465 static void dahdi_disable_ec(struct dahdi_pvt *p)
1467 int x;
1468 int res;
1469 if (p->echocancel) {
1470 x = 0;
1471 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
1472 if (res)
1473 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
1474 else if (option_debug)
1475 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
1477 p->echocanon = 0;
1480 static void fill_txgain(DAHDI_GAINS *g, float gain, int law)
1482 int j;
1483 int k;
1484 float linear_gain = pow(10.0, gain / 20.0);
1486 switch (law) {
1487 case DAHDI_LAW_ALAW:
1488 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
1489 if (gain) {
1490 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1491 if (k > 32767) k = 32767;
1492 if (k < -32767) k = -32767;
1493 g->txgain[j] = AST_LIN2A(k);
1494 } else {
1495 g->txgain[j] = j;
1498 break;
1499 case DAHDI_LAW_MULAW:
1500 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
1501 if (gain) {
1502 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1503 if (k > 32767) k = 32767;
1504 if (k < -32767) k = -32767;
1505 g->txgain[j] = AST_LIN2MU(k);
1506 } else {
1507 g->txgain[j] = j;
1510 break;
1514 static void fill_rxgain(DAHDI_GAINS *g, float gain, int law)
1516 int j;
1517 int k;
1518 float linear_gain = pow(10.0, gain / 20.0);
1520 switch (law) {
1521 case DAHDI_LAW_ALAW:
1522 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
1523 if (gain) {
1524 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1525 if (k > 32767) k = 32767;
1526 if (k < -32767) k = -32767;
1527 g->rxgain[j] = AST_LIN2A(k);
1528 } else {
1529 g->rxgain[j] = j;
1532 break;
1533 case DAHDI_LAW_MULAW:
1534 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
1535 if (gain) {
1536 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1537 if (k > 32767) k = 32767;
1538 if (k < -32767) k = -32767;
1539 g->rxgain[j] = AST_LIN2MU(k);
1540 } else {
1541 g->rxgain[j] = j;
1544 break;
1548 static int set_actual_txgain(int fd, int chan, float gain, int law)
1550 DAHDI_GAINS g;
1551 int res;
1553 memset(&g, 0, sizeof(g));
1554 g.chan = chan;
1555 res = ioctl(fd, DAHDI_GETGAINS, &g);
1556 if (res) {
1557 if (option_debug)
1558 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
1559 return res;
1562 fill_txgain(&g, gain, law);
1564 return ioctl(fd, DAHDI_SETGAINS, &g);
1567 static int set_actual_rxgain(int fd, int chan, float gain, int law)
1569 DAHDI_GAINS g;
1570 int res;
1572 memset(&g, 0, sizeof(g));
1573 g.chan = chan;
1574 res = ioctl(fd, DAHDI_GETGAINS, &g);
1575 if (res) {
1576 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
1577 return res;
1580 fill_rxgain(&g, gain, law);
1582 return ioctl(fd, DAHDI_SETGAINS, &g);
1585 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
1587 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
1590 static int bump_gains(struct dahdi_pvt *p)
1592 int res;
1594 /* Bump receive gain by 5.0db */
1595 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
1596 if (res) {
1597 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
1598 return -1;
1601 return 0;
1604 static int restore_gains(struct dahdi_pvt *p)
1606 int res;
1608 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
1609 if (res) {
1610 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
1611 return -1;
1614 return 0;
1617 static inline int dahdi_set_hook(int fd, int hs)
1619 int x, res;
1621 x = hs;
1622 res = ioctl(fd, DAHDI_HOOK, &x);
1624 if (res < 0) {
1625 if (errno == EINPROGRESS)
1626 return 0;
1627 ast_log(LOG_WARNING, "dahdi hook failed: %s\n", strerror(errno));
1630 return res;
1633 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
1635 int x, y, res;
1636 x = muted;
1637 if (p->sig == SIG_PRI) {
1638 y = 1;
1639 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
1640 if (res)
1641 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
1643 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
1644 if (res < 0)
1645 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
1646 return res;
1649 static int save_conference(struct dahdi_pvt *p)
1651 DAHDI_CONFINFO c;
1652 int res;
1653 if (p->saveconf.confmode) {
1654 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
1655 return -1;
1657 p->saveconf.chan = 0;
1658 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
1659 if (res) {
1660 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
1661 p->saveconf.confmode = 0;
1662 return -1;
1664 c.chan = 0;
1665 c.confno = 0;
1666 c.confmode = DAHDI_CONF_NORMAL;
1667 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
1668 if (res) {
1669 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
1670 return -1;
1672 if (option_debug)
1673 ast_log(LOG_DEBUG, "Disabled conferencing\n");
1674 return 0;
1677 static int restore_conference(struct dahdi_pvt *p)
1679 int res;
1680 if (p->saveconf.confmode) {
1681 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
1682 p->saveconf.confmode = 0;
1683 if (res) {
1684 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
1685 return -1;
1688 if (option_debug)
1689 ast_log(LOG_DEBUG, "Restored conferencing\n");
1690 return 0;
1693 static int send_callerid(struct dahdi_pvt *p);
1695 static int send_cwcidspill(struct dahdi_pvt *p)
1697 p->callwaitcas = 0;
1698 p->cidcwexpire = 0;
1699 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
1700 return -1;
1701 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
1702 /* Make sure we account for the end */
1703 p->cidlen += READ_SIZE * 4;
1704 p->cidpos = 0;
1705 send_callerid(p);
1706 if (option_verbose > 2)
1707 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
1708 return 0;
1711 static int has_voicemail(struct dahdi_pvt *p)
1714 return ast_app_has_voicemail(p->mailbox, NULL);
1717 static int send_callerid(struct dahdi_pvt *p)
1719 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
1720 int res;
1721 /* Take out of linear mode if necessary */
1722 if (p->subs[SUB_REAL].linear) {
1723 p->subs[SUB_REAL].linear = 0;
1724 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
1726 while (p->cidpos < p->cidlen) {
1727 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
1728 if (res < 0) {
1729 if (errno == EAGAIN)
1730 return 0;
1731 else {
1732 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
1733 return -1;
1736 if (!res)
1737 return 0;
1738 p->cidpos += res;
1740 free(p->cidspill);
1741 p->cidspill = NULL;
1742 if (p->callwaitcas) {
1743 /* Wait for CID/CW to expire */
1744 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
1745 } else
1746 restore_conference(p);
1747 return 0;
1750 static int dahdi_callwait(struct ast_channel *ast)
1752 struct dahdi_pvt *p = ast->tech_pvt;
1753 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
1754 if (p->cidspill) {
1755 ast_log(LOG_WARNING, "Spill already exists?!?\n");
1756 free(p->cidspill);
1758 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
1759 return -1;
1760 save_conference(p);
1761 /* Silence */
1762 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
1763 if (!p->callwaitrings && p->callwaitingcallerid) {
1764 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
1765 p->callwaitcas = 1;
1766 p->cidlen = 2400 + 680 + READ_SIZE * 4;
1767 } else {
1768 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
1769 p->callwaitcas = 0;
1770 p->cidlen = 2400 + READ_SIZE * 4;
1772 p->cidpos = 0;
1773 send_callerid(p);
1775 return 0;
1778 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
1780 struct dahdi_pvt *p = ast->tech_pvt;
1781 int x, res, index,mysig;
1782 char *c, *n, *l;
1783 #ifdef HAVE_PRI
1784 char *s = NULL;
1785 #endif
1786 char dest[256]; /* must be same length as p->dialdest */
1787 ast_mutex_lock(&p->lock);
1788 ast_copy_string(dest, rdest, sizeof(dest));
1789 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
1790 if ((ast->_state == AST_STATE_BUSY)) {
1791 p->subs[SUB_REAL].needbusy = 1;
1792 ast_mutex_unlock(&p->lock);
1793 return 0;
1795 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
1796 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
1797 ast_mutex_unlock(&p->lock);
1798 return -1;
1800 p->dialednone = 0;
1801 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
1803 /* Special pseudo -- automatically up */
1804 ast_setstate(ast, AST_STATE_UP);
1805 ast_mutex_unlock(&p->lock);
1806 return 0;
1808 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
1809 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
1810 if (res)
1811 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
1812 p->outgoing = 1;
1814 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
1816 mysig = p->sig;
1817 if (p->outsigmod > -1)
1818 mysig = p->outsigmod;
1820 switch (mysig) {
1821 case SIG_FXOLS:
1822 case SIG_FXOGS:
1823 case SIG_FXOKS:
1824 if (p->owner == ast) {
1825 /* Normal ring, on hook */
1827 /* Don't send audio while on hook, until the call is answered */
1828 p->dialing = 1;
1829 if (p->use_callerid) {
1830 /* Generate the Caller-ID spill if desired */
1831 if (p->cidspill) {
1832 ast_log(LOG_WARNING, "cidspill already exists??\n");
1833 free(p->cidspill);
1835 p->callwaitcas = 0;
1836 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
1837 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
1838 p->cidpos = 0;
1839 send_callerid(p);
1842 /* Choose proper cadence */
1843 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
1844 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
1845 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
1846 p->cidrings = cidrings[p->distinctivering - 1];
1847 } else {
1848 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
1849 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
1850 p->cidrings = p->sendcalleridafter;
1853 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
1854 c = strchr(dest, '/');
1855 if (c)
1856 c++;
1857 if (c && (strlen(c) < p->stripmsd)) {
1858 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
1859 c = NULL;
1861 if (c) {
1862 p->dop.op = DAHDI_DIAL_OP_REPLACE;
1863 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
1864 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
1865 } else {
1866 p->dop.dialstr[0] = '\0';
1868 x = DAHDI_RING;
1869 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
1870 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
1871 ast_mutex_unlock(&p->lock);
1872 return -1;
1874 p->dialing = 1;
1875 } else {
1876 /* Call waiting call */
1877 p->callwaitrings = 0;
1878 if (ast->cid.cid_num)
1879 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
1880 else
1881 p->callwait_num[0] = '\0';
1882 if (ast->cid.cid_name)
1883 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
1884 else
1885 p->callwait_name[0] = '\0';
1886 /* Call waiting tone instead */
1887 if (dahdi_callwait(ast)) {
1888 ast_mutex_unlock(&p->lock);
1889 return -1;
1891 /* Make ring-back */
1892 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
1893 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
1896 n = ast->cid.cid_name;
1897 l = ast->cid.cid_num;
1898 if (l)
1899 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
1900 else
1901 p->lastcid_num[0] = '\0';
1902 if (n)
1903 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
1904 else
1905 p->lastcid_name[0] = '\0';
1906 ast_setstate(ast, AST_STATE_RINGING);
1907 index = dahdi_get_index(ast, p, 0);
1908 if (index > -1) {
1909 p->subs[index].needringing = 1;
1911 break;
1912 case SIG_FXSLS:
1913 case SIG_FXSGS:
1914 case SIG_FXSKS:
1915 case SIG_EMWINK:
1916 case SIG_EM:
1917 case SIG_EM_E1:
1918 case SIG_FEATD:
1919 case SIG_FEATDMF:
1920 case SIG_E911:
1921 case SIG_FGC_CAMA:
1922 case SIG_FGC_CAMAMF:
1923 case SIG_FEATB:
1924 case SIG_SFWINK:
1925 case SIG_SF:
1926 case SIG_SF_FEATD:
1927 case SIG_SF_FEATDMF:
1928 case SIG_FEATDMF_TA:
1929 case SIG_SF_FEATB:
1930 c = strchr(dest, '/');
1931 if (c)
1932 c++;
1933 else
1934 c = "";
1935 if (strlen(c) < p->stripmsd) {
1936 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
1937 ast_mutex_unlock(&p->lock);
1938 return -1;
1940 #ifdef HAVE_PRI
1941 /* Start the trunk, if not GR-303 */
1942 if (!p->pri) {
1943 #endif
1944 x = DAHDI_START;
1945 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
1946 if (res < 0) {
1947 if (errno != EINPROGRESS) {
1948 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
1949 ast_mutex_unlock(&p->lock);
1950 return -1;
1953 #ifdef HAVE_PRI
1955 #endif
1956 ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
1957 p->dop.op = DAHDI_DIAL_OP_REPLACE;
1959 c += p->stripmsd;
1961 switch (mysig) {
1962 case SIG_FEATD:
1963 l = ast->cid.cid_num;
1964 if (l)
1965 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
1966 else
1967 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
1968 break;
1969 case SIG_FEATDMF:
1970 l = ast->cid.cid_num;
1971 if (l)
1972 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
1973 else
1974 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
1975 break;
1976 case SIG_FEATDMF_TA:
1978 const char *cic, *ozz;
1980 /* If you have to go through a Tandem Access point you need to use this */
1981 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
1982 if (!ozz)
1983 ozz = defaultozz;
1984 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
1985 if (!cic)
1986 cic = defaultcic;
1987 if (!ozz || !cic) {
1988 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
1989 ast_mutex_unlock(&p->lock);
1990 return -1;
1992 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
1993 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
1994 p->whichwink = 0;
1996 break;
1997 case SIG_E911:
1998 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
1999 break;
2000 case SIG_FGC_CAMA:
2001 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
2002 break;
2003 case SIG_FGC_CAMAMF:
2004 case SIG_FEATB:
2005 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
2006 break;
2007 default:
2008 if (p->pulse)
2009 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
2010 else
2011 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
2012 break;
2015 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
2016 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
2017 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
2018 p->echorest[sizeof(p->echorest) - 1] = '\0';
2019 p->echobreak = 1;
2020 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
2021 } else
2022 p->echobreak = 0;
2023 if (!res) {
2024 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
2025 int saveerr = errno;
2027 x = DAHDI_ONHOOK;
2028 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
2029 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
2030 ast_mutex_unlock(&p->lock);
2031 return -1;
2033 } else
2034 ast_log(LOG_DEBUG, "Deferring dialing...\n");
2035 p->dialing = 1;
2036 if (ast_strlen_zero(c))
2037 p->dialednone = 1;
2038 ast_setstate(ast, AST_STATE_DIALING);
2039 break;
2040 case 0:
2041 /* Special pseudo -- automatically up*/
2042 ast_setstate(ast, AST_STATE_UP);
2043 break;
2044 case SIG_PRI:
2045 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2046 p->dialdest[0] = '\0';
2047 break;
2048 default:
2049 ast_log(LOG_DEBUG, "not yet implemented\n");
2050 ast_mutex_unlock(&p->lock);
2051 return -1;
2053 #ifdef HAVE_PRI
2054 if (p->pri) {
2055 struct pri_sr *sr;
2056 #ifdef SUPPORT_USERUSER
2057 const char *useruser;
2058 #endif
2059 int pridialplan;
2060 int dp_strip;
2061 int prilocaldialplan;
2062 int ldp_strip;
2063 int exclusive;
2064 const char *rr_str;
2065 int redirect_reason;
2067 c = strchr(dest, '/');
2068 if (c)
2069 c++;
2070 else
2071 c = dest;
2073 l = NULL;
2074 n = NULL;
2076 if (!p->hidecallerid) {
2077 l = ast->cid.cid_num;
2078 if (!p->hidecalleridname) {
2079 n = ast->cid.cid_name;
2084 if (strlen(c) < p->stripmsd) {
2085 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
2086 ast_mutex_unlock(&p->lock);
2087 return -1;
2089 if (mysig != SIG_FXSKS) {
2090 p->dop.op = DAHDI_DIAL_OP_REPLACE;
2091 s = strchr(c + p->stripmsd, 'w');
2092 if (s) {
2093 if (strlen(s) > 1)
2094 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
2095 else
2096 p->dop.dialstr[0] = '\0';
2097 *s = '\0';
2098 } else {
2099 p->dop.dialstr[0] = '\0';
2102 if (pri_grab(p, p->pri)) {
2103 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
2104 ast_mutex_unlock(&p->lock);
2105 return -1;
2107 if (!(p->call = pri_new_call(p->pri->pri))) {
2108 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
2109 pri_rel(p->pri);
2110 ast_mutex_unlock(&p->lock);
2111 return -1;
2113 if (!(sr = pri_sr_new())) {
2114 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
2115 pri_destroycall(p->pri->pri, p->call);
2116 p->call = NULL;
2117 pri_rel(p->pri);
2118 ast_mutex_unlock(&p->lock);
2119 return -1;
2121 if (p->bearer || (mysig == SIG_FXSKS)) {
2122 if (p->bearer) {
2123 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);
2124 p->bearer->call = p->call;
2125 } else
2126 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
2127 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
2129 p->digital = IS_DIGITAL(ast->transfercapability);
2130 /* Add support for exclusive override */
2131 if (p->priexclusive)
2132 exclusive = 1;
2133 else {
2134 /* otherwise, traditional behavior */
2135 if (p->pri->nodetype == PRI_NETWORK)
2136 exclusive = 0;
2137 else
2138 exclusive = 1;
2141 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
2142 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
2143 (p->digital ? -1 :
2144 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
2145 if (p->pri->facilityenable)
2146 pri_facility_enable(p->pri->pri);
2148 if (option_verbose > 2)
2149 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
2150 dp_strip = 0;
2151 pridialplan = p->pri->dialplan - 1;
2152 if (pridialplan == -2) { /* compute dynamically */
2153 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2154 dp_strip = strlen(p->pri->internationalprefix);
2155 pridialplan = PRI_INTERNATIONAL_ISDN;
2156 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2157 dp_strip = strlen(p->pri->nationalprefix);
2158 pridialplan = PRI_NATIONAL_ISDN;
2159 } else {
2160 pridialplan = PRI_LOCAL_ISDN;
2163 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
2165 ldp_strip = 0;
2166 prilocaldialplan = p->pri->localdialplan - 1;
2167 if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
2168 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2169 ldp_strip = strlen(p->pri->internationalprefix);
2170 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
2171 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2172 ldp_strip = strlen(p->pri->nationalprefix);
2173 prilocaldialplan = PRI_NATIONAL_ISDN;
2174 } else {
2175 prilocaldialplan = PRI_LOCAL_ISDN;
2178 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
2179 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
2180 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
2181 if (!strcasecmp(rr_str, "UNKNOWN"))
2182 redirect_reason = 0;
2183 else if (!strcasecmp(rr_str, "BUSY"))
2184 redirect_reason = 1;
2185 else if (!strcasecmp(rr_str, "NO_REPLY"))
2186 redirect_reason = 2;
2187 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
2188 redirect_reason = 15;
2189 else
2190 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2191 } else
2192 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2193 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
2195 #ifdef SUPPORT_USERUSER
2196 /* User-user info */
2197 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
2199 if (useruser)
2200 pri_sr_set_useruser(sr, useruser);
2201 #endif
2203 if (pri_setup(p->pri->pri, p->call, sr)) {
2204 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
2205 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
2206 pri_rel(p->pri);
2207 ast_mutex_unlock(&p->lock);
2208 pri_sr_free(sr);
2209 return -1;
2211 pri_sr_free(sr);
2212 ast_setstate(ast, AST_STATE_DIALING);
2213 pri_rel(p->pri);
2215 #endif
2216 ast_mutex_unlock(&p->lock);
2217 return 0;
2220 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
2222 struct dahdi_pvt *p = *pvt;
2223 /* Remove channel from the list */
2224 if (p->prev)
2225 p->prev->next = p->next;
2226 if (p->next)
2227 p->next->prev = p->prev;
2228 if (p->use_smdi)
2229 ast_smdi_interface_unref(p->smdi_iface);
2230 ast_mutex_destroy(&p->lock);
2231 free(p);
2232 *pvt = NULL;
2235 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
2237 int owned = 0;
2238 int i = 0;
2240 if (!now) {
2241 if (cur->owner) {
2242 owned = 1;
2245 for (i = 0; i < 3; i++) {
2246 if (cur->subs[i].owner) {
2247 owned = 1;
2250 if (!owned) {
2251 if (prev) {
2252 prev->next = cur->next;
2253 if (prev->next)
2254 prev->next->prev = prev;
2255 else
2256 ifend = prev;
2257 } else {
2258 iflist = cur->next;
2259 if (iflist)
2260 iflist->prev = NULL;
2261 else
2262 ifend = NULL;
2264 if (cur->subs[SUB_REAL].dfd > -1) {
2265 dahdi_close(cur->subs[SUB_REAL].dfd);
2267 destroy_dahdi_pvt(&cur);
2269 } else {
2270 if (prev) {
2271 prev->next = cur->next;
2272 if (prev->next)
2273 prev->next->prev = prev;
2274 else
2275 ifend = prev;
2276 } else {
2277 iflist = cur->next;
2278 if (iflist)
2279 iflist->prev = NULL;
2280 else
2281 ifend = NULL;
2283 if (cur->subs[SUB_REAL].dfd > -1) {
2284 dahdi_close(cur->subs[SUB_REAL].dfd);
2286 destroy_dahdi_pvt(&cur);
2288 return 0;
2291 #ifdef HAVE_PRI
2292 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
2294 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
2296 static char *dahdi_send_keypad_facility_descrip =
2297 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2298 " IE over the current channel.\n";
2300 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
2302 /* Data will be our digit string */
2303 struct dahdi_pvt *p;
2304 char *digits = (char *) data;
2306 if (ast_strlen_zero(digits)) {
2307 ast_log(LOG_DEBUG, "No digit string sent to application!\n");
2308 return -1;
2311 p = (struct dahdi_pvt *)chan->tech_pvt;
2313 if (!p) {
2314 ast_log(LOG_DEBUG, "Unable to find technology private\n");
2315 return -1;
2318 ast_mutex_lock(&p->lock);
2320 if (!p->pri || !p->call) {
2321 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
2322 ast_mutex_unlock(&p->lock);
2323 return -1;
2326 if (!pri_grab(p, p->pri)) {
2327 pri_keypad_facility(p->pri->pri, p->call, digits);
2328 pri_rel(p->pri);
2329 } else {
2330 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
2331 ast_mutex_unlock(&p->lock);
2332 return -1;
2335 ast_mutex_unlock(&p->lock);
2337 return 0;
2340 static int pri_is_up(struct dahdi_pri *pri)
2342 int x;
2343 for (x = 0; x < NUM_DCHANS; x++) {
2344 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
2345 return 1;
2347 return 0;
2350 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
2352 bearer->owner = &inuse;
2353 bearer->realcall = crv;
2354 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
2355 if (crv->subs[SUB_REAL].owner)
2356 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
2357 crv->bearer = bearer;
2358 crv->call = bearer->call;
2359 crv->pri = pri;
2360 return 0;
2363 static char *pri_order(int level)
2365 switch (level) {
2366 case 0:
2367 return "Primary";
2368 case 1:
2369 return "Secondary";
2370 case 2:
2371 return "Tertiary";
2372 case 3:
2373 return "Quaternary";
2374 default:
2375 return "<Unknown>";
2379 /* Returns fd of the active dchan */
2380 static int pri_active_dchan_fd(struct dahdi_pri *pri)
2382 int x = -1;
2384 for (x = 0; x < NUM_DCHANS; x++) {
2385 if ((pri->dchans[x] == pri->pri))
2386 break;
2389 return pri->fds[x];
2392 static int pri_find_dchan(struct dahdi_pri *pri)
2394 int oldslot = -1;
2395 struct pri *old;
2396 int newslot = -1;
2397 int x;
2398 old = pri->pri;
2399 for (x = 0; x < NUM_DCHANS; x++) {
2400 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
2401 newslot = x;
2402 if (pri->dchans[x] == old) {
2403 oldslot = x;
2406 if (newslot < 0) {
2407 newslot = 0;
2408 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2409 pri->dchannels[newslot]);
2411 if (old && (oldslot != newslot))
2412 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
2413 pri->dchannels[oldslot], pri->dchannels[newslot]);
2414 pri->pri = pri->dchans[newslot];
2415 return 0;
2417 #endif
2419 static int dahdi_hangup(struct ast_channel *ast)
2421 int res;
2422 int index,x, law;
2423 /*static int restore_gains(struct dahdi_pvt *p);*/
2424 struct dahdi_pvt *p = ast->tech_pvt;
2425 struct dahdi_pvt *tmp = NULL;
2426 struct dahdi_pvt *prev = NULL;
2427 DAHDI_PARAMS par;
2429 if (option_debug)
2430 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
2431 if (!ast->tech_pvt) {
2432 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
2433 return 0;
2436 ast_mutex_lock(&p->lock);
2438 index = dahdi_get_index(ast, p, 1);
2440 if (p->sig == SIG_PRI) {
2441 x = 1;
2442 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
2445 x = 0;
2446 dahdi_confmute(p, 0);
2447 restore_gains(p);
2448 if (p->origcid_num) {
2449 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
2450 free(p->origcid_num);
2451 p->origcid_num = NULL;
2453 if (p->origcid_name) {
2454 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
2455 free(p->origcid_name);
2456 p->origcid_name = NULL;
2458 if (p->dsp)
2459 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
2460 if (p->exten)
2461 p->exten[0] = '\0';
2463 if (option_debug)
2464 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
2465 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
2466 p->ignoredtmf = 0;
2468 if (index > -1) {
2469 /* Real channel, do some fixup */
2470 p->subs[index].owner = NULL;
2471 p->subs[index].needanswer = 0;
2472 p->subs[index].needflash = 0;
2473 p->subs[index].needringing = 0;
2474 p->subs[index].needbusy = 0;
2475 p->subs[index].needcongestion = 0;
2476 p->subs[index].linear = 0;
2477 p->subs[index].needcallerid = 0;
2478 p->polarity = POLARITY_IDLE;
2479 dahdi_setlinear(p->subs[index].dfd, 0);
2480 if (index == SUB_REAL) {
2481 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
2482 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
2483 if (p->subs[SUB_CALLWAIT].inthreeway) {
2484 /* We had flipped over to answer a callwait and now it's gone */
2485 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
2486 /* Move to the call-wait, but un-own us until they flip back. */
2487 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
2488 unalloc_sub(p, SUB_CALLWAIT);
2489 p->owner = NULL;
2490 } else {
2491 /* The three way hung up, but we still have a call wait */
2492 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
2493 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2494 unalloc_sub(p, SUB_THREEWAY);
2495 if (p->subs[SUB_REAL].inthreeway) {
2496 /* This was part of a three way call. Immediately make way for
2497 another call */
2498 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
2499 p->owner = p->subs[SUB_REAL].owner;
2500 } else {
2501 /* This call hasn't been completed yet... Set owner to NULL */
2502 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
2503 p->owner = NULL;
2505 p->subs[SUB_REAL].inthreeway = 0;
2507 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
2508 /* Move to the call-wait and switch back to them. */
2509 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
2510 unalloc_sub(p, SUB_CALLWAIT);
2511 p->owner = p->subs[SUB_REAL].owner;
2512 if (p->owner->_state != AST_STATE_UP)
2513 p->subs[SUB_REAL].needanswer = 1;
2514 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
2515 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
2516 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
2517 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2518 unalloc_sub(p, SUB_THREEWAY);
2519 if (p->subs[SUB_REAL].inthreeway) {
2520 /* This was part of a three way call. Immediately make way for
2521 another call */
2522 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
2523 p->owner = p->subs[SUB_REAL].owner;
2524 } else {
2525 /* This call hasn't been completed yet... Set owner to NULL */
2526 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
2527 p->owner = NULL;
2529 p->subs[SUB_REAL].inthreeway = 0;
2531 } else if (index == SUB_CALLWAIT) {
2532 /* Ditch the holding callwait call, and immediately make it availabe */
2533 if (p->subs[SUB_CALLWAIT].inthreeway) {
2534 /* This is actually part of a three way, placed on hold. Place the third part
2535 on music on hold now */
2536 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
2537 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
2538 S_OR(p->mohsuggest, NULL),
2539 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
2541 p->subs[SUB_THREEWAY].inthreeway = 0;
2542 /* Make it the call wait now */
2543 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
2544 unalloc_sub(p, SUB_THREEWAY);
2545 } else
2546 unalloc_sub(p, SUB_CALLWAIT);
2547 } else if (index == SUB_THREEWAY) {
2548 if (p->subs[SUB_CALLWAIT].inthreeway) {
2549 /* The other party of the three way call is currently in a call-wait state.
2550 Start music on hold for them, and take the main guy out of the third call */
2551 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
2552 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
2553 S_OR(p->mohsuggest, NULL),
2554 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
2556 p->subs[SUB_CALLWAIT].inthreeway = 0;
2558 p->subs[SUB_REAL].inthreeway = 0;
2559 /* If this was part of a three way call index, let us make
2560 another three way call */
2561 unalloc_sub(p, SUB_THREEWAY);
2562 } else {
2563 /* This wasn't any sort of call, but how are we an index? */
2564 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
2568 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
2569 p->owner = NULL;
2570 p->ringt = 0;
2571 p->distinctivering = 0;
2572 p->confirmanswer = 0;
2573 p->cidrings = 1;
2574 p->outgoing = 0;
2575 p->digital = 0;
2576 p->faxhandled = 0;
2577 p->pulsedial = 0;
2578 p->onhooktime = time(NULL);
2579 #ifdef HAVE_PRI
2580 p->proceeding = 0;
2581 p->progress = 0;
2582 p->alerting = 0;
2583 p->setup_ack = 0;
2584 #endif
2585 if (p->dsp) {
2586 ast_dsp_free(p->dsp);
2587 p->dsp = NULL;
2590 law = DAHDI_LAW_DEFAULT;
2591 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
2592 if (res < 0)
2593 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
2594 /* Perform low level hangup if no owner left */
2595 #ifdef HAVE_PRI
2596 if (p->pri) {
2597 #ifdef SUPPORT_USERUSER
2598 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
2599 #endif
2601 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
2602 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
2603 if (!pri_grab(p, p->pri)) {
2604 if (p->alreadyhungup) {
2605 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
2607 #ifdef SUPPORT_USERUSER
2608 pri_call_set_useruser(p->call, useruser);
2609 #endif
2611 pri_hangup(p->pri->pri, p->call, -1);
2612 p->call = NULL;
2613 if (p->bearer)
2614 p->bearer->call = NULL;
2615 } else {
2616 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
2617 int icause = ast->hangupcause ? ast->hangupcause : -1;
2618 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
2620 #ifdef SUPPORT_USERUSER
2621 pri_call_set_useruser(p->call, useruser);
2622 #endif
2624 p->alreadyhungup = 1;
2625 if (p->bearer)
2626 p->bearer->alreadyhungup = 1;
2627 if (cause) {
2628 if (atoi(cause))
2629 icause = atoi(cause);
2631 pri_hangup(p->pri->pri, p->call, icause);
2633 if (res < 0)
2634 ast_log(LOG_WARNING, "pri_disconnect failed\n");
2635 pri_rel(p->pri);
2636 } else {
2637 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
2638 res = -1;
2640 } else {
2641 if (p->bearer)
2642 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
2643 p->call = NULL;
2644 res = 0;
2647 #endif
2648 if (p->sig && (p->sig != SIG_PRI))
2649 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
2650 if (res < 0) {
2651 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
2653 switch (p->sig) {
2654 case SIG_FXOGS:
2655 case SIG_FXOLS:
2656 case SIG_FXOKS:
2657 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
2658 if (!res) {
2659 #if 0
2660 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
2661 #endif
2662 /* If they're off hook, try playing congestion */
2663 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
2664 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
2665 else
2666 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
2668 break;
2669 case SIG_FXSGS:
2670 case SIG_FXSLS:
2671 case SIG_FXSKS:
2672 /* Make sure we're not made available for at least two seconds assuming
2673 we were actually used for an inbound or outbound call. */
2674 if (ast->_state != AST_STATE_RESERVED) {
2675 time(&p->guardtime);
2676 p->guardtime += 2;
2678 break;
2679 default:
2680 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
2682 if (p->cidspill)
2683 free(p->cidspill);
2684 if (p->sig)
2685 dahdi_disable_ec(p);
2686 x = 0;
2687 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
2688 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
2689 p->didtdd = 0;
2690 p->cidspill = NULL;
2691 p->callwaitcas = 0;
2692 p->callwaiting = p->permcallwaiting;
2693 p->hidecallerid = p->permhidecallerid;
2694 p->dialing = 0;
2695 p->rdnis[0] = '\0';
2696 update_conf(p);
2697 reset_conf(p);
2698 /* Restore data mode */
2699 if (p->sig == SIG_PRI) {
2700 x = 0;
2701 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
2703 #ifdef HAVE_PRI
2704 if (p->bearer) {
2705 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
2706 /* Free up the bearer channel as well, and
2707 don't use its file descriptor anymore */
2708 update_conf(p->bearer);
2709 reset_conf(p->bearer);
2710 p->bearer->owner = NULL;
2711 p->bearer->realcall = NULL;
2712 p->bearer = NULL;
2713 p->subs[SUB_REAL].dfd = -1;
2714 p->pri = NULL;
2716 #endif
2717 restart_monitor();
2720 p->callwaitingrepeat = 0;
2721 p->cidcwexpire = 0;
2722 p->oprmode = 0;
2723 ast->tech_pvt = NULL;
2724 ast_mutex_unlock(&p->lock);
2725 ast_module_unref(ast_module_info->self);
2726 if (option_verbose > 2)
2727 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
2729 ast_mutex_lock(&iflock);
2730 tmp = iflist;
2731 prev = NULL;
2732 if (p->destroy) {
2733 while (tmp) {
2734 if (tmp == p) {
2735 destroy_channel(prev, tmp, 0);
2736 break;
2737 } else {
2738 prev = tmp;
2739 tmp = tmp->next;
2743 ast_mutex_unlock(&iflock);
2744 return 0;
2747 static int dahdi_answer(struct ast_channel *ast)
2749 struct dahdi_pvt *p = ast->tech_pvt;
2750 int res = 0;
2751 int index;
2752 int oldstate = ast->_state;
2753 ast_setstate(ast, AST_STATE_UP);
2754 ast_mutex_lock(&p->lock);
2755 index = dahdi_get_index(ast, p, 0);
2756 if (index < 0)
2757 index = SUB_REAL;
2758 /* nothing to do if a radio channel */
2759 if ((p->radio || (p->oprmode < 0))) {
2760 ast_mutex_unlock(&p->lock);
2761 return 0;
2763 switch (p->sig) {
2764 case SIG_FXSLS:
2765 case SIG_FXSGS:
2766 case SIG_FXSKS:
2767 p->ringt = 0;
2768 /* Fall through */
2769 case SIG_EM:
2770 case SIG_EM_E1:
2771 case SIG_EMWINK:
2772 case SIG_FEATD:
2773 case SIG_FEATDMF:
2774 case SIG_FEATDMF_TA:
2775 case SIG_E911:
2776 case SIG_FGC_CAMA:
2777 case SIG_FGC_CAMAMF:
2778 case SIG_FEATB:
2779 case SIG_SF:
2780 case SIG_SFWINK:
2781 case SIG_SF_FEATD:
2782 case SIG_SF_FEATDMF:
2783 case SIG_SF_FEATB:
2784 case SIG_FXOLS:
2785 case SIG_FXOGS:
2786 case SIG_FXOKS:
2787 /* Pick up the line */
2788 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
2789 if (p->hanguponpolarityswitch) {
2790 gettimeofday(&p->polaritydelaytv, NULL);
2792 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
2793 tone_zone_play_tone(p->subs[index].dfd, -1);
2794 p->dialing = 0;
2795 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
2796 if (oldstate == AST_STATE_RINGING) {
2797 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
2798 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
2799 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2800 p->owner = p->subs[SUB_REAL].owner;
2803 if (p->sig & __DAHDI_SIG_FXS) {
2804 dahdi_enable_ec(p);
2805 dahdi_train_ec(p);
2807 break;
2808 #ifdef HAVE_PRI
2809 case SIG_PRI:
2810 /* Send a pri acknowledge */
2811 if (!pri_grab(p, p->pri)) {
2812 p->proceeding = 1;
2813 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
2814 pri_rel(p->pri);
2815 } else {
2816 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
2817 res = -1;
2819 break;
2820 #endif
2821 case 0:
2822 ast_mutex_unlock(&p->lock);
2823 return 0;
2824 default:
2825 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
2826 res = -1;
2828 ast_mutex_unlock(&p->lock);
2829 return res;
2832 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
2834 char *cp;
2835 signed char *scp;
2836 int x;
2837 int index;
2838 struct dahdi_pvt *p = chan->tech_pvt, *pp;
2839 struct oprmode *oprmode;
2842 /* all supported options require data */
2843 if (!data || (datalen < 1)) {
2844 errno = EINVAL;
2845 return -1;
2848 switch (option) {
2849 case AST_OPTION_TXGAIN:
2850 scp = (signed char *) data;
2851 index = dahdi_get_index(chan, p, 0);
2852 if (index < 0) {
2853 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
2854 return -1;
2856 if (option_debug)
2857 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
2858 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
2859 case AST_OPTION_RXGAIN:
2860 scp = (signed char *) data;
2861 index = dahdi_get_index(chan, p, 0);
2862 if (index < 0) {
2863 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
2864 return -1;
2866 if (option_debug)
2867 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
2868 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
2869 case AST_OPTION_TONE_VERIFY:
2870 if (!p->dsp)
2871 break;
2872 cp = (char *) data;
2873 switch (*cp) {
2874 case 1:
2875 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
2876 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
2877 break;
2878 case 2:
2879 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
2880 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
2881 break;
2882 default:
2883 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
2884 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
2885 break;
2887 break;
2888 case AST_OPTION_TDD:
2889 /* turn on or off TDD */
2890 cp = (char *) data;
2891 p->mate = 0;
2892 if (!*cp) { /* turn it off */
2893 if (option_debug)
2894 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
2895 if (p->tdd)
2896 tdd_free(p->tdd);
2897 p->tdd = 0;
2898 break;
2900 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
2901 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
2902 dahdi_disable_ec(p);
2903 /* otherwise, turn it on */
2904 if (!p->didtdd) { /* if havent done it yet */
2905 unsigned char mybuf[41000], *buf;
2906 int size, res, fd, len;
2907 struct pollfd fds[1];
2909 buf = mybuf;
2910 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
2911 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */
2912 len = 40000;
2913 index = dahdi_get_index(chan, p, 0);
2914 if (index < 0) {
2915 ast_log(LOG_WARNING, "No index in TDD?\n");
2916 return -1;
2918 fd = p->subs[index].dfd;
2919 while (len) {
2920 if (ast_check_hangup(chan))
2921 return -1;
2922 size = len;
2923 if (size > READ_SIZE)
2924 size = READ_SIZE;
2925 fds[0].fd = fd;
2926 fds[0].events = POLLPRI | POLLOUT;
2927 fds[0].revents = 0;
2928 res = poll(fds, 1, -1);
2929 if (!res) {
2930 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
2931 continue;
2933 /* if got exception */
2934 if (fds[0].revents & POLLPRI)
2935 return -1;
2936 if (!(fds[0].revents & POLLOUT)) {
2937 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
2938 continue;
2940 res = write(fd, buf, size);
2941 if (res != size) {
2942 if (res == -1) return -1;
2943 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
2944 break;
2946 len -= size;
2947 buf += size;
2949 p->didtdd = 1; /* set to have done it now */
2951 if (*cp == 2) { /* Mate mode */
2952 if (p->tdd)
2953 tdd_free(p->tdd);
2954 p->tdd = 0;
2955 p->mate = 1;
2956 break;
2958 if (!p->tdd) { /* if we dont have one yet */
2959 p->tdd = tdd_new(); /* allocate one */
2961 break;
2962 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
2963 if (!p->dsp)
2964 break;
2965 cp = (char *) data;
2966 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
2967 *cp ? "ON" : "OFF", (int) *cp, chan->name);
2968 p->dtmfrelax = 0;
2969 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
2970 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
2971 break;
2972 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
2973 cp = (char *) data;
2974 if (!*cp) {
2975 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
2976 x = 0;
2977 dahdi_disable_ec(p);
2978 } else {
2979 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
2980 x = 1;
2982 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
2983 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
2984 break;
2985 case AST_OPTION_OPRMODE: /* Operator services mode */
2986 oprmode = (struct oprmode *) data;
2987 pp = oprmode->peer->tech_pvt;
2988 p->oprmode = pp->oprmode = 0;
2989 /* setup peers */
2990 p->oprpeer = pp;
2991 pp->oprpeer = p;
2992 /* setup modes, if any */
2993 if (oprmode->mode)
2995 pp->oprmode = oprmode->mode;
2996 p->oprmode = -oprmode->mode;
2998 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
2999 oprmode->mode, chan->name,oprmode->peer->name);;
3000 break;
3001 case AST_OPTION_ECHOCAN:
3002 cp = (char *) data;
3003 if (*cp) {
3004 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
3005 dahdi_enable_ec(p);
3006 } else {
3007 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
3008 dahdi_disable_ec(p);
3010 break;
3012 errno = 0;
3014 return 0;
3017 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
3019 struct dahdi_pvt *p = chan->tech_pvt;
3021 if (!strcasecmp(data, "rxgain")) {
3022 ast_mutex_lock(&p->lock);
3023 snprintf(buf, len, "%f", p->rxgain);
3024 ast_mutex_unlock(&p->lock);
3025 } else if (!strcasecmp(data, "txgain")) {
3026 ast_mutex_lock(&p->lock);
3027 snprintf(buf, len, "%f", p->txgain);
3028 ast_mutex_unlock(&p->lock);
3029 } else {
3030 ast_copy_string(buf, "", len);
3032 return 0;
3036 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
3038 /* Unlink a specific slave or all slaves/masters from a given master */
3039 int x;
3040 int hasslaves;
3041 if (!master)
3042 return;
3043 if (needlock) {
3044 ast_mutex_lock(&master->lock);
3045 if (slave) {
3046 while (ast_mutex_trylock(&slave->lock)) {
3047 DEADLOCK_AVOIDANCE(&master->lock);
3051 hasslaves = 0;
3052 for (x = 0; x < MAX_SLAVES; x++) {
3053 if (master->slaves[x]) {
3054 if (!slave || (master->slaves[x] == slave)) {
3055 /* Take slave out of the conference */
3056 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
3057 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
3058 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
3059 master->slaves[x]->master = NULL;
3060 master->slaves[x] = NULL;
3061 } else
3062 hasslaves = 1;
3064 if (!hasslaves)
3065 master->inconference = 0;
3067 if (!slave) {
3068 if (master->master) {
3069 /* Take master out of the conference */
3070 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
3071 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
3072 hasslaves = 0;
3073 for (x = 0; x < MAX_SLAVES; x++) {
3074 if (master->master->slaves[x] == master)
3075 master->master->slaves[x] = NULL;
3076 else if (master->master->slaves[x])
3077 hasslaves = 1;
3079 if (!hasslaves)
3080 master->master->inconference = 0;
3082 master->master = NULL;
3084 update_conf(master);
3085 if (needlock) {
3086 if (slave)
3087 ast_mutex_unlock(&slave->lock);
3088 ast_mutex_unlock(&master->lock);
3092 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
3093 int x;
3094 if (!slave || !master) {
3095 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
3096 return;
3098 for (x = 0; x < MAX_SLAVES; x++) {
3099 if (!master->slaves[x]) {
3100 master->slaves[x] = slave;
3101 break;
3104 if (x >= MAX_SLAVES) {
3105 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
3106 master->slaves[MAX_SLAVES - 1] = slave;
3108 if (slave->master)
3109 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
3110 slave->master = master;
3112 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
3115 static void disable_dtmf_detect(struct dahdi_pvt *p)
3117 #ifdef DAHDI_TONEDETECT
3118 int val;
3119 #endif
3121 p->ignoredtmf = 1;
3123 #ifdef DAHDI_TONEDETECT
3124 val = 0;
3125 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
3126 #endif
3127 if (!p->hardwaredtmf && p->dsp) {
3128 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
3129 ast_dsp_set_features(p->dsp, p->dsp_features);
3133 static void enable_dtmf_detect(struct dahdi_pvt *p)
3135 #ifdef DAHDI_TONEDETECT
3136 int val;
3137 #endif
3139 if (p->channel == CHAN_PSEUDO)
3140 return;
3142 p->ignoredtmf = 0;
3144 #ifdef DAHDI_TONEDETECT
3145 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
3146 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
3147 #endif
3148 if (!p->hardwaredtmf && p->dsp) {
3149 p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
3150 ast_dsp_set_features(p->dsp, p->dsp_features);
3154 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)
3156 struct ast_channel *who;
3157 struct dahdi_pvt *p0, *p1, *op0, *op1;
3158 struct dahdi_pvt *master = NULL, *slave = NULL;
3159 struct ast_frame *f;
3160 int inconf = 0;
3161 int nothingok = 1;
3162 int ofd0, ofd1;
3163 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
3164 int os0 = -1, os1 = -1;
3165 int priority = 0;
3166 struct ast_channel *oc0, *oc1;
3167 enum ast_bridge_result res;
3169 #ifdef PRI_2BCT
3170 int triedtopribridge = 0;
3171 q931_call *q931c0 = NULL, *q931c1 = NULL;
3172 #endif
3174 /* For now, don't attempt to native bridge if either channel needs DTMF detection.
3175 There is code below to handle it properly until DTMF is actually seen,
3176 but due to currently unresolved issues it's ignored...
3179 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
3180 return AST_BRIDGE_FAILED_NOWARN;
3182 ast_mutex_lock(&c0->lock);
3183 while (ast_mutex_trylock(&c1->lock)) {
3184 DEADLOCK_AVOIDANCE(&c0->lock);
3187 p0 = c0->tech_pvt;
3188 p1 = c1->tech_pvt;
3189 /* cant do pseudo-channels here */
3190 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
3191 ast_mutex_unlock(&c0->lock);
3192 ast_mutex_unlock(&c1->lock);
3193 return AST_BRIDGE_FAILED_NOWARN;
3196 oi0 = dahdi_get_index(c0, p0, 0);
3197 oi1 = dahdi_get_index(c1, p1, 0);
3198 if ((oi0 < 0) || (oi1 < 0)) {
3199 ast_mutex_unlock(&c0->lock);
3200 ast_mutex_unlock(&c1->lock);
3201 return AST_BRIDGE_FAILED;
3204 op0 = p0 = c0->tech_pvt;
3205 op1 = p1 = c1->tech_pvt;
3206 ofd0 = c0->fds[0];
3207 ofd1 = c1->fds[0];
3208 oc0 = p0->owner;
3209 oc1 = p1->owner;
3211 if (ast_mutex_trylock(&p0->lock)) {
3212 /* Don't block, due to potential for deadlock */
3213 ast_mutex_unlock(&c0->lock);
3214 ast_mutex_unlock(&c1->lock);
3215 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3216 return AST_BRIDGE_RETRY;
3218 if (ast_mutex_trylock(&p1->lock)) {
3219 /* Don't block, due to potential for deadlock */
3220 ast_mutex_unlock(&p0->lock);
3221 ast_mutex_unlock(&c0->lock);
3222 ast_mutex_unlock(&c1->lock);
3223 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3224 return AST_BRIDGE_RETRY;
3227 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3228 if (p0->owner && p1->owner) {
3229 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
3230 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
3231 master = p0;
3232 slave = p1;
3233 inconf = 1;
3234 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
3235 master = p1;
3236 slave = p0;
3237 inconf = 1;
3238 } else {
3239 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
3240 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
3241 p0->channel,
3242 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
3243 p0->subs[SUB_REAL].inthreeway, p0->channel,
3244 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
3245 p1->subs[SUB_REAL].inthreeway);
3247 nothingok = 0;
3249 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
3250 if (p1->subs[SUB_THREEWAY].inthreeway) {
3251 master = p1;
3252 slave = p0;
3253 nothingok = 0;
3255 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
3256 if (p0->subs[SUB_THREEWAY].inthreeway) {
3257 master = p0;
3258 slave = p1;
3259 nothingok = 0;
3261 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
3262 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
3263 don't put us in anything */
3264 if (p1->subs[SUB_CALLWAIT].inthreeway) {
3265 master = p1;
3266 slave = p0;
3267 nothingok = 0;
3269 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
3270 /* Same as previous */
3271 if (p0->subs[SUB_CALLWAIT].inthreeway) {
3272 master = p0;
3273 slave = p1;
3274 nothingok = 0;
3277 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
3278 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
3279 if (master && slave) {
3280 /* Stop any tones, or play ringtone as appropriate. If they're bridged
3281 in an active threeway call with a channel that is ringing, we should
3282 indicate ringing. */
3283 if ((oi1 == SUB_THREEWAY) &&
3284 p1->subs[SUB_THREEWAY].inthreeway &&
3285 p1->subs[SUB_REAL].owner &&
3286 p1->subs[SUB_REAL].inthreeway &&
3287 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3288 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
3289 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
3290 os1 = p1->subs[SUB_REAL].owner->_state;
3291 } else {
3292 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
3293 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
3295 if ((oi0 == SUB_THREEWAY) &&
3296 p0->subs[SUB_THREEWAY].inthreeway &&
3297 p0->subs[SUB_REAL].owner &&
3298 p0->subs[SUB_REAL].inthreeway &&
3299 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3300 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
3301 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
3302 os0 = p0->subs[SUB_REAL].owner->_state;
3303 } else {
3304 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
3305 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
3307 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3308 if (!p0->echocanbridged || !p1->echocanbridged) {
3309 /* Disable echo cancellation if appropriate */
3310 dahdi_disable_ec(p0);
3311 dahdi_disable_ec(p1);
3314 dahdi_link(slave, master);
3315 master->inconference = inconf;
3316 } else if (!nothingok)
3317 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
3319 update_conf(p0);
3320 update_conf(p1);
3321 t0 = p0->subs[SUB_REAL].inthreeway;
3322 t1 = p1->subs[SUB_REAL].inthreeway;
3324 ast_mutex_unlock(&p0->lock);
3325 ast_mutex_unlock(&p1->lock);
3327 ast_mutex_unlock(&c0->lock);
3328 ast_mutex_unlock(&c1->lock);
3330 /* Native bridge failed */
3331 if ((!master || !slave) && !nothingok) {
3332 dahdi_enable_ec(p0);
3333 dahdi_enable_ec(p1);
3334 return AST_BRIDGE_FAILED;
3337 if (option_verbose > 2)
3338 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
3340 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
3341 disable_dtmf_detect(op0);
3343 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
3344 disable_dtmf_detect(op1);
3346 for (;;) {
3347 struct ast_channel *c0_priority[2] = {c0, c1};
3348 struct ast_channel *c1_priority[2] = {c1, c0};
3350 /* Here's our main loop... Start by locking things, looking for private parts,
3351 and then balking if anything is wrong */
3352 ast_mutex_lock(&c0->lock);
3353 while (ast_mutex_trylock(&c1->lock)) {
3354 DEADLOCK_AVOIDANCE(&c0->lock);
3357 p0 = c0->tech_pvt;
3358 p1 = c1->tech_pvt;
3360 if (op0 == p0)
3361 i0 = dahdi_get_index(c0, p0, 1);
3362 if (op1 == p1)
3363 i1 = dahdi_get_index(c1, p1, 1);
3364 ast_mutex_unlock(&c0->lock);
3365 ast_mutex_unlock(&c1->lock);
3367 if (!timeoutms ||
3368 (op0 != p0) ||
3369 (op1 != p1) ||
3370 (ofd0 != c0->fds[0]) ||
3371 (ofd1 != c1->fds[0]) ||
3372 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
3373 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
3374 (oc0 != p0->owner) ||
3375 (oc1 != p1->owner) ||
3376 (t0 != p0->subs[SUB_REAL].inthreeway) ||
3377 (t1 != p1->subs[SUB_REAL].inthreeway) ||
3378 (oi0 != i0) ||
3379 (oi1 != i1)) {
3380 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
3381 op0->channel, oi0, op1->channel, oi1);
3382 res = AST_BRIDGE_RETRY;
3383 goto return_from_bridge;
3386 #ifdef PRI_2BCT
3387 q931c0 = p0->call;
3388 q931c1 = p1->call;
3389 if (p0->transfer && p1->transfer
3390 && q931c0 && q931c1
3391 && !triedtopribridge) {
3392 pri_channel_bridge(q931c0, q931c1);
3393 triedtopribridge = 1;
3395 #endif
3397 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
3398 if (!who) {
3399 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
3400 continue;
3402 f = ast_read(who);
3403 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
3404 *fo = f;
3405 *rc = who;
3406 res = AST_BRIDGE_COMPLETE;
3407 goto return_from_bridge;
3409 if (f->frametype == AST_FRAME_DTMF) {
3410 if ((who == c0) && p0->pulsedial) {
3411 ast_write(c1, f);
3412 } else if ((who == c1) && p1->pulsedial) {
3413 ast_write(c0, f);
3414 } else {
3415 *fo = f;
3416 *rc = who;
3417 res = AST_BRIDGE_COMPLETE;
3418 goto return_from_bridge;
3421 ast_frfree(f);
3423 /* Swap who gets priority */
3424 priority = !priority;
3427 return_from_bridge:
3428 if (op0 == p0)
3429 dahdi_enable_ec(p0);
3431 if (op1 == p1)
3432 dahdi_enable_ec(p1);
3434 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
3435 enable_dtmf_detect(op0);
3437 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
3438 enable_dtmf_detect(op1);
3440 dahdi_unlink(slave, master, 1);
3442 return res;
3445 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
3447 struct dahdi_pvt *p = newchan->tech_pvt;
3448 int x;
3449 ast_mutex_lock(&p->lock);
3450 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
3451 if (p->owner == oldchan) {
3452 p->owner = newchan;
3454 for (x = 0; x < 3; x++)
3455 if (p->subs[x].owner == oldchan) {
3456 if (!x)
3457 dahdi_unlink(NULL, p, 0);
3458 p->subs[x].owner = newchan;
3460 if (newchan->_state == AST_STATE_RINGING)
3461 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
3462 update_conf(p);
3463 ast_mutex_unlock(&p->lock);
3464 return 0;
3467 static int dahdi_ring_phone(struct dahdi_pvt *p)
3469 int x;
3470 int res;
3471 /* Make sure our transmit state is on hook */
3472 x = 0;
3473 x = DAHDI_ONHOOK;
3474 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
3475 do {
3476 x = DAHDI_RING;
3477 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
3478 if (res) {
3479 switch (errno) {
3480 case EBUSY:
3481 case EINTR:
3482 /* Wait just in case */
3483 usleep(10000);
3484 continue;
3485 case EINPROGRESS:
3486 res = 0;
3487 break;
3488 default:
3489 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
3490 res = 0;
3493 } while (res);
3494 return res;
3497 static void *ss_thread(void *data);
3499 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
3501 static int attempt_transfer(struct dahdi_pvt *p)
3503 /* In order to transfer, we need at least one of the channels to
3504 actually be in a call bridge. We can't conference two applications
3505 together (but then, why would we want to?) */
3506 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
3507 /* The three-way person we're about to transfer to could still be in MOH, so
3508 stop if now if appropriate */
3509 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
3510 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
3511 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
3512 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
3514 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
3515 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
3517 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
3518 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
3519 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
3520 return -1;
3522 /* Orphan the channel after releasing the lock */
3523 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3524 unalloc_sub(p, SUB_THREEWAY);
3525 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
3526 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
3527 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
3528 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
3530 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
3531 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
3533 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
3534 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
3535 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
3536 return -1;
3538 /* Three-way is now the REAL */
3539 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3540 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
3541 unalloc_sub(p, SUB_THREEWAY);
3542 /* Tell the caller not to hangup */
3543 return 1;
3544 } else {
3545 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
3546 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
3547 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3548 return -1;
3550 return 0;
3553 static int check_for_conference(struct dahdi_pvt *p)
3555 DAHDI_CONFINFO ci;
3556 /* Fine if we already have a master, etc */
3557 if (p->master || (p->confno > -1))
3558 return 0;
3559 memset(&ci, 0, sizeof(ci));
3560 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
3561 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
3562 return 0;
3564 /* If we have no master and don't have a confno, then
3565 if we're in a conference, it's probably a MeetMe room or
3566 some such, so don't let us 3-way out! */
3567 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
3568 if (option_verbose > 2)
3569 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
3570 return 1;
3572 return 0;
3575 static int get_alarms(struct dahdi_pvt *p)
3577 int res;
3578 DAHDI_SPANINFO zi;
3579 memset(&zi, 0, sizeof(zi));
3580 zi.spanno = p->span;
3581 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi);
3582 if (res < 0) {
3583 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
3584 return 0;
3586 return zi.alarms;
3589 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
3591 struct dahdi_pvt *p = ast->tech_pvt;
3592 struct ast_frame *f = *dest;
3594 if (option_debug)
3595 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
3597 if (p->confirmanswer) {
3598 if (option_debug)
3599 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
3600 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
3601 of a DTMF digit */
3602 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3603 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3604 *dest = &p->subs[index].f;
3605 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
3606 p->confirmanswer = 0;
3607 } else if (p->callwaitcas) {
3608 if ((f->subclass == 'A') || (f->subclass == 'D')) {
3609 if (option_debug)
3610 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
3611 if (p->cidspill)
3612 free(p->cidspill);
3613 send_cwcidspill(p);
3615 if ((f->subclass != 'm') && (f->subclass != 'u'))
3616 p->callwaitcas = 0;
3617 p->subs[index].f.frametype = AST_FRAME_NULL;
3618 p->subs[index].f.subclass = 0;
3619 *dest = &p->subs[index].f;
3620 } else if (f->subclass == 'f') {
3621 /* Fax tone -- Handle and return NULL */
3622 if ((p->callprogress & 0x6) && !p->faxhandled) {
3623 p->faxhandled++;
3624 if (strcmp(ast->exten, "fax")) {
3625 const char *target_context = S_OR(ast->macrocontext, ast->context);
3627 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
3628 if (option_verbose > 2)
3629 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
3630 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
3631 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
3632 if (ast_async_goto(ast, target_context, "fax", 1))
3633 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
3634 } else
3635 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
3636 } else if (option_debug)
3637 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
3638 } else if (option_debug)
3639 ast_log(LOG_DEBUG, "Fax already handled\n");
3640 dahdi_confmute(p, 0);
3641 p->subs[index].f.frametype = AST_FRAME_NULL;
3642 p->subs[index].f.subclass = 0;
3643 *dest = &p->subs[index].f;
3644 } else if (f->subclass == 'm') {
3645 /* Confmute request */
3646 dahdi_confmute(p, 1);
3647 p->subs[index].f.frametype = AST_FRAME_NULL;
3648 p->subs[index].f.subclass = 0;
3649 *dest = &p->subs[index].f;
3650 } else if (f->subclass == 'u') {
3651 /* Unmute */
3652 dahdi_confmute(p, 0);
3653 p->subs[index].f.frametype = AST_FRAME_NULL;
3654 p->subs[index].f.subclass = 0;
3655 *dest = &p->subs[index].f;
3656 } else
3657 dahdi_confmute(p, 0);
3660 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
3662 int res, x;
3663 int index, mysig;
3664 char *c;
3665 struct dahdi_pvt *p = ast->tech_pvt;
3666 pthread_t threadid;
3667 pthread_attr_t attr;
3668 struct ast_channel *chan;
3669 struct ast_frame *f;
3671 index = dahdi_get_index(ast, p, 0);
3672 mysig = p->sig;
3673 if (p->outsigmod > -1)
3674 mysig = p->outsigmod;
3675 p->subs[index].f.frametype = AST_FRAME_NULL;
3676 p->subs[index].f.subclass = 0;
3677 p->subs[index].f.datalen = 0;
3678 p->subs[index].f.samples = 0;
3679 p->subs[index].f.mallocd = 0;
3680 p->subs[index].f.offset = 0;
3681 p->subs[index].f.src = "dahdi_handle_event";
3682 p->subs[index].f.data = NULL;
3683 f = &p->subs[index].f;
3685 if (index < 0)
3686 return &p->subs[index].f;
3687 if (p->fake_event) {
3688 res = p->fake_event;
3689 p->fake_event = 0;
3690 } else
3691 res = dahdi_get_event(p->subs[index].dfd);
3693 if (option_debug)
3694 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
3696 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
3697 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
3699 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
3700 #ifdef HAVE_PRI
3701 if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
3702 /* absorb event */
3703 } else {
3704 #endif
3705 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
3706 p->subs[index].f.subclass = res & 0xff;
3707 #ifdef HAVE_PRI
3709 #endif
3710 dahdi_handle_dtmfup(ast, index, &f);
3711 return f;
3714 if (res & DAHDI_EVENT_DTMFDOWN) {
3715 if (option_debug)
3716 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
3717 /* Mute conference */
3718 dahdi_confmute(p, 1);
3719 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
3720 p->subs[index].f.subclass = res & 0xff;
3721 return &p->subs[index].f;
3724 switch (res) {
3725 #ifdef DAHDI_EVENT_EC_DISABLED
3726 case DAHDI_EVENT_EC_DISABLED:
3727 if (option_verbose > 2)
3728 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
3729 p->echocanon = 0;
3730 break;
3731 #endif
3732 case DAHDI_EVENT_BITSCHANGED:
3733 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
3734 case DAHDI_EVENT_PULSE_START:
3735 /* Stop tone if there's a pulse start and the PBX isn't started */
3736 if (!ast->pbx)
3737 tone_zone_play_tone(p->subs[index].dfd, -1);
3738 break;
3739 case DAHDI_EVENT_DIALCOMPLETE:
3740 if (p->inalarm) break;
3741 if ((p->radio || (p->oprmode < 0))) break;
3742 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
3743 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
3744 return NULL;
3746 if (!x) { /* if not still dialing in driver */
3747 dahdi_enable_ec(p);
3748 if (p->echobreak) {
3749 dahdi_train_ec(p);
3750 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
3751 p->dop.op = DAHDI_DIAL_OP_REPLACE;
3752 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
3753 p->echobreak = 0;
3754 } else {
3755 p->dialing = 0;
3756 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
3757 /* if thru with dialing after offhook */
3758 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
3759 ast_setstate(ast, AST_STATE_UP);
3760 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3761 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3762 break;
3763 } else { /* if to state wait for offhook to dial rest */
3764 /* we now wait for off hook */
3765 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
3768 if (ast->_state == AST_STATE_DIALING) {
3769 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
3770 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
3771 } 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)))) {
3772 ast_setstate(ast, AST_STATE_RINGING);
3773 } else if (!p->answeronpolarityswitch) {
3774 ast_setstate(ast, AST_STATE_UP);
3775 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3776 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3777 /* If aops=0 and hops=1, this is necessary */
3778 p->polarity = POLARITY_REV;
3779 } else {
3780 /* Start clean, so we can catch the change to REV polarity when party answers */
3781 p->polarity = POLARITY_IDLE;
3786 break;
3787 case DAHDI_EVENT_ALARM:
3788 #ifdef HAVE_PRI
3789 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
3790 /* T309 is not enabled : hangup calls when alarm occurs */
3791 if (p->call) {
3792 if (p->pri && p->pri->pri) {
3793 if (!pri_grab(p, p->pri)) {
3794 pri_hangup(p->pri->pri, p->call, -1);
3795 pri_destroycall(p->pri->pri, p->call);
3796 p->call = NULL;
3797 pri_rel(p->pri);
3798 } else
3799 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
3800 } else
3801 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
3803 if (p->owner)
3804 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
3806 if (p->bearer)
3807 p->bearer->inalarm = 1;
3808 else
3809 #endif
3810 p->inalarm = 1;
3811 res = get_alarms(p);
3812 do {
3813 const char *alarm_str = alarm2str(res);
3815 /* hack alert! DAHDI 1.4 now exposes FXO battery as an alarm, but asterisk 1.4
3816 * doesn't know what to do with it. Don't confuse users with log messages. */
3817 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
3818 p->unknown_alarm = 1;
3819 break;
3820 } else {
3821 p->unknown_alarm = 0;
3824 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
3825 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
3826 "Alarm: %s\r\n"
3827 "Channel: %d\r\n",
3828 alarm_str, p->channel);
3829 } while (0);
3830 #ifdef HAVE_LIBPRI
3831 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
3832 /* fall through intentionally */
3833 } else {
3834 break;
3836 #endif
3837 case DAHDI_EVENT_ONHOOK:
3838 if (p->radio) {
3839 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3840 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
3841 break;
3843 if (p->oprmode < 0)
3845 if (p->oprmode != -1) break;
3846 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
3848 /* Make sure it starts ringing */
3849 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
3850 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
3851 save_conference(p->oprpeer);
3852 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
3854 break;
3856 switch (p->sig) {
3857 case SIG_FXOLS:
3858 case SIG_FXOGS:
3859 case SIG_FXOKS:
3860 p->onhooktime = time(NULL);
3861 p->msgstate = -1;
3862 /* Check for some special conditions regarding call waiting */
3863 if (index == SUB_REAL) {
3864 /* The normal line was hung up */
3865 if (p->subs[SUB_CALLWAIT].owner) {
3866 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
3867 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
3868 if (option_verbose > 2)
3869 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
3870 unalloc_sub(p, SUB_CALLWAIT);
3871 #if 0
3872 p->subs[index].needanswer = 0;
3873 p->subs[index].needringing = 0;
3874 #endif
3875 p->callwaitingrepeat = 0;
3876 p->cidcwexpire = 0;
3877 p->owner = NULL;
3878 /* Don't start streaming audio yet if the incoming call isn't up yet */
3879 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
3880 p->dialing = 1;
3881 dahdi_ring_phone(p);
3882 } else if (p->subs[SUB_THREEWAY].owner) {
3883 unsigned int mssinceflash;
3884 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
3885 the private structure -- not especially easy or clean */
3886 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
3887 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
3888 ast_mutex_unlock(&p->lock);
3889 DEADLOCK_AVOIDANCE(&ast->lock);
3890 /* We can grab ast and p in that order, without worry. We should make sure
3891 nothing seriously bad has happened though like some sort of bizarre double
3892 masquerade! */
3893 ast_mutex_lock(&p->lock);
3894 if (p->owner != ast) {
3895 ast_log(LOG_WARNING, "This isn't good...\n");
3896 return NULL;
3899 if (!p->subs[SUB_THREEWAY].owner) {
3900 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
3901 return NULL;
3903 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
3904 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
3905 if (mssinceflash < MIN_MS_SINCE_FLASH) {
3906 /* It hasn't been long enough since the last flashook. This is probably a bounce on
3907 hanging up. Hangup both channels now */
3908 if (p->subs[SUB_THREEWAY].owner)
3909 ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
3910 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3911 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
3912 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3913 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
3914 if (p->transfer) {
3915 /* In any case this isn't a threeway call anymore */
3916 p->subs[SUB_REAL].inthreeway = 0;
3917 p->subs[SUB_THREEWAY].inthreeway = 0;
3918 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
3919 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
3920 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3921 /* Swap subs and dis-own channel */
3922 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3923 p->owner = NULL;
3924 /* Ring the phone */
3925 dahdi_ring_phone(p);
3926 } else {
3927 if ((res = attempt_transfer(p)) < 0) {
3928 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3929 if (p->subs[SUB_THREEWAY].owner)
3930 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3931 } else if (res) {
3932 /* Don't actually hang up at this point */
3933 if (p->subs[SUB_THREEWAY].owner)
3934 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3935 break;
3938 } else {
3939 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3940 if (p->subs[SUB_THREEWAY].owner)
3941 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3943 } else {
3944 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3945 /* Swap subs and dis-own channel */
3946 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3947 p->owner = NULL;
3948 /* Ring the phone */
3949 dahdi_ring_phone(p);
3952 } else {
3953 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
3955 /* Fall through */
3956 default:
3957 dahdi_disable_ec(p);
3958 return NULL;
3960 break;
3961 case DAHDI_EVENT_RINGOFFHOOK:
3962 if (p->inalarm) break;
3963 if (p->oprmode < 0)
3965 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
3967 /* Make sure it stops ringing */
3968 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
3969 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
3970 restore_conference(p->oprpeer);
3972 break;
3974 if (p->radio)
3976 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3977 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
3978 break;
3980 /* for E911, its supposed to wait for offhook then dial
3981 the second half of the dial string */
3982 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
3983 c = strchr(p->dialdest, '/');
3984 if (c)
3985 c++;
3986 else
3987 c = p->dialdest;
3988 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
3989 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
3990 if (strlen(p->dop.dialstr) > 4) {
3991 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
3992 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
3993 p->echorest[sizeof(p->echorest) - 1] = '\0';
3994 p->echobreak = 1;
3995 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
3996 } else
3997 p->echobreak = 0;
3998 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
3999 int saveerr = errno;
4001 x = DAHDI_ONHOOK;
4002 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
4003 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
4004 return NULL;
4006 p->dialing = 1;
4007 return &p->subs[index].f;
4009 switch (p->sig) {
4010 case SIG_FXOLS:
4011 case SIG_FXOGS:
4012 case SIG_FXOKS:
4013 switch (ast->_state) {
4014 case AST_STATE_RINGING:
4015 dahdi_enable_ec(p);
4016 dahdi_train_ec(p);
4017 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4018 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4019 /* Make sure it stops ringing */
4020 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
4021 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
4022 if (p->cidspill) {
4023 /* Cancel any running CallerID spill */
4024 free(p->cidspill);
4025 p->cidspill = NULL;
4027 p->dialing = 0;
4028 p->callwaitcas = 0;
4029 if (p->confirmanswer) {
4030 /* Ignore answer if "confirm answer" is enabled */
4031 p->subs[index].f.frametype = AST_FRAME_NULL;
4032 p->subs[index].f.subclass = 0;
4033 } else if (!ast_strlen_zero(p->dop.dialstr)) {
4034 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
4035 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4036 if (res < 0) {
4037 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4038 p->dop.dialstr[0] = '\0';
4039 return NULL;
4040 } else {
4041 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
4042 p->subs[index].f.frametype = AST_FRAME_NULL;
4043 p->subs[index].f.subclass = 0;
4044 p->dialing = 1;
4046 p->dop.dialstr[0] = '\0';
4047 ast_setstate(ast, AST_STATE_DIALING);
4048 } else
4049 ast_setstate(ast, AST_STATE_UP);
4050 return &p->subs[index].f;
4051 case AST_STATE_DOWN:
4052 ast_setstate(ast, AST_STATE_RING);
4053 ast->rings = 1;
4054 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4055 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
4056 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
4057 return &p->subs[index].f;
4058 case AST_STATE_UP:
4059 /* Make sure it stops ringing */
4060 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
4061 /* Okay -- probably call waiting*/
4062 if (ast_bridged_channel(p->owner))
4063 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4064 p->subs[index].needunhold = 1;
4065 break;
4066 case AST_STATE_RESERVED:
4067 /* Start up dialtone */
4068 if (has_voicemail(p))
4069 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
4070 else
4071 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
4072 break;
4073 default:
4074 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
4076 break;
4077 case SIG_FXSLS:
4078 case SIG_FXSGS:
4079 case SIG_FXSKS:
4080 if (ast->_state == AST_STATE_RING) {
4081 p->ringt = p->ringt_base;
4084 /* Fall through */
4085 case SIG_EM:
4086 case SIG_EM_E1:
4087 case SIG_EMWINK:
4088 case SIG_FEATD:
4089 case SIG_FEATDMF:
4090 case SIG_FEATDMF_TA:
4091 case SIG_E911:
4092 case SIG_FGC_CAMA:
4093 case SIG_FGC_CAMAMF:
4094 case SIG_FEATB:
4095 case SIG_SF:
4096 case SIG_SFWINK:
4097 case SIG_SF_FEATD:
4098 case SIG_SF_FEATDMF:
4099 case SIG_SF_FEATB:
4100 if (ast->_state == AST_STATE_PRERING)
4101 ast_setstate(ast, AST_STATE_RING);
4102 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
4103 if (option_debug)
4104 ast_log(LOG_DEBUG, "Ring detected\n");
4105 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4106 p->subs[index].f.subclass = AST_CONTROL_RING;
4107 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
4108 if (option_debug)
4109 ast_log(LOG_DEBUG, "Line answered\n");
4110 if (p->confirmanswer) {
4111 p->subs[index].f.frametype = AST_FRAME_NULL;
4112 p->subs[index].f.subclass = 0;
4113 } else {
4114 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4115 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4116 ast_setstate(ast, AST_STATE_UP);
4118 } else if (ast->_state != AST_STATE_RING)
4119 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
4120 break;
4121 default:
4122 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
4124 break;
4125 #ifdef DAHDI_EVENT_RINGBEGIN
4126 case DAHDI_EVENT_RINGBEGIN:
4127 switch (p->sig) {
4128 case SIG_FXSLS:
4129 case SIG_FXSGS:
4130 case SIG_FXSKS:
4131 if (ast->_state == AST_STATE_RING) {
4132 p->ringt = p->ringt_base;
4134 break;
4136 break;
4137 #endif
4138 case DAHDI_EVENT_RINGEROFF:
4139 if (p->inalarm) break;
4140 if ((p->radio || (p->oprmode < 0))) break;
4141 ast->rings++;
4142 if ((ast->rings > p->cidrings) && (p->cidspill)) {
4143 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
4144 free(p->cidspill);
4145 p->cidspill = NULL;
4146 p->callwaitcas = 0;
4148 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4149 p->subs[index].f.subclass = AST_CONTROL_RINGING;
4150 break;
4151 case DAHDI_EVENT_RINGERON:
4152 break;
4153 case DAHDI_EVENT_NOALARM:
4154 p->inalarm = 0;
4155 #ifdef HAVE_PRI
4156 /* Extremely unlikely but just in case */
4157 if (p->bearer)
4158 p->bearer->inalarm = 0;
4159 #endif
4160 if (!p->unknown_alarm) {
4161 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
4162 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
4163 "Channel: %d\r\n", p->channel);
4164 } else {
4165 p->unknown_alarm = 0;
4167 break;
4168 case DAHDI_EVENT_WINKFLASH:
4169 if (p->inalarm) break;
4170 if (p->radio) break;
4171 if (p->oprmode < 0) break;
4172 if (p->oprmode > 1)
4174 DAHDI_PARAMS par;
4176 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
4178 if (!par.rxisoffhook)
4180 /* Make sure it stops ringing */
4181 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
4182 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
4183 save_conference(p);
4184 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
4187 break;
4189 /* Remember last time we got a flash-hook */
4190 gettimeofday(&p->flashtime, NULL);
4191 switch (mysig) {
4192 case SIG_FXOLS:
4193 case SIG_FXOGS:
4194 case SIG_FXOKS:
4195 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
4196 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
4197 p->callwaitcas = 0;
4199 if (index != SUB_REAL) {
4200 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
4201 goto winkflashdone;
4204 if (p->subs[SUB_CALLWAIT].owner) {
4205 /* Swap to call-wait */
4206 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
4207 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
4208 p->owner = p->subs[SUB_REAL].owner;
4209 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
4210 if (p->owner->_state == AST_STATE_RINGING) {
4211 ast_setstate(p->owner, AST_STATE_UP);
4212 p->subs[SUB_REAL].needanswer = 1;
4214 p->callwaitingrepeat = 0;
4215 p->cidcwexpire = 0;
4216 /* Start music on hold if appropriate */
4217 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
4218 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
4219 S_OR(p->mohsuggest, NULL),
4220 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4222 p->subs[SUB_CALLWAIT].needhold = 1;
4223 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
4224 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
4225 S_OR(p->mohsuggest, NULL),
4226 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4228 p->subs[SUB_REAL].needunhold = 1;
4229 } else if (!p->subs[SUB_THREEWAY].owner) {
4230 char cid_num[256];
4231 char cid_name[256];
4233 if (!p->threewaycalling) {
4234 /* Just send a flash if no 3-way calling */
4235 p->subs[SUB_REAL].needflash = 1;
4236 goto winkflashdone;
4237 } else if (!check_for_conference(p)) {
4238 if (p->dahditrcallerid && p->owner) {
4239 if (p->owner->cid.cid_num)
4240 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
4241 if (p->owner->cid.cid_name)
4242 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
4244 /* XXX This section needs much more error checking!!! XXX */
4245 /* Start a 3-way call if feasible */
4246 if (!((ast->pbx) ||
4247 (ast->_state == AST_STATE_UP) ||
4248 (ast->_state == AST_STATE_RING))) {
4249 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
4250 goto winkflashdone;
4252 if (alloc_sub(p, SUB_THREEWAY)) {
4253 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
4254 goto winkflashdone;
4256 /* Make new channel */
4257 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
4258 if (p->dahditrcallerid) {
4259 if (!p->origcid_num)
4260 p->origcid_num = ast_strdup(p->cid_num);
4261 if (!p->origcid_name)
4262 p->origcid_name = ast_strdup(p->cid_name);
4263 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
4264 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
4266 /* Swap things around between the three-way and real call */
4267 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4268 /* Disable echo canceller for better dialing */
4269 dahdi_disable_ec(p);
4270 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
4271 if (res)
4272 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
4273 p->owner = chan;
4274 pthread_attr_init(&attr);
4275 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
4276 if (!chan) {
4277 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
4278 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
4279 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
4280 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
4281 dahdi_enable_ec(p);
4282 ast_hangup(chan);
4283 } else {
4284 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
4285 int way3bridge = 0, cdr3way = 0;
4287 if (!other) {
4288 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
4289 } else
4290 way3bridge = 1;
4292 if (p->subs[SUB_THREEWAY].owner->cdr)
4293 cdr3way = 1;
4295 if (option_verbose > 2)
4296 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
4297 /* Start music on hold if appropriate */
4298 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
4299 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
4300 S_OR(p->mohsuggest, NULL),
4301 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4303 p->subs[SUB_THREEWAY].needhold = 1;
4305 pthread_attr_destroy(&attr);
4307 } else {
4308 /* Already have a 3 way call */
4309 if (p->subs[SUB_THREEWAY].inthreeway) {
4310 /* Call is already up, drop the last person */
4311 if (option_debug)
4312 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
4313 /* If the primary call isn't answered yet, use it */
4314 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
4315 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
4316 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4317 p->owner = p->subs[SUB_REAL].owner;
4319 /* Drop the last call and stop the conference */
4320 if (option_verbose > 2)
4321 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
4322 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4323 p->subs[SUB_REAL].inthreeway = 0;
4324 p->subs[SUB_THREEWAY].inthreeway = 0;
4325 } else {
4326 /* Lets see what we're up to */
4327 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
4328 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
4329 int otherindex = SUB_THREEWAY;
4330 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
4331 int way3bridge = 0, cdr3way = 0;
4333 if (!other) {
4334 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
4335 } else
4336 way3bridge = 1;
4338 if (p->subs[SUB_THREEWAY].owner->cdr)
4339 cdr3way = 1;
4341 if (option_verbose > 2)
4342 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);
4343 /* Put them in the threeway, and flip */
4344 p->subs[SUB_THREEWAY].inthreeway = 1;
4345 p->subs[SUB_REAL].inthreeway = 1;
4346 if (ast->_state == AST_STATE_UP) {
4347 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4348 otherindex = SUB_REAL;
4350 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
4351 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
4352 p->subs[otherindex].needunhold = 1;
4353 p->owner = p->subs[SUB_REAL].owner;
4354 if (ast->_state == AST_STATE_RINGING) {
4355 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
4356 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
4357 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
4359 } else {
4360 if (option_verbose > 2)
4361 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
4362 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4363 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4364 p->owner = p->subs[SUB_REAL].owner;
4365 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
4366 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
4367 p->subs[SUB_REAL].needunhold = 1;
4368 dahdi_enable_ec(p);
4373 winkflashdone:
4374 update_conf(p);
4375 break;
4376 case SIG_EM:
4377 case SIG_EM_E1:
4378 case SIG_EMWINK:
4379 case SIG_FEATD:
4380 case SIG_SF:
4381 case SIG_SFWINK:
4382 case SIG_SF_FEATD:
4383 case SIG_FXSLS:
4384 case SIG_FXSGS:
4385 if (p->dialing)
4386 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
4387 else
4388 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
4389 break;
4390 case SIG_FEATDMF_TA:
4391 switch (p->whichwink) {
4392 case 0:
4393 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
4394 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
4395 break;
4396 case 1:
4397 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
4398 break;
4399 case 2:
4400 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
4401 return NULL;
4403 p->whichwink++;
4404 /* Fall through */
4405 case SIG_FEATDMF:
4406 case SIG_E911:
4407 case SIG_FGC_CAMAMF:
4408 case SIG_FGC_CAMA:
4409 case SIG_FEATB:
4410 case SIG_SF_FEATDMF:
4411 case SIG_SF_FEATB:
4412 /* FGD MF *Must* wait for wink */
4413 if (!ast_strlen_zero(p->dop.dialstr)) {
4414 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4415 if (res < 0) {
4416 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4417 p->dop.dialstr[0] = '\0';
4418 return NULL;
4419 } else
4420 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
4422 p->dop.dialstr[0] = '\0';
4423 break;
4424 default:
4425 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
4427 break;
4428 case DAHDI_EVENT_HOOKCOMPLETE:
4429 if (p->inalarm) break;
4430 if ((p->radio || (p->oprmode < 0))) break;
4431 switch (mysig) {
4432 case SIG_FXSLS: /* only interesting for FXS */
4433 case SIG_FXSGS:
4434 case SIG_FXSKS:
4435 case SIG_EM:
4436 case SIG_EM_E1:
4437 case SIG_EMWINK:
4438 case SIG_FEATD:
4439 case SIG_SF:
4440 case SIG_SFWINK:
4441 case SIG_SF_FEATD:
4442 if (!ast_strlen_zero(p->dop.dialstr)) {
4443 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4444 if (res < 0) {
4445 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4446 p->dop.dialstr[0] = '\0';
4447 return NULL;
4448 } else
4449 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
4451 p->dop.dialstr[0] = '\0';
4452 p->dop.op = DAHDI_DIAL_OP_REPLACE;
4453 break;
4454 case SIG_FEATDMF:
4455 case SIG_FEATDMF_TA:
4456 case SIG_E911:
4457 case SIG_FGC_CAMA:
4458 case SIG_FGC_CAMAMF:
4459 case SIG_FEATB:
4460 case SIG_SF_FEATDMF:
4461 case SIG_SF_FEATB:
4462 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
4463 break;
4464 default:
4465 break;
4467 break;
4468 case DAHDI_EVENT_POLARITY:
4470 * If we get a Polarity Switch event, check to see
4471 * if we should change the polarity state and
4472 * mark the channel as UP or if this is an indication
4473 * of remote end disconnect.
4475 if (p->polarity == POLARITY_IDLE) {
4476 p->polarity = POLARITY_REV;
4477 if (p->answeronpolarityswitch &&
4478 ((ast->_state == AST_STATE_DIALING) ||
4479 (ast->_state == AST_STATE_RINGING))) {
4480 ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
4481 ast_setstate(p->owner, AST_STATE_UP);
4482 if (p->hanguponpolarityswitch) {
4483 gettimeofday(&p->polaritydelaytv, NULL);
4485 } else
4486 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
4488 /* Removed else statement from here as it was preventing hangups from ever happening*/
4489 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
4490 if (p->hanguponpolarityswitch &&
4491 (p->polarityonanswerdelay > 0) &&
4492 (p->polarity == POLARITY_REV) &&
4493 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
4494 /* Added log_debug information below to provide a better indication of what is going on */
4495 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) );
4497 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
4498 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
4499 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
4500 p->polarity = POLARITY_IDLE;
4501 } else {
4502 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);
4504 } else {
4505 p->polarity = POLARITY_IDLE;
4506 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
4508 /* Added more log_debug information below to provide a better indication of what is going on */
4509 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) );
4510 break;
4511 default:
4512 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
4514 return &p->subs[index].f;
4517 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
4519 struct dahdi_pvt *p = ast->tech_pvt;
4520 int res;
4521 int usedindex=-1;
4522 int index;
4523 struct ast_frame *f;
4526 index = dahdi_get_index(ast, p, 1);
4528 p->subs[index].f.frametype = AST_FRAME_NULL;
4529 p->subs[index].f.datalen = 0;
4530 p->subs[index].f.samples = 0;
4531 p->subs[index].f.mallocd = 0;
4532 p->subs[index].f.offset = 0;
4533 p->subs[index].f.subclass = 0;
4534 p->subs[index].f.delivery = ast_tv(0,0);
4535 p->subs[index].f.src = "dahdi_exception";
4536 p->subs[index].f.data = NULL;
4539 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
4540 /* If nobody owns us, absorb the event appropriately, otherwise
4541 we loop indefinitely. This occurs when, during call waiting, the
4542 other end hangs up our channel so that it no longer exists, but we
4543 have neither FLASH'd nor ONHOOK'd to signify our desire to
4544 change to the other channel. */
4545 if (p->fake_event) {
4546 res = p->fake_event;
4547 p->fake_event = 0;
4548 } else
4549 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
4550 /* Switch to real if there is one and this isn't something really silly... */
4551 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
4552 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
4553 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
4554 p->owner = p->subs[SUB_REAL].owner;
4555 if (p->owner && ast_bridged_channel(p->owner))
4556 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4557 p->subs[SUB_REAL].needunhold = 1;
4559 switch (res) {
4560 case DAHDI_EVENT_ONHOOK:
4561 dahdi_disable_ec(p);
4562 if (p->owner) {
4563 if (option_verbose > 2)
4564 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
4565 dahdi_ring_phone(p);
4566 p->callwaitingrepeat = 0;
4567 p->cidcwexpire = 0;
4568 } else
4569 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
4570 update_conf(p);
4571 break;
4572 case DAHDI_EVENT_RINGOFFHOOK:
4573 dahdi_enable_ec(p);
4574 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
4575 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
4576 p->subs[SUB_REAL].needanswer = 1;
4577 p->dialing = 0;
4579 break;
4580 case DAHDI_EVENT_HOOKCOMPLETE:
4581 case DAHDI_EVENT_RINGERON:
4582 case DAHDI_EVENT_RINGEROFF:
4583 /* Do nothing */
4584 break;
4585 case DAHDI_EVENT_WINKFLASH:
4586 gettimeofday(&p->flashtime, NULL);
4587 if (p->owner) {
4588 if (option_verbose > 2)
4589 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
4590 if (p->owner->_state != AST_STATE_UP) {
4591 /* Answer if necessary */
4592 usedindex = dahdi_get_index(p->owner, p, 0);
4593 if (usedindex > -1) {
4594 p->subs[usedindex].needanswer = 1;
4596 ast_setstate(p->owner, AST_STATE_UP);
4598 p->callwaitingrepeat = 0;
4599 p->cidcwexpire = 0;
4600 if (ast_bridged_channel(p->owner))
4601 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4602 p->subs[SUB_REAL].needunhold = 1;
4603 } else
4604 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
4605 update_conf(p);
4606 break;
4607 default:
4608 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
4610 f = &p->subs[index].f;
4611 return f;
4613 if (!(p->radio || (p->oprmode < 0)) && option_debug)
4614 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
4615 /* If it's not us, return NULL immediately */
4616 if (ast != p->owner) {
4617 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
4618 f = &p->subs[index].f;
4619 return f;
4621 f = dahdi_handle_event(ast);
4622 return f;
4625 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
4627 struct dahdi_pvt *p = ast->tech_pvt;
4628 struct ast_frame *f;
4629 ast_mutex_lock(&p->lock);
4630 f = __dahdi_exception(ast);
4631 ast_mutex_unlock(&p->lock);
4632 return f;
4635 static struct ast_frame *dahdi_read(struct ast_channel *ast)
4637 struct dahdi_pvt *p = ast->tech_pvt;
4638 int res;
4639 int index;
4640 void *readbuf;
4641 struct ast_frame *f;
4643 while (ast_mutex_trylock(&p->lock)) {
4644 DEADLOCK_AVOIDANCE(&ast->lock);
4647 index = dahdi_get_index(ast, p, 0);
4649 /* Hang up if we don't really exist */
4650 if (index < 0) {
4651 ast_log(LOG_WARNING, "We dont exist?\n");
4652 ast_mutex_unlock(&p->lock);
4653 return NULL;
4656 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
4658 p->subs[index].f.frametype = AST_FRAME_NULL;
4659 p->subs[index].f.datalen = 0;
4660 p->subs[index].f.samples = 0;
4661 p->subs[index].f.mallocd = 0;
4662 p->subs[index].f.offset = 0;
4663 p->subs[index].f.subclass = 0;
4664 p->subs[index].f.delivery = ast_tv(0,0);
4665 p->subs[index].f.src = "dahdi_read";
4666 p->subs[index].f.data = NULL;
4668 /* make sure it sends initial key state as first frame */
4669 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
4671 DAHDI_PARAMS ps;
4673 ps.channo = p->channel;
4674 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
4675 ast_mutex_unlock(&p->lock);
4676 return NULL;
4678 p->firstradio = 1;
4679 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4680 if (ps.rxisoffhook)
4682 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
4684 else
4686 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
4688 ast_mutex_unlock(&p->lock);
4689 return &p->subs[index].f;
4691 if (p->ringt == 1) {
4692 ast_mutex_unlock(&p->lock);
4693 return NULL;
4695 else if (p->ringt > 0)
4696 p->ringt--;
4698 if (p->subs[index].needringing) {
4699 /* Send ringing frame if requested */
4700 p->subs[index].needringing = 0;
4701 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4702 p->subs[index].f.subclass = AST_CONTROL_RINGING;
4703 ast_setstate(ast, AST_STATE_RINGING);
4704 ast_mutex_unlock(&p->lock);
4705 return &p->subs[index].f;
4708 if (p->subs[index].needbusy) {
4709 /* Send busy frame if requested */
4710 p->subs[index].needbusy = 0;
4711 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4712 p->subs[index].f.subclass = AST_CONTROL_BUSY;
4713 ast_mutex_unlock(&p->lock);
4714 return &p->subs[index].f;
4717 if (p->subs[index].needcongestion) {
4718 /* Send congestion frame if requested */
4719 p->subs[index].needcongestion = 0;
4720 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4721 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
4722 ast_mutex_unlock(&p->lock);
4723 return &p->subs[index].f;
4726 if (p->subs[index].needcallerid) {
4727 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
4728 S_OR(p->lastcid_name, NULL),
4729 S_OR(p->lastcid_num, NULL)
4731 p->subs[index].needcallerid = 0;
4734 if (p->subs[index].needanswer) {
4735 /* Send answer frame if requested */
4736 p->subs[index].needanswer = 0;
4737 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4738 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4739 ast_mutex_unlock(&p->lock);
4740 return &p->subs[index].f;
4743 if (p->subs[index].needflash) {
4744 /* Send answer frame if requested */
4745 p->subs[index].needflash = 0;
4746 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4747 p->subs[index].f.subclass = AST_CONTROL_FLASH;
4748 ast_mutex_unlock(&p->lock);
4749 return &p->subs[index].f;
4752 if (p->subs[index].needhold) {
4753 /* Send answer frame if requested */
4754 p->subs[index].needhold = 0;
4755 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4756 p->subs[index].f.subclass = AST_CONTROL_HOLD;
4757 ast_mutex_unlock(&p->lock);
4758 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
4759 return &p->subs[index].f;
4762 if (p->subs[index].needunhold) {
4763 /* Send answer frame if requested */
4764 p->subs[index].needunhold = 0;
4765 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4766 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
4767 ast_mutex_unlock(&p->lock);
4768 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
4769 return &p->subs[index].f;
4772 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
4773 if (!p->subs[index].linear) {
4774 p->subs[index].linear = 1;
4775 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
4776 if (res)
4777 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
4779 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
4780 (ast->rawreadformat == AST_FORMAT_ALAW)) {
4781 if (p->subs[index].linear) {
4782 p->subs[index].linear = 0;
4783 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
4784 if (res)
4785 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
4787 } else {
4788 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
4789 ast_mutex_unlock(&p->lock);
4790 return NULL;
4792 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
4793 CHECK_BLOCKING(ast);
4794 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
4795 ast_clear_flag(ast, AST_FLAG_BLOCKING);
4796 /* Check for hangup */
4797 if (res < 0) {
4798 f = NULL;
4799 if (res == -1) {
4800 if (errno == EAGAIN) {
4801 /* Return "NULL" frame if there is nobody there */
4802 ast_mutex_unlock(&p->lock);
4803 return &p->subs[index].f;
4804 } else if (errno == ELAST) {
4805 f = __dahdi_exception(ast);
4806 } else
4807 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
4809 ast_mutex_unlock(&p->lock);
4810 return f;
4812 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
4813 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
4814 f = __dahdi_exception(ast);
4815 ast_mutex_unlock(&p->lock);
4816 return f;
4818 if (p->tdd) { /* if in TDD mode, see if we receive that */
4819 int c;
4821 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
4822 if (c < 0) {
4823 ast_log(LOG_DEBUG,"tdd_feed failed\n");
4824 ast_mutex_unlock(&p->lock);
4825 return NULL;
4827 if (c) { /* if a char to return */
4828 p->subs[index].f.subclass = 0;
4829 p->subs[index].f.frametype = AST_FRAME_TEXT;
4830 p->subs[index].f.mallocd = 0;
4831 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
4832 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
4833 p->subs[index].f.datalen = 1;
4834 *((char *) p->subs[index].f.data) = c;
4835 ast_mutex_unlock(&p->lock);
4836 return &p->subs[index].f;
4839 /* Ensure the CW timer decrements only on a single subchannel */
4840 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
4841 p->callwaitingrepeat--;
4843 if (p->cidcwexpire)
4844 p->cidcwexpire--;
4845 /* Repeat callwaiting */
4846 if (p->callwaitingrepeat == 1) {
4847 p->callwaitrings++;
4848 dahdi_callwait(ast);
4850 /* Expire CID/CW */
4851 if (p->cidcwexpire == 1) {
4852 if (option_verbose > 2)
4853 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
4854 restore_conference(p);
4856 if (p->subs[index].linear) {
4857 p->subs[index].f.datalen = READ_SIZE * 2;
4858 } else
4859 p->subs[index].f.datalen = READ_SIZE;
4861 /* Handle CallerID Transmission */
4862 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
4863 send_callerid(p);
4866 p->subs[index].f.frametype = AST_FRAME_VOICE;
4867 p->subs[index].f.subclass = ast->rawreadformat;
4868 p->subs[index].f.samples = READ_SIZE;
4869 p->subs[index].f.mallocd = 0;
4870 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
4871 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
4872 #if 0
4873 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
4874 #endif
4875 if (p->dialing || /* Transmitting something */
4876 (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
4877 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
4879 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
4880 don't send anything */
4881 p->subs[index].f.frametype = AST_FRAME_NULL;
4882 p->subs[index].f.subclass = 0;
4883 p->subs[index].f.samples = 0;
4884 p->subs[index].f.mallocd = 0;
4885 p->subs[index].f.offset = 0;
4886 p->subs[index].f.data = NULL;
4887 p->subs[index].f.datalen= 0;
4889 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
4890 /* Perform busy detection. etc on the dahdi line */
4891 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
4892 if (f) {
4893 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
4894 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
4895 /* Treat this as a "hangup" instead of a "busy" on the assumption that
4896 a busy */
4897 f = NULL;
4899 } else if (f->frametype == AST_FRAME_DTMF) {
4900 #ifdef HAVE_PRI
4901 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
4902 /* Don't accept in-band DTMF when in overlap dial mode */
4903 f->frametype = AST_FRAME_NULL;
4904 f->subclass = 0;
4906 #endif
4907 /* DSP clears us of being pulse */
4908 p->pulsedial = 0;
4911 } else
4912 f = &p->subs[index].f;
4914 if (f && (f->frametype == AST_FRAME_DTMF))
4915 dahdi_handle_dtmfup(ast, index, &f);
4917 /* If we have a fake_event, trigger exception to handle it */
4918 if (p->fake_event)
4919 ast_set_flag(ast, AST_FLAG_EXCEPTION);
4921 ast_mutex_unlock(&p->lock);
4922 return f;
4925 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
4927 int sent=0;
4928 int size;
4929 int res;
4930 int fd;
4931 fd = p->subs[index].dfd;
4932 while (len) {
4933 size = len;
4934 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
4935 size = (linear ? READ_SIZE * 2 : READ_SIZE);
4936 res = write(fd, buf, size);
4937 if (res != size) {
4938 if (option_debug)
4939 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
4940 return sent;
4942 len -= size;
4943 buf += size;
4945 return sent;
4948 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
4950 struct dahdi_pvt *p = ast->tech_pvt;
4951 int res;
4952 int index;
4953 index = dahdi_get_index(ast, p, 0);
4954 if (index < 0) {
4955 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
4956 return -1;
4959 #if 0
4960 #ifdef HAVE_PRI
4961 ast_mutex_lock(&p->lock);
4962 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
4963 if (p->pri->pri) {
4964 if (!pri_grab(p, p->pri)) {
4965 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
4966 pri_rel(p->pri);
4967 } else
4968 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
4970 p->proceeding=1;
4972 ast_mutex_unlock(&p->lock);
4973 #endif
4974 #endif
4975 /* Write a frame of (presumably voice) data */
4976 if (frame->frametype != AST_FRAME_VOICE) {
4977 if (frame->frametype != AST_FRAME_IMAGE)
4978 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
4979 return 0;
4981 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
4982 (frame->subclass != AST_FORMAT_ULAW) &&
4983 (frame->subclass != AST_FORMAT_ALAW)) {
4984 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
4985 return -1;
4987 if (p->dialing) {
4988 if (option_debug)
4989 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
4990 return 0;
4992 if (!p->owner) {
4993 if (option_debug)
4994 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
4995 return 0;
4997 if (p->cidspill) {
4998 if (option_debug)
4999 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
5000 return 0;
5002 /* Return if it's not valid data */
5003 if (!frame->data || !frame->datalen)
5004 return 0;
5006 if (frame->subclass == AST_FORMAT_SLINEAR) {
5007 if (!p->subs[index].linear) {
5008 p->subs[index].linear = 1;
5009 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
5010 if (res)
5011 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
5013 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
5014 } else {
5015 /* x-law already */
5016 if (p->subs[index].linear) {
5017 p->subs[index].linear = 0;
5018 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
5019 if (res)
5020 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
5022 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
5024 if (res < 0) {
5025 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
5026 return -1;
5028 return 0;
5031 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
5033 struct dahdi_pvt *p = chan->tech_pvt;
5034 int res=-1;
5035 int index;
5036 int func = DAHDI_FLASH;
5037 ast_mutex_lock(&p->lock);
5038 index = dahdi_get_index(chan, p, 0);
5039 if (option_debug)
5040 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
5041 if (index == SUB_REAL) {
5042 switch (condition) {
5043 case AST_CONTROL_BUSY:
5044 #ifdef HAVE_PRI
5045 if (p->priindication_oob && p->sig == SIG_PRI) {
5046 chan->hangupcause = AST_CAUSE_USER_BUSY;
5047 chan->_softhangup |= AST_SOFTHANGUP_DEV;
5048 res = 0;
5049 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5050 if (p->pri->pri) {
5051 if (!pri_grab(p, p->pri)) {
5052 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5053 pri_rel(p->pri);
5055 else
5056 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5058 p->progress = 1;
5059 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
5060 } else
5061 #endif
5062 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
5063 break;
5064 case AST_CONTROL_RINGING:
5065 #ifdef HAVE_PRI
5066 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
5067 if (p->pri->pri) {
5068 if (!pri_grab(p, p->pri)) {
5069 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5070 pri_rel(p->pri);
5072 else
5073 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5075 p->alerting = 1;
5077 #endif
5078 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
5079 if (chan->_state != AST_STATE_UP) {
5080 if ((chan->_state != AST_STATE_RING) ||
5081 ((p->sig != SIG_FXSKS) &&
5082 (p->sig != SIG_FXSLS) &&
5083 (p->sig != SIG_FXSGS)))
5084 ast_setstate(chan, AST_STATE_RINGING);
5086 break;
5087 case AST_CONTROL_PROCEEDING:
5088 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
5089 #ifdef HAVE_PRI
5090 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5091 if (p->pri->pri) {
5092 if (!pri_grab(p, p->pri)) {
5093 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5094 pri_rel(p->pri);
5096 else
5097 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5099 p->proceeding = 1;
5101 #endif
5102 /* don't continue in ast_indicate */
5103 res = 0;
5104 break;
5105 case AST_CONTROL_PROGRESS:
5106 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
5107 #ifdef HAVE_PRI
5108 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */
5109 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5110 if (p->pri->pri) {
5111 if (!pri_grab(p, p->pri)) {
5112 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5113 pri_rel(p->pri);
5115 else
5116 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5118 p->progress = 1;
5120 #endif
5121 /* don't continue in ast_indicate */
5122 res = 0;
5123 break;
5124 case AST_CONTROL_CONGESTION:
5125 chan->hangupcause = AST_CAUSE_CONGESTION;
5126 #ifdef HAVE_PRI
5127 if (p->priindication_oob && p->sig == SIG_PRI) {
5128 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
5129 chan->_softhangup |= AST_SOFTHANGUP_DEV;
5130 res = 0;
5131 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5132 if (p->pri) {
5133 if (!pri_grab(p, p->pri)) {
5134 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5135 pri_rel(p->pri);
5136 } else
5137 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5139 p->progress = 1;
5140 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5141 } else
5142 #endif
5143 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5144 break;
5145 case AST_CONTROL_HOLD:
5146 #ifdef HAVE_PRI
5147 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
5148 if (!pri_grab(p, p->pri)) {
5149 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
5150 pri_rel(p->pri);
5151 } else
5152 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5153 } else
5154 #endif
5155 ast_moh_start(chan, data, p->mohinterpret);
5156 break;
5157 case AST_CONTROL_UNHOLD:
5158 #ifdef HAVE_PRI
5159 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
5160 if (!pri_grab(p, p->pri)) {
5161 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
5162 pri_rel(p->pri);
5163 } else
5164 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5165 } else
5166 #endif
5167 ast_moh_stop(chan);
5168 break;
5169 case AST_CONTROL_RADIO_KEY:
5170 if (p->radio)
5171 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
5172 res = 0;
5173 break;
5174 case AST_CONTROL_RADIO_UNKEY:
5175 if (p->radio)
5176 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
5177 res = 0;
5178 break;
5179 case AST_CONTROL_FLASH:
5180 /* flash hookswitch */
5181 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
5182 /* Clear out the dial buffer */
5183 p->dop.dialstr[0] = '\0';
5184 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
5185 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
5186 chan->name, strerror(errno));
5187 } else
5188 res = 0;
5189 } else
5190 res = 0;
5191 break;
5192 case AST_CONTROL_SRCUPDATE:
5193 res = 0;
5194 break;
5195 case -1:
5196 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5197 break;
5199 } else
5200 res = 0;
5201 ast_mutex_unlock(&p->lock);
5202 return res;
5205 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
5207 struct ast_channel *tmp;
5208 int deflaw;
5209 int res;
5210 int x,y;
5211 int features;
5212 char *b2 = NULL;
5213 DAHDI_PARAMS ps;
5214 if (i->subs[index].owner) {
5215 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
5216 return NULL;
5218 y = 1;
5219 do {
5220 if (b2)
5221 free(b2);
5222 #ifdef HAVE_PRI
5223 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
5224 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
5225 else
5226 #endif
5227 if (i->channel == CHAN_PSEUDO)
5228 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
5229 else
5230 b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
5231 for (x = 0; x < 3; x++) {
5232 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name))
5233 break;
5235 y++;
5236 } while (x < 3);
5237 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", b2);
5238 if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
5239 free(b2);
5240 if (!tmp)
5241 return NULL;
5242 tmp->tech = &dahdi_tech;
5243 ps.channo = i->channel;
5244 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
5245 if (res) {
5246 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
5247 ps.curlaw = DAHDI_LAW_MULAW;
5249 if (ps.curlaw == DAHDI_LAW_ALAW)
5250 deflaw = AST_FORMAT_ALAW;
5251 else
5252 deflaw = AST_FORMAT_ULAW;
5253 if (law) {
5254 if (law == DAHDI_LAW_ALAW)
5255 deflaw = AST_FORMAT_ALAW;
5256 else
5257 deflaw = AST_FORMAT_ULAW;
5259 tmp->fds[0] = i->subs[index].dfd;
5260 tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
5261 /* Start out assuming ulaw since it's smaller :) */
5262 tmp->rawreadformat = deflaw;
5263 tmp->readformat = deflaw;
5264 tmp->rawwriteformat = deflaw;
5265 tmp->writeformat = deflaw;
5266 i->subs[index].linear = 0;
5267 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
5268 features = 0;
5269 if (index == SUB_REAL) {
5270 if (i->busydetect && CANBUSYDETECT(i))
5271 features |= DSP_FEATURE_BUSY_DETECT;
5272 if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
5273 features |= DSP_FEATURE_CALL_PROGRESS;
5274 if ((!i->outgoing && (i->callprogress & 4)) ||
5275 (i->outgoing && (i->callprogress & 2))) {
5276 features |= DSP_FEATURE_FAX_DETECT;
5278 #ifdef DAHDI_TONEDETECT
5279 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
5280 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
5281 #endif
5282 i->hardwaredtmf = 0;
5283 features |= DSP_FEATURE_DTMF_DETECT;
5284 #ifdef DAHDI_TONEDETECT
5285 } else if (NEED_MFDETECT(i)) {
5286 i->hardwaredtmf = 1;
5287 features |= DSP_FEATURE_DTMF_DETECT;
5289 #endif
5291 if (features) {
5292 if (i->dsp) {
5293 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
5294 } else {
5295 if (i->channel != CHAN_PSEUDO)
5296 i->dsp = ast_dsp_new();
5297 else
5298 i->dsp = NULL;
5299 if (i->dsp) {
5300 i->dsp_features = features & ~DSP_PROGRESS_TALK;
5301 #ifdef HAVE_PRI
5302 /* We cannot do progress detection until receives PROGRESS message */
5303 if (i->outgoing && (i->sig == SIG_PRI)) {
5304 /* Remember requested DSP features, don't treat
5305 talking as ANSWER */
5306 features = 0;
5308 #endif
5309 ast_dsp_set_features(i->dsp, features);
5310 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
5311 if (!ast_strlen_zero(progzone))
5312 ast_dsp_set_call_progress_zone(i->dsp, progzone);
5313 if (i->busydetect && CANBUSYDETECT(i)) {
5314 ast_dsp_set_busy_count(i->dsp, i->busycount);
5315 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
5321 if (state == AST_STATE_RING)
5322 tmp->rings = 1;
5323 tmp->tech_pvt = i;
5324 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
5325 /* Only FXO signalled stuff can be picked up */
5326 tmp->callgroup = i->callgroup;
5327 tmp->pickupgroup = i->pickupgroup;
5329 if (!ast_strlen_zero(i->language))
5330 ast_string_field_set(tmp, language, i->language);
5331 if (!i->owner)
5332 i->owner = tmp;
5333 if (!ast_strlen_zero(i->accountcode))
5334 ast_string_field_set(tmp, accountcode, i->accountcode);
5335 if (i->amaflags)
5336 tmp->amaflags = i->amaflags;
5337 i->subs[index].owner = tmp;
5338 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
5339 ast_string_field_set(tmp, call_forward, i->call_forward);
5340 /* If we've been told "no ADSI" then enforce it */
5341 if (!i->adsi)
5342 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
5343 if (!ast_strlen_zero(i->exten))
5344 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
5345 if (!ast_strlen_zero(i->rdnis))
5346 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
5347 if (!ast_strlen_zero(i->dnid))
5348 tmp->cid.cid_dnid = ast_strdup(i->dnid);
5350 /* Don't use ast_set_callerid() here because it will
5351 * generate a needless NewCallerID event */
5352 #ifdef PRI_ANI
5353 if (!ast_strlen_zero(i->cid_ani))
5354 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
5355 else
5356 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5357 #else
5358 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5359 #endif
5360 tmp->cid.cid_pres = i->callingpres;
5361 tmp->cid.cid_ton = i->cid_ton;
5362 #ifdef HAVE_PRI
5363 tmp->transfercapability = transfercapability;
5364 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
5365 if (transfercapability & PRI_TRANS_CAP_DIGITAL)
5366 i->digital = 1;
5367 /* Assume calls are not idle calls unless we're told differently */
5368 i->isidlecall = 0;
5369 i->alreadyhungup = 0;
5370 #endif
5371 /* clear the fake event in case we posted one before we had ast_channel */
5372 i->fake_event = 0;
5373 /* Assure there is no confmute on this channel */
5374 dahdi_confmute(i, 0);
5375 /* Configure the new channel jb */
5376 ast_jb_configure(tmp, &global_jbconf);
5377 if (startpbx) {
5378 if (ast_pbx_start(tmp)) {
5379 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
5380 ast_hangup(tmp);
5381 i->owner = NULL;
5382 return NULL;
5386 ast_module_ref(ast_module_info->self);
5388 return tmp;
5392 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
5394 char c;
5396 *str = 0; /* start with empty output buffer */
5397 for (;;)
5399 /* Wait for the first digit (up to specified ms). */
5400 c = ast_waitfordigit(chan, ms);
5401 /* if timeout, hangup or error, return as such */
5402 if (c < 1)
5403 return c;
5404 *str++ = c;
5405 *str = 0;
5406 if (strchr(term, c))
5407 return 1;
5411 static int dahdi_wink(struct dahdi_pvt *p, int index)
5413 int j;
5414 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
5415 for (;;)
5417 /* set bits of interest */
5418 j = DAHDI_IOMUX_SIGEVENT;
5419 /* wait for some happening */
5420 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
5421 /* exit loop if we have it */
5422 if (j & DAHDI_IOMUX_SIGEVENT) break;
5424 /* get the event info */
5425 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
5426 return 0;
5429 static void *ss_thread(void *data)
5431 struct ast_channel *chan = data;
5432 struct dahdi_pvt *p = chan->tech_pvt;
5433 char exten[AST_MAX_EXTENSION] = "";
5434 char exten2[AST_MAX_EXTENSION] = "";
5435 unsigned char buf[256];
5436 char dtmfcid[300];
5437 char dtmfbuf[300];
5438 struct callerid_state *cs = NULL;
5439 char *name = NULL, *number = NULL;
5440 int distMatches;
5441 int curRingData[3];
5442 int receivedRingT;
5443 int counter1;
5444 int counter;
5445 int samples = 0;
5446 struct ast_smdi_md_message *smdi_msg = NULL;
5447 int flags;
5448 int i;
5449 int timeout;
5450 int getforward = 0;
5451 char *s1, *s2;
5452 int len = 0;
5453 int res;
5454 int index;
5456 /* in the bizarre case where the channel has become a zombie before we
5457 even get started here, abort safely
5459 if (!p) {
5460 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
5461 ast_hangup(chan);
5462 return NULL;
5465 if (option_verbose > 2)
5466 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
5467 index = dahdi_get_index(chan, p, 1);
5468 if (index < 0) {
5469 ast_log(LOG_WARNING, "Huh?\n");
5470 ast_hangup(chan);
5471 return NULL;
5473 if (p->dsp)
5474 ast_dsp_digitreset(p->dsp);
5475 switch (p->sig) {
5476 #ifdef HAVE_PRI
5477 case SIG_PRI:
5478 /* Now loop looking for an extension */
5479 ast_copy_string(exten, p->exten, sizeof(exten));
5480 len = strlen(exten);
5481 res = 0;
5482 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
5483 if (len && !ast_ignore_pattern(chan->context, exten))
5484 tone_zone_play_tone(p->subs[index].dfd, -1);
5485 else
5486 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5487 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
5488 timeout = matchdigittimeout;
5489 else
5490 timeout = gendigittimeout;
5491 res = ast_waitfordigit(chan, timeout);
5492 if (res < 0) {
5493 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5494 ast_hangup(chan);
5495 return NULL;
5496 } else if (res) {
5497 exten[len++] = res;
5498 exten[len] = '\0';
5499 } else
5500 break;
5502 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
5503 if (ast_strlen_zero(exten)) {
5504 if (option_verbose > 2)
5505 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
5506 exten[0] = 's';
5507 exten[1] = '\0';
5509 tone_zone_play_tone(p->subs[index].dfd, -1);
5510 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
5511 /* Start the real PBX */
5512 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5513 if (p->dsp) ast_dsp_digitreset(p->dsp);
5514 dahdi_enable_ec(p);
5515 ast_setstate(chan, AST_STATE_RING);
5516 res = ast_pbx_run(chan);
5517 if (res) {
5518 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
5520 } else {
5521 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
5522 chan->hangupcause = AST_CAUSE_UNALLOCATED;
5523 ast_hangup(chan);
5524 p->exten[0] = '\0';
5525 /* Since we send release complete here, we won't get one */
5526 p->call = NULL;
5528 return NULL;
5529 break;
5530 #endif
5531 case SIG_FEATD:
5532 case SIG_FEATDMF:
5533 case SIG_FEATDMF_TA:
5534 case SIG_E911:
5535 case SIG_FGC_CAMAMF:
5536 case SIG_FEATB:
5537 case SIG_EMWINK:
5538 case SIG_SF_FEATD:
5539 case SIG_SF_FEATDMF:
5540 case SIG_SF_FEATB:
5541 case SIG_SFWINK:
5542 if (dahdi_wink(p, index))
5543 return NULL;
5544 /* Fall through */
5545 case SIG_EM:
5546 case SIG_EM_E1:
5547 case SIG_SF:
5548 case SIG_FGC_CAMA:
5549 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5550 if (p->dsp)
5551 ast_dsp_digitreset(p->dsp);
5552 /* set digit mode appropriately */
5553 if (p->dsp) {
5554 if (NEED_MFDETECT(p))
5555 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
5556 else
5557 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5559 memset(dtmfbuf, 0, sizeof(dtmfbuf));
5560 /* Wait for the first digit only if immediate=no */
5561 if (!p->immediate)
5562 /* Wait for the first digit (up to 5 seconds). */
5563 res = ast_waitfordigit(chan, 5000);
5564 else
5565 res = 0;
5566 if (res > 0) {
5567 /* save first char */
5568 dtmfbuf[0] = res;
5569 switch (p->sig) {
5570 case SIG_FEATD:
5571 case SIG_SF_FEATD:
5572 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
5573 if (res > 0)
5574 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
5575 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5576 break;
5577 case SIG_FEATDMF_TA:
5578 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5579 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5580 if (dahdi_wink(p, index)) return NULL;
5581 dtmfbuf[0] = 0;
5582 /* Wait for the first digit (up to 5 seconds). */
5583 res = ast_waitfordigit(chan, 5000);
5584 if (res <= 0) break;
5585 dtmfbuf[0] = res;
5586 /* fall through intentionally */
5587 case SIG_FEATDMF:
5588 case SIG_E911:
5589 case SIG_FGC_CAMAMF:
5590 case SIG_SF_FEATDMF:
5591 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5592 /* if international caca, do it again to get real ANO */
5593 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
5595 if (dahdi_wink(p, index)) return NULL;
5596 dtmfbuf[0] = 0;
5597 /* Wait for the first digit (up to 5 seconds). */
5598 res = ast_waitfordigit(chan, 5000);
5599 if (res <= 0) break;
5600 dtmfbuf[0] = res;
5601 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5603 if (res > 0) {
5604 /* if E911, take off hook */
5605 if (p->sig == SIG_E911)
5606 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
5607 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
5609 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5610 break;
5611 case SIG_FEATB:
5612 case SIG_SF_FEATB:
5613 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5614 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5615 break;
5616 case SIG_EMWINK:
5617 /* if we received a '*', we are actually receiving Feature Group D
5618 dial syntax, so use that mode; otherwise, fall through to normal
5619 mode
5621 if (res == '*') {
5622 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
5623 if (res > 0)
5624 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
5625 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5626 break;
5628 default:
5629 /* If we got the first digit, get the rest */
5630 len = 1;
5631 dtmfbuf[len] = '\0';
5632 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
5633 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
5634 timeout = matchdigittimeout;
5635 } else {
5636 timeout = gendigittimeout;
5638 res = ast_waitfordigit(chan, timeout);
5639 if (res < 0) {
5640 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5641 ast_hangup(chan);
5642 return NULL;
5643 } else if (res) {
5644 dtmfbuf[len++] = res;
5645 dtmfbuf[len] = '\0';
5646 } else {
5647 break;
5650 break;
5653 if (res == -1) {
5654 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
5655 ast_hangup(chan);
5656 return NULL;
5657 } else if (res < 0) {
5658 ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
5659 ast_hangup(chan);
5660 return NULL;
5663 if (p->sig == SIG_FGC_CAMA) {
5664 char anibuf[100];
5666 if (ast_safe_sleep(chan,1000) == -1) {
5667 ast_hangup(chan);
5668 return NULL;
5670 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
5671 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
5672 res = my_getsigstr(chan, anibuf, "#", 10000);
5673 if ((res > 0) && (strlen(anibuf) > 2)) {
5674 if (anibuf[strlen(anibuf) - 1] == '#')
5675 anibuf[strlen(anibuf) - 1] = 0;
5676 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
5678 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5681 ast_copy_string(exten, dtmfbuf, sizeof(exten));
5682 if (ast_strlen_zero(exten))
5683 ast_copy_string(exten, "s", sizeof(exten));
5684 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
5685 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
5686 if (exten[0] == '*') {
5687 char *stringp=NULL;
5688 ast_copy_string(exten2, exten, sizeof(exten2));
5689 /* Parse out extension and callerid */
5690 stringp=exten2 +1;
5691 s1 = strsep(&stringp, "*");
5692 s2 = strsep(&stringp, "*");
5693 if (s2) {
5694 if (!ast_strlen_zero(p->cid_num))
5695 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5696 else
5697 ast_set_callerid(chan, s1, NULL, s1);
5698 ast_copy_string(exten, s2, sizeof(exten));
5699 } else
5700 ast_copy_string(exten, s1, sizeof(exten));
5701 } else if (p->sig == SIG_FEATD)
5702 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
5704 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
5705 if (exten[0] == '*') {
5706 char *stringp=NULL;
5707 ast_copy_string(exten2, exten, sizeof(exten2));
5708 /* Parse out extension and callerid */
5709 stringp=exten2 +1;
5710 s1 = strsep(&stringp, "#");
5711 s2 = strsep(&stringp, "#");
5712 if (s2) {
5713 if (!ast_strlen_zero(p->cid_num))
5714 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5715 else
5716 if (*(s1 + 2))
5717 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
5718 ast_copy_string(exten, s2 + 1, sizeof(exten));
5719 } else
5720 ast_copy_string(exten, s1 + 2, sizeof(exten));
5721 } else
5722 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
5724 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
5725 if (exten[0] == '*') {
5726 char *stringp=NULL;
5727 ast_copy_string(exten2, exten, sizeof(exten2));
5728 /* Parse out extension and callerid */
5729 stringp=exten2 +1;
5730 s1 = strsep(&stringp, "#");
5731 s2 = strsep(&stringp, "#");
5732 if (s2 && (*(s2 + 1) == '0')) {
5733 if (*(s2 + 2))
5734 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
5736 if (s1) ast_copy_string(exten, s1, sizeof(exten));
5737 else ast_copy_string(exten, "911", sizeof(exten));
5738 } else
5739 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
5741 if (p->sig == SIG_FEATB) {
5742 if (exten[0] == '*') {
5743 char *stringp=NULL;
5744 ast_copy_string(exten2, exten, sizeof(exten2));
5745 /* Parse out extension and callerid */
5746 stringp=exten2 +1;
5747 s1 = strsep(&stringp, "#");
5748 ast_copy_string(exten, exten2 + 1, sizeof(exten));
5749 } else
5750 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
5752 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
5753 dahdi_wink(p, index);
5754 /* some switches require a minimum guard time between
5755 the last FGD wink and something that answers
5756 immediately. This ensures it */
5757 if (ast_safe_sleep(chan,100)) return NULL;
5759 dahdi_enable_ec(p);
5760 if (NEED_MFDETECT(p)) {
5761 if (p->dsp) {
5762 if (!p->hardwaredtmf)
5763 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5764 else {
5765 ast_dsp_free(p->dsp);
5766 p->dsp = NULL;
5771 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
5772 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5773 if (p->dsp) ast_dsp_digitreset(p->dsp);
5774 res = ast_pbx_run(chan);
5775 if (res) {
5776 ast_log(LOG_WARNING, "PBX exited non-zero\n");
5777 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5779 return NULL;
5780 } else {
5781 if (option_verbose > 2)
5782 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
5783 sleep(2);
5784 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
5785 if (res < 0)
5786 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
5787 else
5788 sleep(1);
5789 res = ast_streamfile(chan, "ss-noservice", chan->language);
5790 if (res >= 0)
5791 ast_waitstream(chan, "");
5792 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5793 ast_hangup(chan);
5794 return NULL;
5796 break;
5797 case SIG_FXOLS:
5798 case SIG_FXOGS:
5799 case SIG_FXOKS:
5800 /* Read the first digit */
5801 timeout = firstdigittimeout;
5802 /* If starting a threeway call, never timeout on the first digit so someone
5803 can use flash-hook as a "hold" feature */
5804 if (p->subs[SUB_THREEWAY].owner)
5805 timeout = 999999;
5806 while (len < AST_MAX_EXTENSION-1) {
5807 /* Read digit unless it's supposed to be immediate, in which case the
5808 only answer is 's' */
5809 if (p->immediate)
5810 res = 's';
5811 else
5812 res = ast_waitfordigit(chan, timeout);
5813 timeout = 0;
5814 if (res < 0) {
5815 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5816 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5817 ast_hangup(chan);
5818 return NULL;
5819 } else if (res) {
5820 exten[len++]=res;
5821 exten[len] = '\0';
5823 if (!ast_ignore_pattern(chan->context, exten))
5824 tone_zone_play_tone(p->subs[index].dfd, -1);
5825 else
5826 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5827 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
5828 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
5829 if (getforward) {
5830 /* Record this as the forwarding extension */
5831 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
5832 if (option_verbose > 2)
5833 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
5834 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5835 if (res)
5836 break;
5837 usleep(500000);
5838 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5839 sleep(1);
5840 memset(exten, 0, sizeof(exten));
5841 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5842 len = 0;
5843 getforward = 0;
5844 } else {
5845 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5846 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5847 if (!ast_strlen_zero(p->cid_num)) {
5848 if (!p->hidecallerid)
5849 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5850 else
5851 ast_set_callerid(chan, NULL, NULL, p->cid_num);
5853 if (!ast_strlen_zero(p->cid_name)) {
5854 if (!p->hidecallerid)
5855 ast_set_callerid(chan, NULL, p->cid_name, NULL);
5857 ast_setstate(chan, AST_STATE_RING);
5858 dahdi_enable_ec(p);
5859 res = ast_pbx_run(chan);
5860 if (res) {
5861 ast_log(LOG_WARNING, "PBX exited non-zero\n");
5862 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5864 return NULL;
5866 } else {
5867 /* It's a match, but they just typed a digit, and there is an ambiguous match,
5868 so just set the timeout to matchdigittimeout and wait some more */
5869 timeout = matchdigittimeout;
5871 } else if (res == 0) {
5872 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
5873 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5874 dahdi_wait_event(p->subs[index].dfd);
5875 ast_hangup(chan);
5876 return NULL;
5877 } else if (p->callwaiting && !strcmp(exten, "*70")) {
5878 if (option_verbose > 2)
5879 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
5880 /* Disable call waiting if enabled */
5881 p->callwaiting = 0;
5882 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5883 if (res) {
5884 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
5885 chan->name, strerror(errno));
5887 len = 0;
5888 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
5889 memset(exten, 0, sizeof(exten));
5890 timeout = firstdigittimeout;
5892 } else if (!strcmp(exten,ast_pickup_ext())) {
5893 /* Scan all channels and see if there are any
5894 * ringing channels that have call groups
5895 * that equal this channels pickup group
5897 if (index == SUB_REAL) {
5898 /* Switch us from Third call to Call Wait */
5899 if (p->subs[SUB_THREEWAY].owner) {
5900 /* If you make a threeway call and the *8# a call, it should actually
5901 look like a callwait */
5902 alloc_sub(p, SUB_CALLWAIT);
5903 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
5904 unalloc_sub(p, SUB_THREEWAY);
5906 dahdi_enable_ec(p);
5907 if (ast_pickup_call(chan)) {
5908 ast_log(LOG_DEBUG, "No call pickup possible...\n");
5909 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5910 dahdi_wait_event(p->subs[index].dfd);
5912 ast_hangup(chan);
5913 return NULL;
5914 } else {
5915 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
5916 ast_hangup(chan);
5917 return NULL;
5920 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
5921 if (option_verbose > 2)
5922 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
5923 /* Disable Caller*ID if enabled */
5924 p->hidecallerid = 1;
5925 if (chan->cid.cid_num)
5926 free(chan->cid.cid_num);
5927 chan->cid.cid_num = NULL;
5928 if (chan->cid.cid_name)
5929 free(chan->cid.cid_name);
5930 chan->cid.cid_name = NULL;
5931 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5932 if (res) {
5933 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
5934 chan->name, strerror(errno));
5936 len = 0;
5937 memset(exten, 0, sizeof(exten));
5938 timeout = firstdigittimeout;
5939 } else if (p->callreturn && !strcmp(exten, "*69")) {
5940 res = 0;
5941 if (!ast_strlen_zero(p->lastcid_num)) {
5942 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
5944 if (!res)
5945 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5946 break;
5947 } else if (!strcmp(exten, "*78")) {
5948 /* Do not disturb */
5949 if (option_verbose > 2)
5950 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
5951 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
5952 "Channel: DAHDI/%d\r\n"
5953 "Status: enabled\r\n", p->channel);
5954 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5955 p->dnd = 1;
5956 getforward = 0;
5957 memset(exten, 0, sizeof(exten));
5958 len = 0;
5959 } else if (!strcmp(exten, "*79")) {
5960 /* Do not disturb */
5961 if (option_verbose > 2)
5962 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
5963 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
5964 "Channel: DAHDI/%d\r\n"
5965 "Status: disabled\r\n", p->channel);
5966 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5967 p->dnd = 0;
5968 getforward = 0;
5969 memset(exten, 0, sizeof(exten));
5970 len = 0;
5971 } else if (p->cancallforward && !strcmp(exten, "*72")) {
5972 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5973 getforward = 1;
5974 memset(exten, 0, sizeof(exten));
5975 len = 0;
5976 } else if (p->cancallforward && !strcmp(exten, "*73")) {
5977 if (option_verbose > 2)
5978 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
5979 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5980 memset(p->call_forward, 0, sizeof(p->call_forward));
5981 getforward = 0;
5982 memset(exten, 0, sizeof(exten));
5983 len = 0;
5984 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
5985 p->subs[SUB_THREEWAY].owner &&
5986 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
5987 /* This is a three way call, the main call being a real channel,
5988 and we're parking the first call. */
5989 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
5990 if (option_verbose > 2)
5991 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
5992 break;
5993 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
5994 if (option_verbose > 2)
5995 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
5996 res = ast_db_put("blacklist", p->lastcid_num, "1");
5997 if (!res) {
5998 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5999 memset(exten, 0, sizeof(exten));
6000 len = 0;
6002 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
6003 if (option_verbose > 2)
6004 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
6005 /* Enable Caller*ID if enabled */
6006 p->hidecallerid = 0;
6007 if (chan->cid.cid_num)
6008 free(chan->cid.cid_num);
6009 chan->cid.cid_num = NULL;
6010 if (chan->cid.cid_name)
6011 free(chan->cid.cid_name);
6012 chan->cid.cid_name = NULL;
6013 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
6014 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6015 if (res) {
6016 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6017 chan->name, strerror(errno));
6019 len = 0;
6020 memset(exten, 0, sizeof(exten));
6021 timeout = firstdigittimeout;
6022 } else if (!strcmp(exten, "*0")) {
6023 struct ast_channel *nbridge =
6024 p->subs[SUB_THREEWAY].owner;
6025 struct dahdi_pvt *pbridge = NULL;
6026 /* set up the private struct of the bridged one, if any */
6027 if (nbridge && ast_bridged_channel(nbridge))
6028 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
6029 if (nbridge && pbridge &&
6030 (nbridge->tech == &dahdi_tech) &&
6031 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
6032 ISTRUNK(pbridge)) {
6033 int func = DAHDI_FLASH;
6034 /* Clear out the dial buffer */
6035 p->dop.dialstr[0] = '\0';
6036 /* flash hookswitch */
6037 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
6038 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
6039 nbridge->name, strerror(errno));
6041 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6042 unalloc_sub(p, SUB_THREEWAY);
6043 p->owner = p->subs[SUB_REAL].owner;
6044 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
6045 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
6046 ast_hangup(chan);
6047 return NULL;
6048 } else {
6049 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6050 dahdi_wait_event(p->subs[index].dfd);
6051 tone_zone_play_tone(p->subs[index].dfd, -1);
6052 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6053 unalloc_sub(p, SUB_THREEWAY);
6054 p->owner = p->subs[SUB_REAL].owner;
6055 ast_hangup(chan);
6056 return NULL;
6058 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
6059 ((exten[0] != '*') || (strlen(exten) > 2))) {
6060 if (option_debug)
6061 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);
6062 break;
6064 if (!timeout)
6065 timeout = gendigittimeout;
6066 if (len && !ast_ignore_pattern(chan->context, exten))
6067 tone_zone_play_tone(p->subs[index].dfd, -1);
6069 break;
6070 case SIG_FXSLS:
6071 case SIG_FXSGS:
6072 case SIG_FXSKS:
6073 #ifdef HAVE_PRI
6074 if (p->pri) {
6075 /* This is a GR-303 trunk actually. Wait for the first ring... */
6076 struct ast_frame *f;
6077 int res;
6078 time_t start;
6080 time(&start);
6081 ast_setstate(chan, AST_STATE_RING);
6082 while (time(NULL) < start + 3) {
6083 res = ast_waitfor(chan, 1000);
6084 if (res) {
6085 f = ast_read(chan);
6086 if (!f) {
6087 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
6088 ast_hangup(chan);
6089 return NULL;
6090 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
6091 res = 1;
6092 } else
6093 res = 0;
6094 ast_frfree(f);
6095 if (res) {
6096 ast_log(LOG_DEBUG, "Got ring!\n");
6097 res = 0;
6098 break;
6103 #endif
6104 /* check for SMDI messages */
6105 if (p->use_smdi && p->smdi_iface) {
6106 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
6108 if (smdi_msg != NULL) {
6109 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
6111 if (smdi_msg->type == 'B')
6112 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
6113 else if (smdi_msg->type == 'N')
6114 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
6116 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
6117 } else {
6118 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
6122 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
6123 number = smdi_msg->calling_st;
6125 /* If we want caller id, we're in a prering state due to a polarity reversal
6126 * and we're set to use a polarity reversal to trigger the start of caller id,
6127 * grab the caller id and wait for ringing to start... */
6128 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
6129 /* If set to use DTMF CID signalling, listen for DTMF */
6130 if (p->cid_signalling == CID_SIG_DTMF) {
6131 int i = 0;
6132 cs = NULL;
6133 ast_log(LOG_DEBUG, "Receiving DTMF cid on "
6134 "channel %s\n", chan->name);
6135 dahdi_setlinear(p->subs[index].dfd, 0);
6136 res = 2000;
6137 for (;;) {
6138 struct ast_frame *f;
6139 res = ast_waitfor(chan, res);
6140 if (res <= 0) {
6141 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
6142 "Exiting simple switch\n");
6143 ast_hangup(chan);
6144 return NULL;
6146 f = ast_read(chan);
6147 if (!f)
6148 break;
6149 if (f->frametype == AST_FRAME_DTMF) {
6150 dtmfbuf[i++] = f->subclass;
6151 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
6152 res = 2000;
6154 ast_frfree(f);
6155 if (chan->_state == AST_STATE_RING ||
6156 chan->_state == AST_STATE_RINGING)
6157 break; /* Got ring */
6159 dtmfbuf[i] = '\0';
6160 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6161 /* Got cid and ring. */
6162 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
6163 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
6164 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
6165 dtmfcid, flags);
6166 /* If first byte is NULL, we have no cid */
6167 if (!ast_strlen_zero(dtmfcid))
6168 number = dtmfcid;
6169 else
6170 number = NULL;
6171 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
6172 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
6173 cs = callerid_new(p->cid_signalling);
6174 if (cs) {
6175 samples = 0;
6176 #if 1
6177 bump_gains(p);
6178 #endif
6179 /* Take out of linear mode for Caller*ID processing */
6180 dahdi_setlinear(p->subs[index].dfd, 0);
6182 /* First we wait and listen for the Caller*ID */
6183 for (;;) {
6184 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6185 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6186 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6187 callerid_free(cs);
6188 ast_hangup(chan);
6189 return NULL;
6191 if (i & DAHDI_IOMUX_SIGEVENT) {
6192 res = dahdi_get_event(p->subs[index].dfd);
6193 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6195 if (p->cid_signalling == CID_SIG_V23_JP) {
6196 #ifdef DAHDI_EVENT_RINGBEGIN
6197 if (res == DAHDI_EVENT_RINGBEGIN) {
6198 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6199 usleep(1);
6201 #endif
6202 } else {
6203 res = 0;
6204 break;
6206 } else if (i & DAHDI_IOMUX_READ) {
6207 res = read(p->subs[index].dfd, buf, sizeof(buf));
6208 if (res < 0) {
6209 if (errno != ELAST) {
6210 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6211 callerid_free(cs);
6212 ast_hangup(chan);
6213 return NULL;
6215 break;
6217 samples += res;
6219 if (p->cid_signalling == CID_SIG_V23_JP) {
6220 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
6221 } else {
6222 res = callerid_feed(cs, buf, res, AST_LAW(p));
6225 if (res < 0) {
6226 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
6227 break;
6228 } else if (res)
6229 break;
6230 else if (samples > (8000 * 10))
6231 break;
6234 if (res == 1) {
6235 callerid_get(cs, &name, &number, &flags);
6236 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
6239 if (p->cid_signalling == CID_SIG_V23_JP) {
6240 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6241 usleep(1);
6242 res = 4000;
6243 } else {
6245 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
6246 res = 2000;
6249 for (;;) {
6250 struct ast_frame *f;
6251 res = ast_waitfor(chan, res);
6252 if (res <= 0) {
6253 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
6254 "Exiting simple switch\n");
6255 ast_hangup(chan);
6256 return NULL;
6258 if (!(f = ast_read(chan))) {
6259 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
6260 ast_hangup(chan);
6261 return NULL;
6263 ast_frfree(f);
6264 if (chan->_state == AST_STATE_RING ||
6265 chan->_state == AST_STATE_RINGING)
6266 break; /* Got ring */
6269 /* We must have a ring by now, so, if configured, lets try to listen for
6270 * distinctive ringing */
6271 if (p->usedistinctiveringdetection == 1) {
6272 len = 0;
6273 distMatches = 0;
6274 /* Clear the current ring data array so we dont have old data in it. */
6275 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
6276 curRingData[receivedRingT] = 0;
6277 receivedRingT = 0;
6278 counter = 0;
6279 counter1 = 0;
6280 /* Check to see if context is what it should be, if not set to be. */
6281 if (strcmp(p->context,p->defcontext) != 0) {
6282 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
6283 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
6286 for (;;) {
6287 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6288 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6289 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6290 callerid_free(cs);
6291 ast_hangup(chan);
6292 return NULL;
6294 if (i & DAHDI_IOMUX_SIGEVENT) {
6295 res = dahdi_get_event(p->subs[index].dfd);
6296 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6297 res = 0;
6298 /* Let us detect distinctive ring */
6300 curRingData[receivedRingT] = p->ringt;
6302 if (p->ringt < p->ringt_base/2)
6303 break;
6304 /* Increment the ringT counter so we can match it against
6305 values in chan_dahdi.conf for distinctive ring */
6306 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6307 break;
6308 } else if (i & DAHDI_IOMUX_READ) {
6309 res = read(p->subs[index].dfd, buf, sizeof(buf));
6310 if (res < 0) {
6311 if (errno != ELAST) {
6312 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6313 callerid_free(cs);
6314 ast_hangup(chan);
6315 return NULL;
6317 break;
6319 if (p->ringt)
6320 p->ringt--;
6321 if (p->ringt == 1) {
6322 res = -1;
6323 break;
6327 if (option_verbose > 2)
6328 /* this only shows up if you have n of the dring patterns filled in */
6329 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
6331 for (counter = 0; counter < 3; counter++) {
6332 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6333 channel */
6334 distMatches = 0;
6335 for (counter1 = 0; counter1 < 3; counter1++) {
6336 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
6337 (p->drings.ringnum[counter].ring[counter1]-10)) {
6338 distMatches++;
6341 if (distMatches == 3) {
6342 /* The ring matches, set the context to whatever is for distinctive ring.. */
6343 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
6344 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
6345 if (option_verbose > 2)
6346 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
6347 break;
6351 /* Restore linear mode (if appropriate) for Caller*ID processing */
6352 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6353 #if 1
6354 restore_gains(p);
6355 #endif
6356 } else
6357 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
6358 } else {
6359 ast_log(LOG_WARNING, "Channel %s in prering "
6360 "state, but I have nothing to do. "
6361 "Terminating simple switch, should be "
6362 "restarted by the actual ring.\n",
6363 chan->name);
6364 ast_hangup(chan);
6365 return NULL;
6367 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
6368 /* FSK Bell202 callerID */
6369 cs = callerid_new(p->cid_signalling);
6370 if (cs) {
6371 #if 1
6372 bump_gains(p);
6373 #endif
6374 samples = 0;
6375 len = 0;
6376 distMatches = 0;
6377 /* Clear the current ring data array so we dont have old data in it. */
6378 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
6379 curRingData[receivedRingT] = 0;
6380 receivedRingT = 0;
6381 counter = 0;
6382 counter1 = 0;
6383 /* Check to see if context is what it should be, if not set to be. */
6384 if (strcmp(p->context,p->defcontext) != 0) {
6385 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
6386 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
6389 /* Take out of linear mode for Caller*ID processing */
6390 dahdi_setlinear(p->subs[index].dfd, 0);
6391 for (;;) {
6392 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6393 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6394 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6395 callerid_free(cs);
6396 ast_hangup(chan);
6397 return NULL;
6399 if (i & DAHDI_IOMUX_SIGEVENT) {
6400 res = dahdi_get_event(p->subs[index].dfd);
6401 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6402 /* If we get a PR event, they hung up while processing calerid */
6403 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
6404 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
6405 p->polarity = POLARITY_IDLE;
6406 callerid_free(cs);
6407 ast_hangup(chan);
6408 return NULL;
6410 res = 0;
6411 /* Let us detect callerid when the telco uses distinctive ring */
6413 curRingData[receivedRingT] = p->ringt;
6415 if (p->ringt < p->ringt_base/2)
6416 break;
6417 /* Increment the ringT counter so we can match it against
6418 values in chan_dahdi.conf for distinctive ring */
6419 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6420 break;
6421 } else if (i & DAHDI_IOMUX_READ) {
6422 res = read(p->subs[index].dfd, buf, sizeof(buf));
6423 if (res < 0) {
6424 if (errno != ELAST) {
6425 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6426 callerid_free(cs);
6427 ast_hangup(chan);
6428 return NULL;
6430 break;
6432 if (p->ringt)
6433 p->ringt--;
6434 if (p->ringt == 1) {
6435 res = -1;
6436 break;
6438 samples += res;
6439 res = callerid_feed(cs, buf, res, AST_LAW(p));
6440 if (res < 0) {
6441 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
6442 break;
6443 } else if (res)
6444 break;
6445 else if (samples > (8000 * 10))
6446 break;
6449 if (res == 1) {
6450 callerid_get(cs, &name, &number, &flags);
6451 if (option_debug)
6452 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
6454 if (distinctiveringaftercid == 1) {
6455 /* Clear the current ring data array so we dont have old data in it. */
6456 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
6457 curRingData[receivedRingT] = 0;
6459 receivedRingT = 0;
6460 if (option_verbose > 2)
6461 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
6462 for (;;) {
6463 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6464 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6465 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6466 callerid_free(cs);
6467 ast_hangup(chan);
6468 return NULL;
6470 if (i & DAHDI_IOMUX_SIGEVENT) {
6471 res = dahdi_get_event(p->subs[index].dfd);
6472 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6473 res = 0;
6474 /* Let us detect callerid when the telco uses distinctive ring */
6476 curRingData[receivedRingT] = p->ringt;
6478 if (p->ringt < p->ringt_base/2)
6479 break;
6480 /* Increment the ringT counter so we can match it against
6481 values in chan_dahdi.conf for distinctive ring */
6482 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6483 break;
6484 } else if (i & DAHDI_IOMUX_READ) {
6485 res = read(p->subs[index].dfd, buf, sizeof(buf));
6486 if (res < 0) {
6487 if (errno != ELAST) {
6488 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6489 callerid_free(cs);
6490 ast_hangup(chan);
6491 return NULL;
6493 break;
6495 if (p->ringt)
6496 p->ringt--;
6497 if (p->ringt == 1) {
6498 res = -1;
6499 break;
6504 if (p->usedistinctiveringdetection == 1) {
6505 if (option_verbose > 2)
6506 /* this only shows up if you have n of the dring patterns filled in */
6507 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
6509 for (counter = 0; counter < 3; counter++) {
6510 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6511 channel */
6512 if (option_verbose > 2)
6513 /* this only shows up if you have n of the dring patterns filled in */
6514 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
6515 p->drings.ringnum[counter].ring[0],
6516 p->drings.ringnum[counter].ring[1],
6517 p->drings.ringnum[counter].ring[2]);
6518 distMatches = 0;
6519 for (counter1 = 0; counter1 < 3; counter1++) {
6520 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
6521 (p->drings.ringnum[counter].ring[counter1]-10)) {
6522 distMatches++;
6525 if (distMatches == 3) {
6526 /* The ring matches, set the context to whatever is for distinctive ring.. */
6527 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
6528 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
6529 if (option_verbose > 2)
6530 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
6531 break;
6535 /* Restore linear mode (if appropriate) for Caller*ID processing */
6536 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6537 #if 1
6538 restore_gains(p);
6539 #endif
6540 if (res < 0) {
6541 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
6543 } else
6544 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
6546 else
6547 cs = NULL;
6549 if (number)
6550 ast_shrink_phone_number(number);
6551 ast_set_callerid(chan, number, name, number);
6553 if (smdi_msg)
6554 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
6556 if (cs)
6557 callerid_free(cs);
6559 ast_setstate(chan, AST_STATE_RING);
6560 chan->rings = 1;
6561 p->ringt = p->ringt_base;
6562 res = ast_pbx_run(chan);
6563 if (res) {
6564 ast_hangup(chan);
6565 ast_log(LOG_WARNING, "PBX exited non-zero\n");
6567 return NULL;
6568 default:
6569 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
6570 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6571 if (res < 0)
6572 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
6574 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6575 if (res < 0)
6576 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
6577 ast_hangup(chan);
6578 return NULL;
6581 /* destroy a DAHDI channel, identified by its number */
6582 static int dahdi_destroy_channel_bynum(int channel)
6584 struct dahdi_pvt *tmp = NULL;
6585 struct dahdi_pvt *prev = NULL;
6587 tmp = iflist;
6588 while (tmp) {
6589 if (tmp->channel == channel) {
6590 destroy_channel(prev, tmp, 1);
6591 return RESULT_SUCCESS;
6593 prev = tmp;
6594 tmp = tmp->next;
6596 return RESULT_FAILURE;
6599 static int handle_init_event(struct dahdi_pvt *i, int event)
6601 int res;
6602 pthread_t threadid;
6603 pthread_attr_t attr;
6604 struct ast_channel *chan;
6605 pthread_attr_init(&attr);
6606 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
6607 /* Handle an event on a given channel for the monitor thread. */
6608 switch (event) {
6609 case DAHDI_EVENT_NONE:
6610 case DAHDI_EVENT_BITSCHANGED:
6611 break;
6612 case DAHDI_EVENT_WINKFLASH:
6613 case DAHDI_EVENT_RINGOFFHOOK:
6614 if (i->inalarm) break;
6615 if (i->radio) break;
6616 /* Got a ring/answer. What kind of channel are we? */
6617 switch (i->sig) {
6618 case SIG_FXOLS:
6619 case SIG_FXOGS:
6620 case SIG_FXOKS:
6621 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6622 if (res && (errno == EBUSY))
6623 break;
6624 if (i->cidspill) {
6625 /* Cancel VMWI spill */
6626 free(i->cidspill);
6627 i->cidspill = NULL;
6629 if (i->immediate) {
6630 dahdi_enable_ec(i);
6631 /* The channel is immediately up. Start right away */
6632 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
6633 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
6634 if (!chan) {
6635 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
6636 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6637 if (res < 0)
6638 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6640 } else {
6641 /* Check for callerid, digits, etc */
6642 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
6643 if (chan) {
6644 if (has_voicemail(i))
6645 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
6646 else
6647 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
6648 if (res < 0)
6649 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
6650 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6651 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6652 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6653 if (res < 0)
6654 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6655 ast_hangup(chan);
6657 } else
6658 ast_log(LOG_WARNING, "Unable to create channel\n");
6660 break;
6661 case SIG_FXSLS:
6662 case SIG_FXSGS:
6663 case SIG_FXSKS:
6664 i->ringt = i->ringt_base;
6665 /* Fall through */
6666 case SIG_EMWINK:
6667 case SIG_FEATD:
6668 case SIG_FEATDMF:
6669 case SIG_FEATDMF_TA:
6670 case SIG_E911:
6671 case SIG_FGC_CAMA:
6672 case SIG_FGC_CAMAMF:
6673 case SIG_FEATB:
6674 case SIG_EM:
6675 case SIG_EM_E1:
6676 case SIG_SFWINK:
6677 case SIG_SF_FEATD:
6678 case SIG_SF_FEATDMF:
6679 case SIG_SF_FEATB:
6680 case SIG_SF:
6681 /* Check for callerid, digits, etc */
6682 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
6683 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6684 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6685 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6686 if (res < 0)
6687 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6688 ast_hangup(chan);
6689 } else if (!chan) {
6690 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
6692 break;
6693 default:
6694 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
6695 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6696 if (res < 0)
6697 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6698 return -1;
6700 break;
6701 case DAHDI_EVENT_NOALARM:
6702 i->inalarm = 0;
6703 if (!i->unknown_alarm) {
6704 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
6705 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
6706 "Channel: %d\r\n", i->channel);
6707 } else {
6708 i->unknown_alarm = 0;
6710 break;
6711 case DAHDI_EVENT_ALARM:
6712 i->inalarm = 1;
6713 res = get_alarms(i);
6714 do {
6715 const char *alarm_str = alarm2str(res);
6717 /* hack alert! DAHDI 1.4 now exposes FXO battery as an alarm, but asterisk 1.4
6718 * doesn't know what to do with it. Don't confuse users with log messages. */
6719 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
6720 i->unknown_alarm = 1;
6721 break;
6722 } else {
6723 i->unknown_alarm = 0;
6726 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm_str);
6727 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
6728 "Alarm: %s\r\n"
6729 "Channel: %d\r\n",
6730 alarm_str, i->channel);
6731 } while (0);
6732 /* fall thru intentionally */
6733 case DAHDI_EVENT_ONHOOK:
6734 if (i->radio)
6735 break;
6736 /* Back on hook. Hang up. */
6737 switch (i->sig) {
6738 case SIG_FXOLS:
6739 case SIG_FXOGS:
6740 case SIG_FEATD:
6741 case SIG_FEATDMF:
6742 case SIG_FEATDMF_TA:
6743 case SIG_E911:
6744 case SIG_FGC_CAMA:
6745 case SIG_FGC_CAMAMF:
6746 case SIG_FEATB:
6747 case SIG_EM:
6748 case SIG_EM_E1:
6749 case SIG_EMWINK:
6750 case SIG_SF_FEATD:
6751 case SIG_SF_FEATDMF:
6752 case SIG_SF_FEATB:
6753 case SIG_SF:
6754 case SIG_SFWINK:
6755 case SIG_FXSLS:
6756 case SIG_FXSGS:
6757 case SIG_FXSKS:
6758 case SIG_GR303FXSKS:
6759 dahdi_disable_ec(i);
6760 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6761 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6762 break;
6763 case SIG_GR303FXOKS:
6764 case SIG_FXOKS:
6765 dahdi_disable_ec(i);
6766 /* Diddle the battery for the zhone */
6767 #ifdef ZHONE_HACK
6768 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6769 usleep(1);
6770 #endif
6771 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6772 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6773 break;
6774 case SIG_PRI:
6775 dahdi_disable_ec(i);
6776 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6777 break;
6778 default:
6779 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
6780 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6781 return -1;
6783 break;
6784 case DAHDI_EVENT_POLARITY:
6785 switch (i->sig) {
6786 case SIG_FXSLS:
6787 case SIG_FXSKS:
6788 case SIG_FXSGS:
6789 /* We have already got a PR before the channel was
6790 created, but it wasn't handled. We need polarity
6791 to be REV for remote hangup detection to work.
6792 At least in Spain */
6793 if (i->hanguponpolarityswitch)
6794 i->polarity = POLARITY_REV;
6796 if (i->cid_start == CID_START_POLARITY) {
6797 i->polarity = POLARITY_REV;
6798 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
6799 "CID detection on channel %d\n",
6800 i->channel);
6801 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
6802 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6803 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6806 break;
6807 default:
6808 ast_log(LOG_WARNING, "handle_init_event detected "
6809 "polarity reversal on non-FXO (SIG_FXS) "
6810 "interface %d\n", i->channel);
6812 break;
6813 case DAHDI_EVENT_REMOVED: /* destroy channel */
6814 ast_log(LOG_NOTICE,
6815 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
6816 i->channel);
6817 dahdi_destroy_channel_bynum(i->channel);
6818 break;
6820 pthread_attr_destroy(&attr);
6821 return 0;
6824 static void *do_monitor(void *data)
6826 int count, res, res2, spoint, pollres=0;
6827 struct dahdi_pvt *i;
6828 struct dahdi_pvt *last = NULL;
6829 time_t thispass = 0, lastpass = 0;
6830 int found;
6831 char buf[1024];
6832 struct pollfd *pfds=NULL;
6833 int lastalloc = -1;
6834 /* This thread monitors all the frame relay interfaces which are not yet in use
6835 (and thus do not have a separate thread) indefinitely */
6836 /* From here on out, we die whenever asked */
6837 #if 0
6838 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
6839 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
6840 return NULL;
6842 ast_log(LOG_DEBUG, "Monitor starting...\n");
6843 #endif
6844 for (;;) {
6845 /* Lock the interface list */
6846 ast_mutex_lock(&iflock);
6847 if (!pfds || (lastalloc != ifcount)) {
6848 if (pfds) {
6849 free(pfds);
6850 pfds = NULL;
6852 if (ifcount) {
6853 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
6854 ast_mutex_unlock(&iflock);
6855 return NULL;
6858 lastalloc = ifcount;
6860 /* Build the stuff we're going to poll on, that is the socket of every
6861 dahdi_pvt that does not have an associated owner channel */
6862 count = 0;
6863 i = iflist;
6864 while (i) {
6865 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
6866 if (!i->owner && !i->subs[SUB_REAL].owner) {
6867 /* This needs to be watched, as it lacks an owner */
6868 pfds[count].fd = i->subs[SUB_REAL].dfd;
6869 pfds[count].events = POLLPRI;
6870 pfds[count].revents = 0;
6871 /* Message waiting or r2 channels also get watched for reading */
6872 if (i->cidspill)
6873 pfds[count].events |= POLLIN;
6874 count++;
6877 i = i->next;
6879 /* Okay, now that we know what to do, release the interface lock */
6880 ast_mutex_unlock(&iflock);
6882 pthread_testcancel();
6883 /* Wait at least a second for something to happen */
6884 res = poll(pfds, count, 1000);
6885 pthread_testcancel();
6886 /* Okay, poll has finished. Let's see what happened. */
6887 if (res < 0) {
6888 if ((errno != EAGAIN) && (errno != EINTR))
6889 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
6890 continue;
6892 /* Alright, lock the interface list again, and let's look and see what has
6893 happened */
6894 ast_mutex_lock(&iflock);
6895 found = 0;
6896 spoint = 0;
6897 lastpass = thispass;
6898 thispass = time(NULL);
6899 i = iflist;
6900 while (i) {
6901 if (thispass != lastpass) {
6902 if (!found && ((i == last) || ((i == iflist) && !last))) {
6903 last = i;
6904 if (last) {
6905 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
6906 (last->sig & __DAHDI_SIG_FXO)) {
6907 res = ast_app_has_voicemail(last->mailbox, NULL);
6908 if (last->msgstate != res) {
6909 int x;
6910 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
6911 x = DAHDI_FLUSH_BOTH;
6912 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
6913 if (res2)
6914 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
6915 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
6916 /* Turn on on hook transfer for 4 seconds */
6917 x = 4000;
6918 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
6919 last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
6920 last->cidpos = 0;
6921 last->msgstate = res;
6922 last->onhooktime = thispass;
6924 found ++;
6927 last = last->next;
6931 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
6932 if (i->radio && !i->owner)
6934 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
6935 if (res)
6937 if (option_debug)
6938 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
6939 /* Don't hold iflock while handling init events */
6940 ast_mutex_unlock(&iflock);
6941 handle_init_event(i, res);
6942 ast_mutex_lock(&iflock);
6944 i = i->next;
6945 continue;
6947 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
6948 if (pollres & POLLIN) {
6949 if (i->owner || i->subs[SUB_REAL].owner) {
6950 #ifdef HAVE_PRI
6951 if (!i->pri)
6952 #endif
6953 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
6954 i = i->next;
6955 continue;
6957 if (!i->cidspill) {
6958 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
6959 i = i->next;
6960 continue;
6962 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
6963 if (res > 0) {
6964 /* We read some number of bytes. Write an equal amount of data */
6965 if (res > i->cidlen - i->cidpos)
6966 res = i->cidlen - i->cidpos;
6967 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
6968 if (res2 > 0) {
6969 i->cidpos += res2;
6970 if (i->cidpos >= i->cidlen) {
6971 free(i->cidspill);
6972 i->cidspill = 0;
6973 i->cidpos = 0;
6974 i->cidlen = 0;
6976 } else {
6977 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
6978 i->msgstate = -1;
6980 } else {
6981 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
6984 if (pollres & POLLPRI) {
6985 if (i->owner || i->subs[SUB_REAL].owner) {
6986 #ifdef HAVE_PRI
6987 if (!i->pri)
6988 #endif
6989 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
6990 i = i->next;
6991 continue;
6993 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
6994 if (option_debug)
6995 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
6996 /* Don't hold iflock while handling init events */
6997 ast_mutex_unlock(&iflock);
6998 handle_init_event(i, res);
6999 ast_mutex_lock(&iflock);
7002 i=i->next;
7004 ast_mutex_unlock(&iflock);
7006 /* Never reached */
7007 return NULL;
7011 static int restart_monitor(void)
7013 pthread_attr_t attr;
7014 pthread_attr_init(&attr);
7015 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
7016 /* If we're supposed to be stopped -- stay stopped */
7017 if (monitor_thread == AST_PTHREADT_STOP)
7018 return 0;
7019 ast_mutex_lock(&monlock);
7020 if (monitor_thread == pthread_self()) {
7021 ast_mutex_unlock(&monlock);
7022 ast_log(LOG_WARNING, "Cannot kill myself\n");
7023 return -1;
7025 if (monitor_thread != AST_PTHREADT_NULL) {
7026 /* Wake up the thread */
7027 pthread_kill(monitor_thread, SIGURG);
7028 } else {
7029 /* Start a new monitor */
7030 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
7031 ast_mutex_unlock(&monlock);
7032 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
7033 pthread_attr_destroy(&attr);
7034 return -1;
7037 ast_mutex_unlock(&monlock);
7038 pthread_attr_destroy(&attr);
7039 return 0;
7042 #ifdef HAVE_PRI
7043 static int pri_resolve_span(int *span, int channel, int offset, DAHDI_SPANINFO *si)
7045 int x;
7046 int trunkgroup;
7047 /* Get appropriate trunk group if there is one */
7048 trunkgroup = pris[*span].mastertrunkgroup;
7049 if (trunkgroup) {
7050 /* Select a specific trunk group */
7051 for (x = 0; x < NUM_SPANS; x++) {
7052 if (pris[x].trunkgroup == trunkgroup) {
7053 *span = x;
7054 return 0;
7057 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
7058 *span = -1;
7059 } else {
7060 if (pris[*span].trunkgroup) {
7061 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
7062 *span = -1;
7063 } else if (pris[*span].mastertrunkgroup) {
7064 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
7065 *span = -1;
7066 } else {
7067 if (si->totalchans == 31) { /* if it's an E1 */
7068 pris[*span].dchannels[0] = 16 + offset;
7069 } else {
7070 pris[*span].dchannels[0] = 24 + offset;
7072 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
7073 pris[*span].offset = offset;
7074 pris[*span].span = *span + 1;
7077 return 0;
7080 static int pri_create_trunkgroup(int trunkgroup, int *channels)
7082 DAHDI_SPANINFO si;
7083 DAHDI_PARAMS p;
7084 int fd;
7085 int span;
7086 int ospan=0;
7087 int x,y;
7088 for (x = 0; x < NUM_SPANS; x++) {
7089 if (pris[x].trunkgroup == trunkgroup) {
7090 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
7091 return -1;
7094 for (y = 0; y < NUM_DCHANS; y++) {
7095 if (!channels[y])
7096 break;
7097 memset(&si, 0, sizeof(si));
7098 memset(&p, 0, sizeof(p));
7099 #ifdef HAVE_ZAPTEL
7100 fd = open("/dev/zap/channel", O_RDWR);
7101 #else
7102 fd = open("/dev/dahdi/channel", O_RDWR);
7103 #endif
7104 if (fd < 0) {
7105 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
7106 return -1;
7108 x = channels[y];
7109 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
7110 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
7111 dahdi_close(fd);
7112 return -1;
7114 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
7115 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
7116 return -1;
7118 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
7119 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
7120 dahdi_close(fd);
7121 return -1;
7123 span = p.spanno - 1;
7124 if (pris[span].trunkgroup) {
7125 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
7126 dahdi_close(fd);
7127 return -1;
7129 if (pris[span].pvts[0]) {
7130 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
7131 dahdi_close(fd);
7132 return -1;
7134 if (!y) {
7135 pris[span].trunkgroup = trunkgroup;
7136 pris[span].offset = channels[y] - p.chanpos;
7137 ospan = span;
7139 pris[ospan].dchannels[y] = channels[y];
7140 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
7141 pris[span].span = span + 1;
7142 dahdi_close(fd);
7144 return 0;
7147 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
7149 if (pris[span].mastertrunkgroup) {
7150 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);
7151 return -1;
7153 pris[span].mastertrunkgroup = trunkgroup;
7154 pris[span].prilogicalspan = logicalspan;
7155 return 0;
7158 #endif
7160 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
7162 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
7163 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
7164 char fn[80];
7165 #if 1
7166 DAHDI_BUFFERINFO bi;
7167 #endif
7168 DAHDI_SPANINFO si;
7169 int res;
7170 int span=0;
7171 int here = 0;
7172 int x;
7173 struct dahdi_pvt **wlist;
7174 struct dahdi_pvt **wend;
7175 DAHDI_PARAMS p;
7177 wlist = &iflist;
7178 wend = &ifend;
7180 #ifdef HAVE_PRI
7181 if (pri) {
7182 wlist = &pri->crvs;
7183 wend = &pri->crvend;
7185 #endif
7187 tmp2 = *wlist;
7188 prev = NULL;
7190 while (tmp2) {
7191 if (!tmp2->destroy) {
7192 if (tmp2->channel == channel) {
7193 tmp = tmp2;
7194 here = 1;
7195 break;
7197 if (tmp2->channel > channel) {
7198 break;
7201 prev = tmp2;
7202 tmp2 = tmp2->next;
7205 if (!here && !reloading) {
7206 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
7207 destroy_dahdi_pvt(&tmp);
7208 return NULL;
7210 ast_mutex_init(&tmp->lock);
7211 ifcount++;
7212 for (x = 0; x < 3; x++)
7213 tmp->subs[x].dfd = -1;
7214 tmp->channel = channel;
7217 if (tmp) {
7218 int chan_sig = conf->chan.sig;
7219 if (!here) {
7220 if ((channel != CHAN_PSEUDO) && !pri) {
7221 snprintf(fn, sizeof(fn), "%d", channel);
7222 /* Open non-blocking */
7223 if (!here)
7224 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
7225 /* Allocate a DAHDI structure */
7226 if (tmp->subs[SUB_REAL].dfd < 0) {
7227 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);
7228 destroy_dahdi_pvt(&tmp);
7229 return NULL;
7231 memset(&p, 0, sizeof(p));
7232 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
7233 if (res < 0) {
7234 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
7235 destroy_dahdi_pvt(&tmp);
7236 return NULL;
7238 if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
7239 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));
7240 destroy_dahdi_pvt(&tmp);
7241 return NULL;
7243 tmp->law = p.curlaw;
7244 tmp->span = p.spanno;
7245 span = p.spanno - 1;
7246 } else {
7247 if (channel == CHAN_PSEUDO)
7248 chan_sig = 0;
7249 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
7250 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
7251 return NULL;
7254 #ifdef HAVE_PRI
7255 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
7256 int offset;
7257 int myswitchtype;
7258 int matchesdchan;
7259 int x,y;
7260 offset = 0;
7261 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
7262 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
7263 destroy_dahdi_pvt(&tmp);
7264 return NULL;
7266 if (span >= NUM_SPANS) {
7267 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
7268 destroy_dahdi_pvt(&tmp);
7269 return NULL;
7270 } else {
7271 si.spanno = 0;
7272 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
7273 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
7274 destroy_dahdi_pvt(&tmp);
7275 return NULL;
7277 /* Store the logical span first based upon the real span */
7278 tmp->logicalspan = pris[span].prilogicalspan;
7279 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
7280 if (span < 0) {
7281 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
7282 destroy_dahdi_pvt(&tmp);
7283 return NULL;
7285 if (chan_sig == SIG_PRI)
7286 myswitchtype = conf->pri.switchtype;
7287 else
7288 myswitchtype = PRI_SWITCH_GR303_TMC;
7289 /* Make sure this isn't a d-channel */
7290 matchesdchan=0;
7291 for (x = 0; x < NUM_SPANS; x++) {
7292 for (y = 0; y < NUM_DCHANS; y++) {
7293 if (pris[x].dchannels[y] == tmp->channel) {
7294 matchesdchan = 1;
7295 break;
7299 offset = p.chanpos;
7300 if (!matchesdchan) {
7301 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
7302 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
7303 destroy_dahdi_pvt(&tmp);
7304 return NULL;
7306 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
7307 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
7308 destroy_dahdi_pvt(&tmp);
7309 return NULL;
7311 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
7312 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
7313 destroy_dahdi_pvt(&tmp);
7314 return NULL;
7316 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
7317 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
7318 destroy_dahdi_pvt(&tmp);
7319 return NULL;
7321 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
7322 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
7323 destroy_dahdi_pvt(&tmp);
7324 return NULL;
7326 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
7327 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
7328 destroy_dahdi_pvt(&tmp);
7329 return NULL;
7331 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
7332 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
7333 destroy_dahdi_pvt(&tmp);
7334 return NULL;
7336 if (pris[span].numchans >= MAX_CHANNELS) {
7337 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
7338 pris[span].trunkgroup);
7339 destroy_dahdi_pvt(&tmp);
7340 return NULL;
7342 pris[span].nodetype = conf->pri.nodetype;
7343 pris[span].switchtype = myswitchtype;
7344 pris[span].nsf = conf->pri.nsf;
7345 pris[span].dialplan = conf->pri.dialplan;
7346 pris[span].localdialplan = conf->pri.localdialplan;
7347 pris[span].pvts[pris[span].numchans++] = tmp;
7348 pris[span].minunused = conf->pri.minunused;
7349 pris[span].minidle = conf->pri.minidle;
7350 pris[span].overlapdial = conf->pri.overlapdial;
7351 pris[span].facilityenable = conf->pri.facilityenable;
7352 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
7353 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
7354 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
7355 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
7356 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
7357 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
7358 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
7359 pris[span].resetinterval = conf->pri.resetinterval;
7361 tmp->pri = &pris[span];
7362 tmp->prioffset = offset;
7363 tmp->call = NULL;
7364 } else {
7365 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
7366 destroy_dahdi_pvt(&tmp);
7367 return NULL;
7370 } else {
7371 tmp->prioffset = 0;
7373 #endif
7374 } else {
7375 chan_sig = tmp->sig;
7376 memset(&p, 0, sizeof(p));
7377 if (tmp->subs[SUB_REAL].dfd > -1)
7378 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
7380 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
7381 switch (chan_sig) {
7382 case SIG_FXSKS:
7383 case SIG_FXSLS:
7384 case SIG_EM:
7385 case SIG_EM_E1:
7386 case SIG_EMWINK:
7387 case SIG_FEATD:
7388 case SIG_FEATDMF:
7389 case SIG_FEATDMF_TA:
7390 case SIG_FEATB:
7391 case SIG_E911:
7392 case SIG_SF:
7393 case SIG_SFWINK:
7394 case SIG_FGC_CAMA:
7395 case SIG_FGC_CAMAMF:
7396 case SIG_SF_FEATD:
7397 case SIG_SF_FEATDMF:
7398 case SIG_SF_FEATB:
7399 p.starttime = 250;
7400 break;
7403 if (tmp->radio) {
7404 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
7405 p.channo = channel;
7406 p.rxwinktime = 1;
7407 p.rxflashtime = 1;
7408 p.starttime = 1;
7409 p.debouncetime = 5;
7411 if (!tmp->radio) {
7412 p.channo = channel;
7413 /* Override timing settings based on config file */
7414 if (conf->timing.prewinktime >= 0)
7415 p.prewinktime = conf->timing.prewinktime;
7416 if (conf->timing.preflashtime >= 0)
7417 p.preflashtime = conf->timing.preflashtime;
7418 if (conf->timing.winktime >= 0)
7419 p.winktime = conf->timing.winktime;
7420 if (conf->timing.flashtime >= 0)
7421 p.flashtime = conf->timing.flashtime;
7422 if (conf->timing.starttime >= 0)
7423 p.starttime = conf->timing.starttime;
7424 if (conf->timing.rxwinktime >= 0)
7425 p.rxwinktime = conf->timing.rxwinktime;
7426 if (conf->timing.rxflashtime >= 0)
7427 p.rxflashtime = conf->timing.rxflashtime;
7428 if (conf->timing.debouncetime >= 0)
7429 p.debouncetime = conf->timing.debouncetime;
7432 /* dont set parms on a pseudo-channel (or CRV) */
7433 if (tmp->subs[SUB_REAL].dfd >= 0)
7435 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
7436 if (res < 0) {
7437 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
7438 destroy_dahdi_pvt(&tmp);
7439 return NULL;
7442 #if 1
7443 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
7444 memset(&bi, 0, sizeof(bi));
7445 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
7446 if (!res) {
7447 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
7448 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
7449 bi.numbufs = numbufs;
7450 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
7451 if (res < 0) {
7452 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
7454 } else
7455 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
7457 #endif
7458 tmp->immediate = conf->chan.immediate;
7459 tmp->transfertobusy = conf->chan.transfertobusy;
7460 tmp->sig = chan_sig;
7461 tmp->outsigmod = conf->chan.outsigmod;
7462 tmp->ringt_base = ringt_base;
7463 tmp->firstradio = 0;
7464 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
7465 tmp->permcallwaiting = conf->chan.callwaiting;
7466 else
7467 tmp->permcallwaiting = 0;
7468 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
7469 tmp->destroy = 0;
7470 tmp->drings = drings;
7471 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
7472 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
7473 tmp->threewaycalling = conf->chan.threewaycalling;
7474 tmp->adsi = conf->chan.adsi;
7475 tmp->use_smdi = conf->chan.use_smdi;
7476 tmp->permhidecallerid = conf->chan.hidecallerid;
7477 tmp->callreturn = conf->chan.callreturn;
7478 tmp->echocancel = conf->chan.echocancel;
7479 tmp->echotraining = conf->chan.echotraining;
7480 tmp->pulse = conf->chan.pulse;
7481 if (tmp->echocancel)
7482 tmp->echocanbridged = conf->chan.echocanbridged;
7483 else {
7484 if (conf->chan.echocanbridged)
7485 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
7486 tmp->echocanbridged = 0;
7488 tmp->busydetect = conf->chan.busydetect;
7489 tmp->busycount = conf->chan.busycount;
7490 tmp->busy_tonelength = conf->chan.busy_tonelength;
7491 tmp->busy_quietlength = conf->chan.busy_quietlength;
7492 tmp->callprogress = conf->chan.callprogress;
7493 tmp->cancallforward = conf->chan.cancallforward;
7494 tmp->dtmfrelax = conf->chan.dtmfrelax;
7495 tmp->callwaiting = tmp->permcallwaiting;
7496 tmp->hidecallerid = tmp->permhidecallerid;
7497 tmp->channel = channel;
7498 tmp->stripmsd = conf->chan.stripmsd;
7499 tmp->use_callerid = conf->chan.use_callerid;
7500 tmp->cid_signalling = conf->chan.cid_signalling;
7501 tmp->cid_start = conf->chan.cid_start;
7502 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
7503 tmp->restrictcid = conf->chan.restrictcid;
7504 tmp->use_callingpres = conf->chan.use_callingpres;
7505 tmp->priindication_oob = conf->chan.priindication_oob;
7506 tmp->priexclusive = conf->chan.priexclusive;
7507 if (tmp->usedistinctiveringdetection) {
7508 if (!tmp->use_callerid) {
7509 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
7510 tmp->use_callerid = 1;
7514 if (tmp->cid_signalling == CID_SIG_SMDI) {
7515 if (!tmp->use_smdi) {
7516 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
7517 tmp->use_smdi = 1;
7520 if (tmp->use_smdi) {
7521 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
7522 if (!(tmp->smdi_iface)) {
7523 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
7524 tmp->use_smdi = 0;
7528 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
7529 tmp->amaflags = conf->chan.amaflags;
7530 if (!here) {
7531 tmp->confno = -1;
7532 tmp->propconfno = -1;
7534 tmp->canpark = conf->chan.canpark;
7535 tmp->transfer = conf->chan.transfer;
7536 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
7537 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
7538 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
7539 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
7540 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
7541 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
7542 tmp->cid_ton = 0;
7543 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
7544 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
7545 tmp->msgstate = -1;
7546 tmp->group = conf->chan.group;
7547 tmp->callgroup = conf->chan.callgroup;
7548 tmp->pickupgroup= conf->chan.pickupgroup;
7549 tmp->rxgain = conf->chan.rxgain;
7550 tmp->txgain = conf->chan.txgain;
7551 tmp->tonezone = conf->chan.tonezone;
7552 tmp->onhooktime = time(NULL);
7553 if (tmp->subs[SUB_REAL].dfd > -1) {
7554 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
7555 if (tmp->dsp)
7556 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
7557 update_conf(tmp);
7558 if (!here) {
7559 if (chan_sig != SIG_PRI)
7560 /* Hang it up to be sure it's good */
7561 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
7563 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
7564 #ifdef HAVE_PRI
7565 /* the dchannel is down so put the channel in alarm */
7566 if (tmp->pri && !pri_is_up(tmp->pri))
7567 tmp->inalarm = 1;
7568 else
7569 tmp->inalarm = 0;
7570 #endif
7571 memset(&si, 0, sizeof(si));
7572 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
7573 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
7574 destroy_dahdi_pvt(&tmp);
7575 return NULL;
7577 if (si.alarms) tmp->inalarm = 1;
7580 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
7581 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
7582 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
7583 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
7586 if (tmp && !here) {
7587 /* nothing on the iflist */
7588 if (!*wlist) {
7589 *wlist = tmp;
7590 tmp->prev = NULL;
7591 tmp->next = NULL;
7592 *wend = tmp;
7593 } else {
7594 /* at least one member on the iflist */
7595 struct dahdi_pvt *working = *wlist;
7597 /* check if we maybe have to put it on the begining */
7598 if (working->channel > tmp->channel) {
7599 tmp->next = *wlist;
7600 tmp->prev = NULL;
7601 (*wlist)->prev = tmp;
7602 *wlist = tmp;
7603 } else {
7604 /* go through all the members and put the member in the right place */
7605 while (working) {
7606 /* in the middle */
7607 if (working->next) {
7608 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
7609 tmp->next = working->next;
7610 tmp->prev = working;
7611 working->next->prev = tmp;
7612 working->next = tmp;
7613 break;
7615 } else {
7616 /* the last */
7617 if (working->channel < tmp->channel) {
7618 working->next = tmp;
7619 tmp->next = NULL;
7620 tmp->prev = working;
7621 *wend = tmp;
7622 break;
7625 working = working->next;
7630 return tmp;
7633 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
7635 int res;
7636 DAHDI_PARAMS par;
7638 /* First, check group matching */
7639 if (groupmatch) {
7640 if ((p->group & groupmatch) != groupmatch)
7641 return 0;
7642 *groupmatched = 1;
7644 /* Check to see if we have a channel match */
7645 if (channelmatch != -1) {
7646 if (p->channel != channelmatch)
7647 return 0;
7648 *channelmatched = 1;
7650 /* We're at least busy at this point */
7651 if (busy) {
7652 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
7653 *busy = 1;
7655 /* If do not disturb, definitely not */
7656 if (p->dnd)
7657 return 0;
7658 /* If guard time, definitely not */
7659 if (p->guardtime && (time(NULL) < p->guardtime))
7660 return 0;
7662 /* If no owner definitely available */
7663 if (!p->owner) {
7664 #ifdef HAVE_PRI
7665 /* Trust PRI */
7666 if (p->pri) {
7667 if (p->resetting || p->call)
7668 return 0;
7669 else
7670 return 1;
7672 #endif
7673 if (!(p->radio || (p->oprmode < 0)))
7675 if (!p->sig || (p->sig == SIG_FXSLS))
7676 return 1;
7677 /* Check hook state */
7678 if (p->subs[SUB_REAL].dfd > -1)
7679 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
7680 else {
7681 /* Assume not off hook on CVRS */
7682 res = 0;
7683 par.rxisoffhook = 0;
7685 if (res) {
7686 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
7687 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
7688 /* When "onhook" that means no battery on the line, and thus
7689 it is out of service..., if it's on a TDM card... If it's a channel
7690 bank, there is no telling... */
7691 if (par.rxbits > -1)
7692 return 1;
7693 if (par.rxisoffhook)
7694 return 1;
7695 else
7696 #ifdef DAHDI_CHECK_HOOKSTATE
7697 return 0;
7698 #else
7699 return 1;
7700 #endif
7701 } else if (par.rxisoffhook) {
7702 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
7703 /* Not available when the other end is off hook */
7704 return 0;
7707 return 1;
7710 /* If it's not an FXO, forget about call wait */
7711 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
7712 return 0;
7714 if (!p->callwaiting) {
7715 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
7716 return 0;
7719 if (p->subs[SUB_CALLWAIT].dfd > -1) {
7720 /* If there is already a call waiting call, then we can't take a second one */
7721 return 0;
7724 if ((p->owner->_state != AST_STATE_UP) &&
7725 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
7726 /* If the current call is not up, then don't allow the call */
7727 return 0;
7729 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
7730 /* Can't take a call wait when the three way calling hasn't been merged yet. */
7731 return 0;
7733 /* We're cool */
7734 return 1;
7737 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
7739 struct dahdi_pvt *p;
7740 DAHDI_BUFFERINFO bi;
7741 int res;
7743 if ((p = ast_malloc(sizeof(*p)))) {
7744 memcpy(p, src, sizeof(struct dahdi_pvt));
7745 ast_mutex_init(&p->lock);
7746 #ifdef HAVE_ZAPTEL
7747 p->subs[SUB_REAL].dfd = dahdi_open("/dev/zap/pseudo");
7748 #else
7749 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
7750 #endif
7751 /* Allocate a DAHDI structure */
7752 if (p->subs[SUB_REAL].dfd < 0) {
7753 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
7754 destroy_dahdi_pvt(&p);
7755 return NULL;
7757 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
7758 if (!res) {
7759 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
7760 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
7761 bi.numbufs = numbufs;
7762 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
7763 if (res < 0) {
7764 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
7766 } else
7767 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
7769 p->destroy = 1;
7770 p->next = iflist;
7771 p->prev = NULL;
7772 iflist = p;
7773 if (iflist->next)
7774 iflist->next->prev = p;
7775 return p;
7779 #ifdef HAVE_PRI
7780 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
7782 int x;
7783 if (backwards)
7784 x = pri->numchans;
7785 else
7786 x = 0;
7787 for (;;) {
7788 if (backwards && (x < 0))
7789 break;
7790 if (!backwards && (x >= pri->numchans))
7791 break;
7792 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
7793 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
7794 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
7795 return x;
7797 if (backwards)
7798 x--;
7799 else
7800 x++;
7802 return -1;
7804 #endif
7806 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
7808 ast_group_t groupmatch = 0;
7809 int channelmatch = -1;
7810 int roundrobin = 0;
7811 int callwait = 0;
7812 int busy = 0;
7813 struct dahdi_pvt *p;
7814 struct ast_channel *tmp = NULL;
7815 char *dest=NULL;
7816 int x;
7817 char *s;
7818 char opt=0;
7819 int res=0, y=0;
7820 int backwards = 0;
7821 #ifdef HAVE_PRI
7822 int crv;
7823 int bearer = -1;
7824 int trunkgroup;
7825 struct dahdi_pri *pri=NULL;
7826 #endif
7827 struct dahdi_pvt *exit, *start, *end;
7828 ast_mutex_t *lock;
7829 int channelmatched = 0;
7830 int groupmatched = 0;
7832 /* Assume we're locking the iflock */
7833 lock = &iflock;
7834 start = iflist;
7835 end = ifend;
7836 if (data) {
7837 dest = ast_strdupa((char *)data);
7838 } else {
7839 ast_log(LOG_WARNING, "Channel requested with no data\n");
7840 return NULL;
7842 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
7843 /* Retrieve the group number */
7844 char *stringp=NULL;
7845 stringp=dest + 1;
7846 s = strsep(&stringp, "/");
7847 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
7848 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
7849 return NULL;
7851 groupmatch = ((ast_group_t) 1 << x);
7852 if (toupper(dest[0]) == 'G') {
7853 if (dest[0] == 'G') {
7854 backwards = 1;
7855 p = ifend;
7856 } else
7857 p = iflist;
7858 } else {
7859 if (dest[0] == 'R') {
7860 backwards = 1;
7861 p = round_robin[x]?round_robin[x]->prev:ifend;
7862 if (!p)
7863 p = ifend;
7864 } else {
7865 p = round_robin[x]?round_robin[x]->next:iflist;
7866 if (!p)
7867 p = iflist;
7869 roundrobin = 1;
7871 } else {
7872 char *stringp=NULL;
7873 stringp=dest;
7874 s = strsep(&stringp, "/");
7875 p = iflist;
7876 if (!strcasecmp(s, "pseudo")) {
7877 /* Special case for pseudo */
7878 x = CHAN_PSEUDO;
7879 channelmatch = x;
7881 #ifdef HAVE_PRI
7882 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
7883 if ((trunkgroup < 1) || (crv < 1)) {
7884 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
7885 return NULL;
7887 res--;
7888 for (x = 0; x < NUM_SPANS; x++) {
7889 if (pris[x].trunkgroup == trunkgroup) {
7890 pri = pris + x;
7891 lock = &pri->lock;
7892 start = pri->crvs;
7893 end = pri->crvend;
7894 break;
7897 if (!pri) {
7898 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
7899 return NULL;
7901 channelmatch = crv;
7902 p = pris[x].crvs;
7904 #endif
7905 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
7906 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
7907 return NULL;
7908 } else {
7909 channelmatch = x;
7912 /* Search for an unowned channel */
7913 ast_mutex_lock(lock);
7914 exit = p;
7915 while (p && !tmp) {
7916 if (roundrobin)
7917 round_robin[x] = p;
7918 #if 0
7919 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
7920 #endif
7922 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
7923 if (option_debug)
7924 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
7925 if (p->inalarm)
7926 goto next;
7928 callwait = (p->owner != NULL);
7929 #ifdef HAVE_PRI
7930 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
7931 if (p->sig != SIG_FXSKS) {
7932 /* Gotta find an actual channel to use for this
7933 CRV if this isn't a callwait */
7934 bearer = pri_find_empty_chan(pri, 0);
7935 if (bearer < 0) {
7936 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
7937 p = NULL;
7938 break;
7940 pri_assign_bearer(p, pri, pri->pvts[bearer]);
7941 } else {
7942 if (alloc_sub(p, 0)) {
7943 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
7944 p = NULL;
7945 break;
7946 } else
7947 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
7948 p->pri = pri;
7951 #endif
7952 if (p->channel == CHAN_PSEUDO) {
7953 p = chandup(p);
7954 if (!p) {
7955 break;
7958 if (p->owner) {
7959 if (alloc_sub(p, SUB_CALLWAIT)) {
7960 p = NULL;
7961 break;
7964 p->outgoing = 1;
7965 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
7966 #ifdef HAVE_PRI
7967 if (p->bearer) {
7968 /* Log owner to bearer channel, too */
7969 p->bearer->owner = tmp;
7971 #endif
7972 /* Make special notes */
7973 if (res > 1) {
7974 if (opt == 'c') {
7975 /* Confirm answer */
7976 p->confirmanswer = 1;
7977 } else if (opt == 'r') {
7978 /* Distinctive ring */
7979 if (res < 3)
7980 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
7981 else
7982 p->distinctivering = y;
7983 } else if (opt == 'd') {
7984 /* If this is an ISDN call, make it digital */
7985 p->digital = 1;
7986 if (tmp)
7987 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
7988 } else {
7989 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
7992 /* Note if the call is a call waiting call */
7993 if (tmp && callwait)
7994 tmp->cdrflags |= AST_CDR_CALLWAIT;
7995 break;
7997 next:
7998 if (backwards) {
7999 p = p->prev;
8000 if (!p)
8001 p = end;
8002 } else {
8003 p = p->next;
8004 if (!p)
8005 p = start;
8007 /* stop when you roll to the one that we started from */
8008 if (p == exit)
8009 break;
8011 ast_mutex_unlock(lock);
8012 restart_monitor();
8013 if (callwait)
8014 *cause = AST_CAUSE_BUSY;
8015 else if (!tmp) {
8016 if (channelmatched) {
8017 if (busy)
8018 *cause = AST_CAUSE_BUSY;
8019 } else if (groupmatched) {
8020 *cause = AST_CAUSE_CONGESTION;
8024 return tmp;
8028 #ifdef HAVE_PRI
8029 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
8031 struct dahdi_pvt *p;
8032 p = pri->crvs;
8033 while (p) {
8034 if (p->channel == crv)
8035 return p;
8036 p = p->next;
8038 return NULL;
8042 static int pri_find_principle(struct dahdi_pri *pri, int channel)
8044 int x;
8045 int span = PRI_SPAN(channel);
8046 int spanfd;
8047 DAHDI_PARAMS param;
8048 int principle = -1;
8049 int explicit = PRI_EXPLICIT(channel);
8050 channel = PRI_CHANNEL(channel);
8052 if (!explicit) {
8053 spanfd = pri_active_dchan_fd(pri);
8054 if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
8055 return -1;
8056 span = pris[param.spanno - 1].prilogicalspan;
8059 for (x = 0; x < pri->numchans; x++) {
8060 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
8061 principle = x;
8062 break;
8066 return principle;
8069 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
8071 int x;
8072 struct dahdi_pvt *crv;
8073 if (!c) {
8074 if (principle < 0)
8075 return -1;
8076 return principle;
8078 if ((principle > -1) &&
8079 (principle < pri->numchans) &&
8080 (pri->pvts[principle]) &&
8081 (pri->pvts[principle]->call == c))
8082 return principle;
8083 /* First, check for other bearers */
8084 for (x = 0; x < pri->numchans; x++) {
8085 if (!pri->pvts[x])
8086 continue;
8087 if (pri->pvts[x]->call == c) {
8088 /* Found our call */
8089 if (principle != x) {
8090 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
8092 if (option_verbose > 2)
8093 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
8094 old->channel, new->channel);
8095 if (new->owner) {
8096 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
8097 old->channel, new->channel, new->channel);
8098 return -1;
8100 /* Fix it all up now */
8101 new->owner = old->owner;
8102 old->owner = NULL;
8103 if (new->owner) {
8104 ast_string_field_build(new->owner, name,
8105 "DAHDI/%d:%d-%d", pri->trunkgroup,
8106 new->channel, 1);
8107 new->owner->tech_pvt = new;
8108 new->owner->fds[0] = new->subs[SUB_REAL].dfd;
8109 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
8110 old->subs[SUB_REAL].owner = NULL;
8111 } else
8112 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);
8113 new->call = old->call;
8114 old->call = NULL;
8116 /* Copy any DSP that may be present */
8117 new->dsp = old->dsp;
8118 new->dsp_features = old->dsp_features;
8119 old->dsp = NULL;
8120 old->dsp_features = 0;
8122 return principle;
8125 /* Now check for a CRV with no bearer */
8126 crv = pri->crvs;
8127 while (crv) {
8128 if (crv->call == c) {
8129 /* This is our match... Perform some basic checks */
8130 if (crv->bearer)
8131 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
8132 else if (pri->pvts[principle]->owner)
8133 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
8134 else {
8135 /* Looks good. Drop the pseudo channel now, clear up the assignment, and
8136 wakeup the potential sleeper */
8137 dahdi_close(crv->subs[SUB_REAL].dfd);
8138 pri->pvts[principle]->call = crv->call;
8139 pri_assign_bearer(crv, pri, pri->pvts[principle]);
8140 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
8141 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
8142 pri->trunkgroup, crv->channel);
8143 wakeup_sub(crv, SUB_REAL, pri);
8145 return principle;
8147 crv = crv->next;
8149 ast_log(LOG_WARNING, "Call specified, but not found?\n");
8150 return -1;
8153 static void *do_idle_thread(void *vchan)
8155 struct ast_channel *chan = vchan;
8156 struct dahdi_pvt *pvt = chan->tech_pvt;
8157 struct ast_frame *f;
8158 char ex[80];
8159 /* Wait up to 30 seconds for an answer */
8160 int newms, ms = 30000;
8161 if (option_verbose > 2)
8162 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
8163 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
8164 if (ast_call(chan, ex, 0)) {
8165 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
8166 ast_hangup(chan);
8167 return NULL;
8169 while ((newms = ast_waitfor(chan, ms)) > 0) {
8170 f = ast_read(chan);
8171 if (!f) {
8172 /* Got hangup */
8173 break;
8175 if (f->frametype == AST_FRAME_CONTROL) {
8176 switch (f->subclass) {
8177 case AST_CONTROL_ANSWER:
8178 /* Launch the PBX */
8179 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
8180 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
8181 chan->priority = 1;
8182 if (option_verbose > 3)
8183 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
8184 ast_pbx_run(chan);
8185 /* It's already hungup, return immediately */
8186 return NULL;
8187 case AST_CONTROL_BUSY:
8188 if (option_verbose > 3)
8189 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
8190 break;
8191 case AST_CONTROL_CONGESTION:
8192 if (option_verbose > 3)
8193 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
8194 break;
8197 ast_frfree(f);
8198 ms = newms;
8200 /* Hangup the channel since nothing happend */
8201 ast_hangup(chan);
8202 return NULL;
8205 #ifndef PRI_RESTART
8206 #error "Upgrade your libpri"
8207 #endif
8208 static void dahdi_pri_message(struct pri *pri, char *s)
8210 int x, y;
8211 int dchan = -1, span = -1;
8212 int dchancount = 0;
8214 if (pri) {
8215 for (x = 0; x < NUM_SPANS; x++) {
8216 for (y = 0; y < NUM_DCHANS; y++) {
8217 if (pris[x].dchans[y])
8218 dchancount++;
8220 if (pris[x].dchans[y] == pri)
8221 dchan = y;
8223 if (dchan >= 0) {
8224 span = x;
8225 break;
8227 dchancount = 0;
8229 if ((dchan >= 0) && (span >= 0)) {
8230 if (dchancount > 1)
8231 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
8232 else
8233 ast_verbose("%s", s);
8234 } else
8235 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
8236 } else
8237 ast_verbose("%s", s);
8239 ast_mutex_lock(&pridebugfdlock);
8241 if (pridebugfd >= 0)
8242 write(pridebugfd, s, strlen(s));
8244 ast_mutex_unlock(&pridebugfdlock);
8247 static void dahdi_pri_error(struct pri *pri, char *s)
8249 int x, y;
8250 int dchan = -1, span = -1;
8251 int dchancount = 0;
8253 if (pri) {
8254 for (x = 0; x < NUM_SPANS; x++) {
8255 for (y = 0; y < NUM_DCHANS; y++) {
8256 if (pris[x].dchans[y])
8257 dchancount++;
8259 if (pris[x].dchans[y] == pri)
8260 dchan = y;
8262 if (dchan >= 0) {
8263 span = x;
8264 break;
8266 dchancount = 0;
8268 if ((dchan >= 0) && (span >= 0)) {
8269 if (dchancount > 1)
8270 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
8271 else
8272 ast_log(LOG_ERROR, "%s", s);
8273 } else
8274 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
8275 } else
8276 ast_log(LOG_ERROR, "%s", s);
8278 ast_mutex_lock(&pridebugfdlock);
8280 if (pridebugfd >= 0)
8281 write(pridebugfd, s, strlen(s));
8283 ast_mutex_unlock(&pridebugfdlock);
8286 static int pri_check_restart(struct dahdi_pri *pri)
8288 do {
8289 pri->resetpos++;
8290 } while ((pri->resetpos < pri->numchans) &&
8291 (!pri->pvts[pri->resetpos] ||
8292 pri->pvts[pri->resetpos]->call ||
8293 pri->pvts[pri->resetpos]->resetting));
8294 if (pri->resetpos < pri->numchans) {
8295 /* Mark the channel as resetting and restart it */
8296 pri->pvts[pri->resetpos]->resetting = 1;
8297 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
8298 } else {
8299 pri->resetting = 0;
8300 time(&pri->lastreset);
8302 return 0;
8305 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
8307 int x;
8308 int redo;
8309 ast_mutex_unlock(&pri->lock);
8310 ast_mutex_lock(&p->lock);
8311 do {
8312 redo = 0;
8313 for (x = 0; x < 3; x++) {
8314 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
8315 redo++;
8316 DEADLOCK_AVOIDANCE(&p->lock);
8318 if (p->subs[x].owner) {
8319 ast_queue_hangup(p->subs[x].owner);
8320 ast_mutex_unlock(&p->subs[x].owner->lock);
8323 } while (redo);
8324 ast_mutex_unlock(&p->lock);
8325 ast_mutex_lock(&pri->lock);
8326 return 0;
8329 static char * redirectingreason2str(int redirectingreason)
8331 switch (redirectingreason) {
8332 case 0:
8333 return "UNKNOWN";
8334 case 1:
8335 return "BUSY";
8336 case 2:
8337 return "NO_REPLY";
8338 case 0xF:
8339 return "UNCONDITIONAL";
8340 default:
8341 return "NOREDIRECT";
8345 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
8347 switch (plan) {
8348 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
8349 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
8350 break;
8351 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
8352 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
8353 break;
8354 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
8355 snprintf(buf, size, "%s%s", pri->localprefix, number);
8356 break;
8357 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
8358 snprintf(buf, size, "%s%s", pri->privateprefix, number);
8359 break;
8360 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
8361 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
8362 break;
8363 default: /* other Q.931 dialplan => don't twiddle with callingnum */
8364 snprintf(buf, size, "%s", number);
8365 break;
8369 static int dahdi_setlaw(int dfd, int law)
8371 int res;
8372 res = ioctl(dfd, DAHDI_SETLAW, &law);
8373 if (res)
8374 return res;
8375 return 0;
8378 static void *pri_dchannel(void *vpri)
8380 struct dahdi_pri *pri = vpri;
8381 pri_event *e;
8382 struct pollfd fds[NUM_DCHANS];
8383 int res;
8384 int chanpos = 0;
8385 int x;
8386 int haveidles;
8387 int activeidles;
8388 int nextidle = -1;
8389 struct ast_channel *c;
8390 struct timeval tv, lowest, *next;
8391 struct timeval lastidle = { 0, 0 };
8392 int doidling=0;
8393 char *cc;
8394 char idlen[80];
8395 struct ast_channel *idle;
8396 pthread_t p;
8397 time_t t;
8398 int i, which=-1;
8399 int numdchans;
8400 int cause=0;
8401 struct dahdi_pvt *crv;
8402 pthread_t threadid;
8403 pthread_attr_t attr;
8404 char ani2str[6];
8405 char plancallingnum[256];
8406 char plancallingani[256];
8407 char calledtonstr[10];
8409 gettimeofday(&lastidle, NULL);
8410 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
8411 /* Need to do idle dialing, check to be sure though */
8412 cc = strchr(pri->idleext, '@');
8413 if (cc) {
8414 *cc = '\0';
8415 cc++;
8416 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
8417 #if 0
8418 /* Extensions may not be loaded yet */
8419 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
8420 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
8421 else
8422 #endif
8423 doidling = 1;
8424 } else
8425 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
8427 for (;;) {
8428 for (i = 0; i < NUM_DCHANS; i++) {
8429 if (!pri->dchannels[i])
8430 break;
8431 fds[i].fd = pri->fds[i];
8432 fds[i].events = POLLIN | POLLPRI;
8433 fds[i].revents = 0;
8435 numdchans = i;
8436 time(&t);
8437 ast_mutex_lock(&pri->lock);
8438 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
8439 if (pri->resetting && pri_is_up(pri)) {
8440 if (pri->resetpos < 0)
8441 pri_check_restart(pri);
8442 } else {
8443 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
8444 pri->resetting = 1;
8445 pri->resetpos = -1;
8449 /* Look for any idle channels if appropriate */
8450 if (doidling && pri_is_up(pri)) {
8451 nextidle = -1;
8452 haveidles = 0;
8453 activeidles = 0;
8454 for (x = pri->numchans; x >= 0; x--) {
8455 if (pri->pvts[x] && !pri->pvts[x]->owner &&
8456 !pri->pvts[x]->call) {
8457 if (haveidles < pri->minunused) {
8458 haveidles++;
8459 } else if (!pri->pvts[x]->resetting) {
8460 nextidle = x;
8461 break;
8463 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
8464 activeidles++;
8466 if (nextidle > -1) {
8467 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
8468 /* Don't create a new idle call more than once per second */
8469 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
8470 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
8471 if (idle) {
8472 pri->pvts[nextidle]->isidlecall = 1;
8473 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
8474 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
8475 dahdi_hangup(idle);
8477 } else
8478 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
8479 gettimeofday(&lastidle, NULL);
8481 } else if ((haveidles < pri->minunused) &&
8482 (activeidles > pri->minidle)) {
8483 /* Mark something for hangup if there is something
8484 that can be hungup */
8485 for (x = pri->numchans; x >= 0; x--) {
8486 /* find a candidate channel */
8487 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
8488 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8489 haveidles++;
8490 /* Stop if we have enough idle channels or
8491 can't spare any more active idle ones */
8492 if ((haveidles >= pri->minunused) ||
8493 (activeidles <= pri->minidle))
8494 break;
8499 /* Start with reasonable max */
8500 lowest = ast_tv(60, 0);
8501 for (i = 0; i < NUM_DCHANS; i++) {
8502 /* Find lowest available d-channel */
8503 if (!pri->dchannels[i])
8504 break;
8505 if ((next = pri_schedule_next(pri->dchans[i]))) {
8506 /* We need relative time here */
8507 tv = ast_tvsub(*next, ast_tvnow());
8508 if (tv.tv_sec < 0) {
8509 tv = ast_tv(0,0);
8511 if (doidling || pri->resetting) {
8512 if (tv.tv_sec > 1) {
8513 tv = ast_tv(1, 0);
8515 } else {
8516 if (tv.tv_sec > 60) {
8517 tv = ast_tv(60, 0);
8520 } else if (doidling || pri->resetting) {
8521 /* Make sure we stop at least once per second if we're
8522 monitoring idle channels */
8523 tv = ast_tv(1,0);
8524 } else {
8525 /* Don't poll for more than 60 seconds */
8526 tv = ast_tv(60, 0);
8528 if (!i || ast_tvcmp(tv, lowest) < 0) {
8529 lowest = tv;
8532 ast_mutex_unlock(&pri->lock);
8534 e = NULL;
8535 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
8537 ast_mutex_lock(&pri->lock);
8538 if (!res) {
8539 for (which = 0; which < NUM_DCHANS; which++) {
8540 if (!pri->dchans[which])
8541 break;
8542 /* Just a timeout, run the scheduler */
8543 e = pri_schedule_run(pri->dchans[which]);
8544 if (e)
8545 break;
8547 } else if (res > -1) {
8548 for (which = 0; which < NUM_DCHANS; which++) {
8549 if (!pri->dchans[which])
8550 break;
8551 if (fds[which].revents & POLLPRI) {
8552 /* Check for an event */
8553 x = 0;
8554 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
8555 if (x)
8556 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);
8557 /* Keep track of alarm state */
8558 if (x == DAHDI_EVENT_ALARM) {
8559 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
8560 pri_find_dchan(pri);
8561 } else if (x == DAHDI_EVENT_NOALARM) {
8562 pri->dchanavail[which] |= DCHAN_NOTINALARM;
8563 pri_restart(pri->dchans[which]);
8566 if (option_debug)
8567 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
8568 } else if (fds[which].revents & POLLIN) {
8569 e = pri_check_event(pri->dchans[which]);
8571 if (e)
8572 break;
8574 } else if (errno != EINTR)
8575 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
8577 if (e) {
8578 if (pri->debug)
8579 pri_dump_event(pri->dchans[which], e);
8581 if (e->e != PRI_EVENT_DCHAN_DOWN) {
8582 if (!(pri->dchanavail[which] & DCHAN_UP)) {
8583 if (option_verbose > 1)
8584 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
8586 pri->dchanavail[which] |= DCHAN_UP;
8587 } else {
8588 if (pri->dchanavail[which] & DCHAN_UP) {
8589 if (option_verbose > 1)
8590 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
8592 pri->dchanavail[which] &= ~DCHAN_UP;
8595 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
8596 /* Must be an NFAS group that has the secondary dchan active */
8597 pri->pri = pri->dchans[which];
8599 switch (e->e) {
8600 case PRI_EVENT_DCHAN_UP:
8601 if (!pri->pri) pri_find_dchan(pri);
8603 /* Note presense of D-channel */
8604 time(&pri->lastreset);
8606 /* Restart in 5 seconds */
8607 if (pri->resetinterval > -1) {
8608 pri->lastreset -= pri->resetinterval;
8609 pri->lastreset += 5;
8611 pri->resetting = 0;
8612 /* Take the channels from inalarm condition */
8613 for (i = 0; i < pri->numchans; i++)
8614 if (pri->pvts[i]) {
8615 pri->pvts[i]->inalarm = 0;
8617 break;
8618 case PRI_EVENT_DCHAN_DOWN:
8619 pri_find_dchan(pri);
8620 if (!pri_is_up(pri)) {
8621 pri->resetting = 0;
8622 /* Hangup active channels and put them in alarm mode */
8623 for (i = 0; i < pri->numchans; i++) {
8624 struct dahdi_pvt *p = pri->pvts[i];
8625 if (p) {
8626 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
8627 /* T309 is not enabled : hangup calls when alarm occurs */
8628 if (p->call) {
8629 if (p->pri && p->pri->pri) {
8630 pri_hangup(p->pri->pri, p->call, -1);
8631 pri_destroycall(p->pri->pri, p->call);
8632 p->call = NULL;
8633 } else
8634 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
8636 if (p->realcall) {
8637 pri_hangup_all(p->realcall, pri);
8638 } else if (p->owner)
8639 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8641 p->inalarm = 1;
8645 break;
8646 case PRI_EVENT_RESTART:
8647 if (e->restart.channel > -1) {
8648 chanpos = pri_find_principle(pri, e->restart.channel);
8649 if (chanpos < 0)
8650 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
8651 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
8652 else {
8653 if (option_verbose > 2)
8654 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n",
8655 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
8656 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8657 if (pri->pvts[chanpos]->call) {
8658 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
8659 pri->pvts[chanpos]->call = NULL;
8661 /* Force soft hangup if appropriate */
8662 if (pri->pvts[chanpos]->realcall)
8663 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8664 else if (pri->pvts[chanpos]->owner)
8665 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8666 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8668 } else {
8669 if (option_verbose > 2)
8670 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
8671 for (x = 0; x < pri->numchans; x++)
8672 if (pri->pvts[x]) {
8673 ast_mutex_lock(&pri->pvts[x]->lock);
8674 if (pri->pvts[x]->call) {
8675 pri_destroycall(pri->pri, pri->pvts[x]->call);
8676 pri->pvts[x]->call = NULL;
8678 if (pri->pvts[chanpos]->realcall)
8679 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8680 else if (pri->pvts[x]->owner)
8681 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8682 ast_mutex_unlock(&pri->pvts[x]->lock);
8685 break;
8686 case PRI_EVENT_KEYPAD_DIGIT:
8687 chanpos = pri_find_principle(pri, e->digit.channel);
8688 if (chanpos < 0) {
8689 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
8690 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
8691 } else {
8692 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
8693 if (chanpos > -1) {
8694 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8695 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
8696 if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
8697 /* how to do that */
8698 int digitlen = strlen(e->digit.digits);
8699 char digit;
8700 int i;
8701 for (i = 0; i < digitlen; i++) {
8702 digit = e->digit.digits[i];
8704 struct ast_frame f = { AST_FRAME_DTMF, digit, };
8705 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
8709 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8712 break;
8714 case PRI_EVENT_INFO_RECEIVED:
8715 chanpos = pri_find_principle(pri, e->ring.channel);
8716 if (chanpos < 0) {
8717 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
8718 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8719 } else {
8720 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
8721 if (chanpos > -1) {
8722 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8723 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
8724 if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
8725 /* how to do that */
8726 int digitlen = strlen(e->ring.callednum);
8727 char digit;
8728 int i;
8729 for (i = 0; i < digitlen; i++) {
8730 digit = e->ring.callednum[i];
8732 struct ast_frame f = { AST_FRAME_DTMF, digit, };
8733 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
8737 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8740 break;
8741 case PRI_EVENT_RING:
8742 crv = NULL;
8743 if (e->ring.channel == -1)
8744 chanpos = pri_find_empty_chan(pri, 1);
8745 else
8746 chanpos = pri_find_principle(pri, e->ring.channel);
8747 /* if no channel specified find one empty */
8748 if (chanpos < 0) {
8749 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
8750 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8751 } else {
8752 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8753 if (pri->pvts[chanpos]->owner) {
8754 if (pri->pvts[chanpos]->call == e->ring.call) {
8755 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
8756 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8757 break;
8758 } else {
8759 /* This is where we handle initial glare */
8760 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
8761 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8762 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8763 chanpos = -1;
8766 if (chanpos > -1)
8767 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8769 if ((chanpos < 0) && (e->ring.flexible))
8770 chanpos = pri_find_empty_chan(pri, 1);
8771 if (chanpos > -1) {
8772 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8773 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
8774 /* Should be safe to lock CRV AFAIK while bearer is still locked */
8775 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
8776 if (crv)
8777 ast_mutex_lock(&crv->lock);
8778 if (!crv || crv->owner) {
8779 pri->pvts[chanpos]->call = NULL;
8780 if (crv) {
8781 if (crv->owner)
8782 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8783 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);
8784 } else
8785 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);
8786 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
8787 if (crv)
8788 ast_mutex_unlock(&crv->lock);
8789 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8790 break;
8793 pri->pvts[chanpos]->call = e->ring.call;
8794 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
8795 if (pri->pvts[chanpos]->use_callerid) {
8796 ast_shrink_phone_number(plancallingnum);
8797 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
8798 #ifdef PRI_ANI
8799 if (!ast_strlen_zero(e->ring.callingani)) {
8800 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
8801 ast_shrink_phone_number(plancallingani);
8802 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
8803 } else {
8804 pri->pvts[chanpos]->cid_ani[0] = '\0';
8806 #endif
8807 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
8808 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
8809 } else {
8810 pri->pvts[chanpos]->cid_num[0] = '\0';
8811 pri->pvts[chanpos]->cid_ani[0] = '\0';
8812 pri->pvts[chanpos]->cid_name[0] = '\0';
8813 pri->pvts[chanpos]->cid_ton = 0;
8815 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
8816 e->ring.redirectingnum, e->ring.callingplanrdnis);
8817 /* If immediate=yes go to s|1 */
8818 if (pri->pvts[chanpos]->immediate) {
8819 if (option_verbose > 2)
8820 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
8821 pri->pvts[chanpos]->exten[0] = 's';
8822 pri->pvts[chanpos]->exten[1] = '\0';
8824 /* Get called number */
8825 else if (!ast_strlen_zero(e->ring.callednum)) {
8826 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
8827 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
8828 } else if (pri->overlapdial)
8829 pri->pvts[chanpos]->exten[0] = '\0';
8830 else {
8831 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
8832 pri->pvts[chanpos]->exten[0] = 's';
8833 pri->pvts[chanpos]->exten[1] = '\0';
8835 /* Set DNID on all incoming calls -- even immediate */
8836 if (!ast_strlen_zero(e->ring.callednum))
8837 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
8838 /* No number yet, but received "sending complete"? */
8839 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
8840 if (option_verbose > 2)
8841 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
8842 pri->pvts[chanpos]->exten[0] = 's';
8843 pri->pvts[chanpos]->exten[1] = '\0';
8845 /* Make sure extension exists (or in overlap dial mode, can exist) */
8846 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
8847 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
8848 /* Setup law */
8849 int law;
8850 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
8851 /* Set to audio mode at this point */
8852 law = 1;
8853 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
8854 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
8856 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
8857 law = DAHDI_LAW_ALAW;
8858 else
8859 law = DAHDI_LAW_MULAW;
8860 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
8861 if (res < 0)
8862 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
8863 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
8864 if (res < 0)
8865 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
8866 if (e->ring.complete || !pri->overlapdial) {
8867 /* Just announce proceeding */
8868 pri->pvts[chanpos]->proceeding = 1;
8869 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
8870 } else {
8871 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
8872 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
8873 else
8874 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
8876 /* Get the use_callingpres state */
8877 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
8879 /* Start PBX */
8880 if (!e->ring.complete && pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
8881 /* Release the PRI lock while we create the channel */
8882 ast_mutex_unlock(&pri->lock);
8883 if (crv) {
8884 /* Set bearer and such */
8885 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
8886 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
8887 pri->pvts[chanpos]->owner = &inuse;
8888 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
8889 } else {
8890 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
8893 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8895 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
8896 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
8898 if (e->ring.ani2 >= 0) {
8899 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
8900 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
8903 #ifdef SUPPORT_USERUSER
8904 if (!ast_strlen_zero(e->ring.useruserinfo)) {
8905 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
8907 #endif
8909 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
8910 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
8911 if (e->ring.redirectingreason >= 0)
8912 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
8914 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8915 ast_mutex_lock(&pri->lock);
8917 pthread_attr_init(&attr);
8918 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
8919 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
8920 if (option_verbose > 2)
8921 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
8922 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
8923 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8924 } else {
8925 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
8926 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8927 if (c)
8928 ast_hangup(c);
8929 else {
8930 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
8931 pri->pvts[chanpos]->call = NULL;
8934 pthread_attr_destroy(&attr);
8935 } else {
8936 ast_mutex_unlock(&pri->lock);
8937 /* Release PRI lock while we create the channel */
8938 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
8939 if (c) {
8940 char calledtonstr[10];
8942 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8944 if (e->ring.ani2 >= 0) {
8945 snprintf(ani2str, 5, "%d", e->ring.ani2);
8946 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
8949 #ifdef SUPPORT_USERUSER
8950 if (!ast_strlen_zero(e->ring.useruserinfo)) {
8951 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
8953 #endif
8955 if (e->ring.redirectingreason >= 0)
8956 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
8958 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
8959 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
8961 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8962 ast_mutex_lock(&pri->lock);
8964 if (option_verbose > 2)
8965 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
8966 plancallingnum, pri->pvts[chanpos]->exten,
8967 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8968 dahdi_enable_ec(pri->pvts[chanpos]);
8969 } else {
8971 ast_mutex_lock(&pri->lock);
8973 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
8974 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8975 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
8976 pri->pvts[chanpos]->call = NULL;
8979 } else {
8980 if (option_verbose > 2)
8981 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
8982 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
8983 pri->pvts[chanpos]->prioffset, pri->span);
8984 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
8985 pri->pvts[chanpos]->call = NULL;
8986 pri->pvts[chanpos]->exten[0] = '\0';
8988 if (crv)
8989 ast_mutex_unlock(&crv->lock);
8990 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8991 } else {
8992 if (e->ring.flexible)
8993 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
8994 else
8995 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
8997 break;
8998 case PRI_EVENT_RINGING:
8999 chanpos = pri_find_principle(pri, e->ringing.channel);
9000 if (chanpos < 0) {
9001 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
9002 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
9003 } else {
9004 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
9005 if (chanpos < 0) {
9006 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
9007 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
9008 } else {
9009 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9010 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
9011 dahdi_enable_ec(pri->pvts[chanpos]);
9012 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
9013 pri->pvts[chanpos]->alerting = 1;
9014 } else
9015 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
9016 #ifdef PRI_PROGRESS_MASK
9017 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9018 #else
9019 if (e->ringing.progress == 8) {
9020 #endif
9021 /* Now we can do call progress detection */
9022 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9023 /* RINGING detection isn't required because we got ALERTING signal */
9024 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
9025 pri->pvts[chanpos]->dsp_features = 0;
9029 #ifdef SUPPORT_USERUSER
9030 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
9031 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9032 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9033 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
9034 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9036 #endif
9038 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9041 break;
9042 case PRI_EVENT_PROGRESS:
9043 /* Get chan value if e->e is not PRI_EVNT_RINGING */
9044 chanpos = pri_find_principle(pri, e->proceeding.channel);
9045 if (chanpos > -1) {
9046 #ifdef PRI_PROGRESS_MASK
9047 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
9048 #else
9049 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
9050 #endif
9051 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
9053 if (e->proceeding.cause > -1) {
9054 if (option_verbose > 2)
9055 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
9057 /* Work around broken, out of spec USER_BUSY cause in a progress message */
9058 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
9059 if (pri->pvts[chanpos]->owner) {
9060 if (option_verbose > 2)
9061 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
9063 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
9064 f.subclass = AST_CONTROL_BUSY;
9069 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9070 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
9071 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
9072 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9073 #ifdef PRI_PROGRESS_MASK
9074 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9075 #else
9076 if (e->proceeding.progress == 8) {
9077 #endif
9078 /* Now we can do call progress detection */
9079 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9080 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9081 pri->pvts[chanpos]->dsp_features = 0;
9084 pri->pvts[chanpos]->progress = 1;
9085 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9088 break;
9089 case PRI_EVENT_PROCEEDING:
9090 chanpos = pri_find_principle(pri, e->proceeding.channel);
9091 if (chanpos > -1) {
9092 if (!pri->pvts[chanpos]->proceeding) {
9093 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
9095 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9096 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
9097 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
9098 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9099 #ifdef PRI_PROGRESS_MASK
9100 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9101 #else
9102 if (e->proceeding.progress == 8) {
9103 #endif
9104 /* Now we can do call progress detection */
9105 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9106 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9107 pri->pvts[chanpos]->dsp_features = 0;
9109 /* Bring voice path up */
9110 f.subclass = AST_CONTROL_PROGRESS;
9111 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9113 pri->pvts[chanpos]->proceeding = 1;
9114 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9117 break;
9118 case PRI_EVENT_FACNAME:
9119 chanpos = pri_find_principle(pri, e->facname.channel);
9120 if (chanpos < 0) {
9121 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
9122 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
9123 } else {
9124 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
9125 if (chanpos < 0) {
9126 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
9127 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
9128 } else {
9129 /* Re-use *69 field for PRI */
9130 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9131 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
9132 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
9133 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
9134 dahdi_enable_ec(pri->pvts[chanpos]);
9135 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9138 break;
9139 case PRI_EVENT_ANSWER:
9140 chanpos = pri_find_principle(pri, e->answer.channel);
9141 if (chanpos < 0) {
9142 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
9143 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
9144 } else {
9145 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
9146 if (chanpos < 0) {
9147 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
9148 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
9149 } else {
9150 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9151 /* Now we can do call progress detection */
9153 /* We changed this so it turns on the DSP no matter what... progress or no progress.
9154 * By this time, we need DTMF detection and other features that were previously disabled
9155 * -- Matt F */
9156 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9157 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9158 pri->pvts[chanpos]->dsp_features = 0;
9160 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
9161 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
9162 x = DAHDI_START;
9163 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
9164 if (res < 0) {
9165 if (errno != EINPROGRESS) {
9166 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
9169 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
9170 pri->pvts[chanpos]->dialing = 1;
9171 /* Send any "w" waited stuff */
9172 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
9173 if (res < 0) {
9174 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
9175 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
9176 } else
9177 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
9178 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
9179 } else if (pri->pvts[chanpos]->confirmanswer) {
9180 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
9181 } else {
9182 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
9183 /* Enable echo cancellation if it's not on already */
9184 dahdi_enable_ec(pri->pvts[chanpos]);
9187 #ifdef SUPPORT_USERUSER
9188 if (!ast_strlen_zero(e->answer.useruserinfo)) {
9189 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9190 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9191 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
9192 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9194 #endif
9196 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9199 break;
9200 case PRI_EVENT_HANGUP:
9201 chanpos = pri_find_principle(pri, e->hangup.channel);
9202 if (chanpos < 0) {
9203 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
9204 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9205 } else {
9206 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9207 if (chanpos > -1) {
9208 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9209 if (!pri->pvts[chanpos]->alreadyhungup) {
9210 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
9211 pri->pvts[chanpos]->alreadyhungup = 1;
9212 if (pri->pvts[chanpos]->realcall)
9213 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9214 else if (pri->pvts[chanpos]->owner) {
9215 /* Queue a BUSY instead of a hangup if our cause is appropriate */
9216 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
9217 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
9218 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9219 else {
9220 switch (e->hangup.cause) {
9221 case PRI_CAUSE_USER_BUSY:
9222 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
9223 break;
9224 case PRI_CAUSE_CALL_REJECTED:
9225 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
9226 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
9227 case PRI_CAUSE_SWITCH_CONGESTION:
9228 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
9229 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
9230 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
9231 break;
9232 default:
9233 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9237 if (option_verbose > 2)
9238 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
9239 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
9240 } else {
9241 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
9242 pri->pvts[chanpos]->call = NULL;
9244 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
9245 if (option_verbose > 2)
9246 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
9247 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9248 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
9249 pri->pvts[chanpos]->resetting = 1;
9251 if (e->hangup.aoc_units > -1)
9252 if (option_verbose > 2)
9253 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9254 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
9256 #ifdef SUPPORT_USERUSER
9257 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
9258 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9259 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9260 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9261 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9263 #endif
9265 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9266 } else {
9267 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
9268 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9271 break;
9272 #ifndef PRI_EVENT_HANGUP_REQ
9273 #error please update libpri
9274 #endif
9275 case PRI_EVENT_HANGUP_REQ:
9276 chanpos = pri_find_principle(pri, e->hangup.channel);
9277 if (chanpos < 0) {
9278 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
9279 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9280 } else {
9281 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9282 if (chanpos > -1) {
9283 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9284 if (pri->pvts[chanpos]->realcall)
9285 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9286 else if (pri->pvts[chanpos]->owner) {
9287 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
9288 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
9289 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9290 else {
9291 switch (e->hangup.cause) {
9292 case PRI_CAUSE_USER_BUSY:
9293 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
9294 break;
9295 case PRI_CAUSE_CALL_REJECTED:
9296 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
9297 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
9298 case PRI_CAUSE_SWITCH_CONGESTION:
9299 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
9300 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
9301 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
9302 break;
9303 default:
9304 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9307 if (option_verbose > 2)
9308 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);
9309 if (e->hangup.aoc_units > -1)
9310 if (option_verbose > 2)
9311 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9312 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
9313 } else {
9314 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
9315 pri->pvts[chanpos]->call = NULL;
9317 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
9318 if (option_verbose > 2)
9319 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
9320 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9321 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
9322 pri->pvts[chanpos]->resetting = 1;
9325 #ifdef SUPPORT_USERUSER
9326 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
9327 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9328 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9329 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9330 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9332 #endif
9334 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9335 } else {
9336 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);
9339 break;
9340 case PRI_EVENT_HANGUP_ACK:
9341 chanpos = pri_find_principle(pri, e->hangup.channel);
9342 if (chanpos < 0) {
9343 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
9344 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9345 } else {
9346 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9347 if (chanpos > -1) {
9348 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9349 pri->pvts[chanpos]->call = NULL;
9350 pri->pvts[chanpos]->resetting = 0;
9351 if (pri->pvts[chanpos]->owner) {
9352 if (option_verbose > 2)
9353 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);
9356 #ifdef SUPPORT_USERUSER
9357 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
9358 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9359 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9360 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9361 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9363 #endif
9365 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9368 break;
9369 case PRI_EVENT_CONFIG_ERR:
9370 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
9371 break;
9372 case PRI_EVENT_RESTART_ACK:
9373 chanpos = pri_find_principle(pri, e->restartack.channel);
9374 if (chanpos < 0) {
9375 /* Sometime switches (e.g. I421 / British Telecom) don't give us the
9376 channel number, so we have to figure it out... This must be why
9377 everybody resets exactly a channel at a time. */
9378 for (x = 0; x < pri->numchans; x++) {
9379 if (pri->pvts[x] && pri->pvts[x]->resetting) {
9380 chanpos = x;
9381 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9382 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
9383 pri->pvts[chanpos]->prioffset, pri->span);
9384 if (pri->pvts[chanpos]->realcall)
9385 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9386 else if (pri->pvts[chanpos]->owner) {
9387 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
9388 pri->pvts[chanpos]->prioffset, pri->span);
9389 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9391 pri->pvts[chanpos]->resetting = 0;
9392 if (option_verbose > 2)
9393 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
9394 pri->pvts[chanpos]->prioffset, pri->span);
9395 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9396 if (pri->resetting)
9397 pri_check_restart(pri);
9398 break;
9401 if (chanpos < 0) {
9402 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
9403 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
9405 } else {
9406 if (pri->pvts[chanpos]) {
9407 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9408 if (pri->pvts[chanpos]->realcall)
9409 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9410 else if (pri->pvts[chanpos]->owner) {
9411 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
9412 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
9413 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9415 pri->pvts[chanpos]->resetting = 0;
9416 if (option_verbose > 2)
9417 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
9418 pri->pvts[chanpos]->prioffset, pri->span);
9419 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9420 if (pri->resetting)
9421 pri_check_restart(pri);
9424 break;
9425 case PRI_EVENT_SETUP_ACK:
9426 chanpos = pri_find_principle(pri, e->setup_ack.channel);
9427 if (chanpos < 0) {
9428 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
9429 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
9430 } else {
9431 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
9432 if (chanpos > -1) {
9433 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9434 pri->pvts[chanpos]->setup_ack = 1;
9435 /* Send any queued digits */
9436 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
9437 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
9438 pri_information(pri->pri, pri->pvts[chanpos]->call,
9439 pri->pvts[chanpos]->dialdest[x]);
9441 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9442 } else
9443 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
9445 break;
9446 case PRI_EVENT_NOTIFY:
9447 chanpos = pri_find_principle(pri, e->notify.channel);
9448 if (chanpos < 0) {
9449 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
9450 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
9451 } else {
9452 struct ast_frame f = { AST_FRAME_CONTROL, };
9453 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9454 switch (e->notify.info) {
9455 case PRI_NOTIFY_REMOTE_HOLD:
9456 f.subclass = AST_CONTROL_HOLD;
9457 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9458 break;
9459 case PRI_NOTIFY_REMOTE_RETRIEVAL:
9460 f.subclass = AST_CONTROL_UNHOLD;
9461 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9462 break;
9464 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9466 break;
9467 default:
9468 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
9471 ast_mutex_unlock(&pri->lock);
9473 /* Never reached */
9474 return NULL;
9477 static int start_pri(struct dahdi_pri *pri)
9479 int res, x;
9480 DAHDI_PARAMS p;
9481 DAHDI_BUFFERINFO bi;
9482 DAHDI_SPANINFO si;
9483 int i;
9485 for (i = 0; i < NUM_DCHANS; i++) {
9486 if (!pri->dchannels[i])
9487 break;
9488 #ifdef HAVE_ZAPTEL
9489 pri->fds[i] = open("/dev/zap/channel", O_RDWR, 0600);
9490 #else
9491 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR, 0600);
9492 #endif
9493 x = pri->dchannels[i];
9494 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
9495 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
9496 return -1;
9498 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
9499 if (res) {
9500 dahdi_close(pri->fds[i]);
9501 pri->fds[i] = -1;
9502 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
9503 return -1;
9505 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
9506 dahdi_close(pri->fds[i]);
9507 pri->fds[i] = -1;
9508 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/DAHDI.conf\n", x);
9509 return -1;
9511 memset(&si, 0, sizeof(si));
9512 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
9513 if (res) {
9514 dahdi_close(pri->fds[i]);
9515 pri->fds[i] = -1;
9516 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
9518 if (!si.alarms)
9519 pri->dchanavail[i] |= DCHAN_NOTINALARM;
9520 else
9521 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
9522 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
9523 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
9524 bi.numbufs = 32;
9525 bi.bufsize = 1024;
9526 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
9527 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
9528 dahdi_close(pri->fds[i]);
9529 pri->fds[i] = -1;
9530 return -1;
9532 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
9533 /* Force overlap dial if we're doing GR-303! */
9534 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
9535 pri->overlapdial = 1;
9536 pri_set_overlapdial(pri->dchans[i],pri->overlapdial);
9537 /* Enslave to master if appropriate */
9538 if (i)
9539 pri_enslave(pri->dchans[0], pri->dchans[i]);
9540 if (!pri->dchans[i]) {
9541 dahdi_close(pri->fds[i]);
9542 pri->fds[i] = -1;
9543 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
9544 return -1;
9546 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
9547 pri_set_nsf(pri->dchans[i], pri->nsf);
9548 #ifdef PRI_GETSET_TIMERS
9549 for (x = 0; x < PRI_MAX_TIMERS; x++) {
9550 if (pritimers[x] != 0)
9551 pri_set_timer(pri->dchans[i], x, pritimers[x]);
9553 #endif
9555 /* Assume primary is the one we use */
9556 pri->pri = pri->dchans[0];
9557 pri->resetpos = -1;
9558 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
9559 for (i = 0; i < NUM_DCHANS; i++) {
9560 if (!pri->dchannels[i])
9561 break;
9562 dahdi_close(pri->fds[i]);
9563 pri->fds[i] = -1;
9565 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
9566 return -1;
9568 return 0;
9571 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
9573 int which, span;
9574 char *ret = NULL;
9576 if (pos != rpos)
9577 return ret;
9579 for (which = span = 0; span < NUM_SPANS; span++) {
9580 if (pris[span].pri && ++which > state) {
9581 asprintf(&ret, "%d", span + 1); /* user indexes start from 1 */
9582 break;
9585 return ret;
9588 static char *complete_span_4(const char *line, const char *word, int pos, int state)
9590 return complete_span_helper(line,word,pos,state,3);
9593 static char *complete_span_5(const char *line, const char *word, int pos, int state)
9595 return complete_span_helper(line,word,pos,state,4);
9598 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
9600 int myfd;
9602 if (!strncasecmp(argv[1], "set", 3)) {
9603 if (argc < 5)
9604 return RESULT_SHOWUSAGE;
9606 if (ast_strlen_zero(argv[4]))
9607 return RESULT_SHOWUSAGE;
9609 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
9610 if (myfd < 0) {
9611 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
9612 return RESULT_SUCCESS;
9615 ast_mutex_lock(&pridebugfdlock);
9617 if (pridebugfd >= 0)
9618 close(pridebugfd);
9620 pridebugfd = myfd;
9621 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
9623 ast_mutex_unlock(&pridebugfdlock);
9625 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
9626 } else {
9627 /* Assume it is unset */
9628 ast_mutex_lock(&pridebugfdlock);
9629 close(pridebugfd);
9630 pridebugfd = -1;
9631 ast_cli(fd, "PRI debug output to file disabled\n");
9632 ast_mutex_unlock(&pridebugfdlock);
9635 return RESULT_SUCCESS;
9638 #ifdef HAVE_PRI_VERSION
9639 static int handle_pri_version(int fd, int agc, char *argv[]) {
9640 ast_cli(fd, "libpri version: %s\n", pri_get_version());
9641 return RESULT_SUCCESS;
9643 #endif
9645 static int handle_pri_debug(int fd, int argc, char *argv[])
9647 int span;
9648 int x;
9649 if (argc < 4) {
9650 return RESULT_SHOWUSAGE;
9652 span = atoi(argv[3]);
9653 if ((span < 1) || (span > NUM_SPANS)) {
9654 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
9655 return RESULT_SUCCESS;
9657 if (!pris[span-1].pri) {
9658 ast_cli(fd, "No PRI running on span %d\n", span);
9659 return RESULT_SUCCESS;
9661 for (x = 0; x < NUM_DCHANS; x++) {
9662 if (pris[span-1].dchans[x])
9663 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
9664 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
9665 PRI_DEBUG_Q921_STATE);
9667 ast_cli(fd, "Enabled debugging on span %d\n", span);
9668 return RESULT_SUCCESS;
9673 static int handle_pri_no_debug(int fd, int argc, char *argv[])
9675 int span;
9676 int x;
9677 if (argc < 5)
9678 return RESULT_SHOWUSAGE;
9679 span = atoi(argv[4]);
9680 if ((span < 1) || (span > NUM_SPANS)) {
9681 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
9682 return RESULT_SUCCESS;
9684 if (!pris[span-1].pri) {
9685 ast_cli(fd, "No PRI running on span %d\n", span);
9686 return RESULT_SUCCESS;
9688 for (x = 0; x < NUM_DCHANS; x++) {
9689 if (pris[span-1].dchans[x])
9690 pri_set_debug(pris[span-1].dchans[x], 0);
9692 ast_cli(fd, "Disabled debugging on span %d\n", span);
9693 return RESULT_SUCCESS;
9696 static int handle_pri_really_debug(int fd, int argc, char *argv[])
9698 int span;
9699 int x;
9700 if (argc < 5)
9701 return RESULT_SHOWUSAGE;
9702 span = atoi(argv[4]);
9703 if ((span < 1) || (span > NUM_SPANS)) {
9704 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
9705 return RESULT_SUCCESS;
9707 if (!pris[span-1].pri) {
9708 ast_cli(fd, "No PRI running on span %d\n", span);
9709 return RESULT_SUCCESS;
9711 for (x = 0; x < NUM_DCHANS; x++) {
9712 if (pris[span-1].dchans[x])
9713 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
9714 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
9715 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
9717 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
9718 return RESULT_SUCCESS;
9721 static void build_status(char *s, size_t len, int status, int active)
9723 if (!s || len < 1) {
9724 return;
9726 s[0] = '\0';
9727 if (status & DCHAN_PROVISIONED)
9728 strncat(s, "Provisioned, ", len - strlen(s) - 1);
9729 if (!(status & DCHAN_NOTINALARM))
9730 strncat(s, "In Alarm, ", len - strlen(s) - 1);
9731 if (status & DCHAN_UP)
9732 strncat(s, "Up", len - strlen(s) - 1);
9733 else
9734 strncat(s, "Down", len - strlen(s) - 1);
9735 if (active)
9736 strncat(s, ", Active", len - strlen(s) - 1);
9737 else
9738 strncat(s, ", Standby", len - strlen(s) - 1);
9739 s[len - 1] = '\0';
9742 static int handle_pri_show_spans(int fd, int argc, char *argv[])
9744 int span;
9745 int x;
9746 char status[256];
9747 if (argc != 3)
9748 return RESULT_SHOWUSAGE;
9750 for (span = 0; span < NUM_SPANS; span++) {
9751 if (pris[span].pri) {
9752 for (x = 0; x < NUM_DCHANS; x++) {
9753 if (pris[span].dchannels[x]) {
9754 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
9755 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
9760 return RESULT_SUCCESS;
9763 static int handle_pri_show_span(int fd, int argc, char *argv[])
9765 int span;
9766 int x;
9767 char status[256];
9768 if (argc < 4)
9769 return RESULT_SHOWUSAGE;
9770 span = atoi(argv[3]);
9771 if ((span < 1) || (span > NUM_SPANS)) {
9772 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
9773 return RESULT_SUCCESS;
9775 if (!pris[span-1].pri) {
9776 ast_cli(fd, "No PRI running on span %d\n", span);
9777 return RESULT_SUCCESS;
9779 for (x = 0; x < NUM_DCHANS; x++) {
9780 if (pris[span-1].dchannels[x]) {
9781 #ifdef PRI_DUMP_INFO_STR
9782 char *info_str = NULL;
9783 #endif
9784 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
9785 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
9786 ast_cli(fd, "Status: %s\n", status);
9787 #ifdef PRI_DUMP_INFO_STR
9788 info_str = pri_dump_info_str(pris[span-1].pri);
9789 if (info_str) {
9790 ast_cli(fd, "%s", info_str);
9791 free(info_str);
9793 #else
9794 pri_dump_info(pris[span-1].pri);
9795 #endif
9796 ast_cli(fd, "\n");
9799 return RESULT_SUCCESS;
9802 static int handle_pri_show_debug(int fd, int argc, char *argv[])
9804 int x;
9805 int span;
9806 int count=0;
9807 int debug=0;
9809 for (span = 0; span < NUM_SPANS; span++) {
9810 if (pris[span].pri) {
9811 for (x = 0; x < NUM_DCHANS; x++) {
9812 debug = 0;
9813 if (pris[span].dchans[x]) {
9814 debug = pri_get_debug(pris[span].dchans[x]);
9815 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" );
9816 count++;
9822 ast_mutex_lock(&pridebugfdlock);
9823 if (pridebugfd >= 0)
9824 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
9825 ast_mutex_unlock(&pridebugfdlock);
9827 if (!count)
9828 ast_cli(fd, "No debug set or no PRI running\n");
9829 return RESULT_SUCCESS;
9832 static const char pri_debug_help[] =
9833 "Usage: pri debug span <span>\n"
9834 " Enables debugging on a given PRI span\n";
9836 static const char pri_no_debug_help[] =
9837 "Usage: pri no debug span <span>\n"
9838 " Disables debugging on a given PRI span\n";
9840 static const char pri_really_debug_help[] =
9841 "Usage: pri intensive debug span <span>\n"
9842 " Enables debugging down to the Q.921 level\n";
9844 static const char pri_show_span_help[] =
9845 "Usage: pri show span <span>\n"
9846 " Displays PRI Information on a given PRI span\n";
9848 static const char pri_show_spans_help[] =
9849 "Usage: pri show spans\n"
9850 " Displays PRI Information\n";
9852 static struct ast_cli_entry dahdi_pri_cli[] = {
9853 { { "pri", "debug", "span", NULL },
9854 handle_pri_debug, "Enables PRI debugging on a span",
9855 pri_debug_help, complete_span_4 },
9857 { { "pri", "no", "debug", "span", NULL },
9858 handle_pri_no_debug, "Disables PRI debugging on a span",
9859 pri_no_debug_help, complete_span_5 },
9861 { { "pri", "intense", "debug", "span", NULL },
9862 handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
9863 pri_really_debug_help, complete_span_5 },
9865 { { "pri", "show", "spans", NULL },
9866 handle_pri_show_spans, "Displays PRI Information",
9867 pri_show_spans_help },
9869 { { "pri", "show", "span", NULL },
9870 handle_pri_show_span, "Displays PRI Information",
9871 pri_show_span_help, complete_span_4 },
9873 { { "pri", "show", "debug", NULL },
9874 handle_pri_show_debug, "Displays current PRI debug settings" },
9876 { { "pri", "set", "debug", "file", NULL },
9877 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
9879 { { "pri", "unset", "debug", "file", NULL },
9880 handle_pri_set_debug_file, "Ends PRI debug output to file" },
9882 #ifdef HAVE_PRI_VERSION
9883 { { "pri", "show", "version", NULL },
9884 handle_pri_version, "Displays version of libpri" },
9885 #endif
9888 #endif /* HAVE_PRI */
9890 static int dahdi_destroy_channel(int fd, int argc, char **argv)
9892 int channel;
9894 if (argc != 4)
9895 return RESULT_SHOWUSAGE;
9897 channel = atoi(argv[3]);
9899 return dahdi_destroy_channel_bynum(channel);
9902 static int setup_dahdi(int reload);
9903 static int dahdi_restart(void)
9905 if (option_verbose > 0)
9906 ast_verbose(VERBOSE_PREFIX_1 "Destroying channels and reloading DAHDI configuration.\n");
9907 while (iflist) {
9908 if (option_debug)
9909 ast_log(LOG_DEBUG, "Destroying DAHDI channel no. %d\n", iflist->channel);
9910 /* Also updates iflist: */
9911 destroy_channel(NULL, iflist, 1);
9913 if (option_debug)
9914 ast_log(LOG_DEBUG, "Channels destroyed. Now re-reading config.\n");
9915 if (setup_dahdi(0) != 0) {
9916 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
9917 return 1;
9919 return 0;
9922 static int dahdi_restart_cmd(int fd, int argc, char **argv)
9924 if (argc != 2) {
9925 return RESULT_SHOWUSAGE;
9928 if (dahdi_restart() != 0)
9929 return RESULT_FAILURE;
9930 return RESULT_SUCCESS;
9933 static int action_dahdirestart(struct mansession *s, const struct message *m)
9935 if (dahdi_restart() != 0) {
9936 astman_send_error(s, m, "Failed rereading DAHDI configuration");
9937 return 1;
9939 astman_send_ack(s, m, "DAHDIRestart: Success");
9940 return 0;
9943 static int dahdi_show_channels(int fd, int argc, char **argv)
9945 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
9946 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
9947 struct dahdi_pvt *tmp = NULL;
9948 char tmps[20] = "";
9949 ast_mutex_t *lock;
9950 struct dahdi_pvt *start;
9951 #ifdef HAVE_PRI
9952 int trunkgroup;
9953 struct dahdi_pri *pri = NULL;
9954 int x;
9955 #endif
9957 lock = &iflock;
9958 start = iflist;
9960 #ifdef HAVE_PRI
9961 if (argc == 4) {
9962 if ((trunkgroup = atoi(argv[3])) < 1)
9963 return RESULT_SHOWUSAGE;
9964 for (x = 0; x < NUM_SPANS; x++) {
9965 if (pris[x].trunkgroup == trunkgroup) {
9966 pri = pris + x;
9967 break;
9970 if (pri) {
9971 start = pri->crvs;
9972 lock = &pri->lock;
9973 } else {
9974 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
9975 return RESULT_FAILURE;
9977 } else
9978 #endif
9979 if (argc != 3)
9980 return RESULT_SHOWUSAGE;
9982 ast_mutex_lock(lock);
9983 #ifdef HAVE_PRI
9984 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
9985 #else
9986 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
9987 #endif
9989 tmp = start;
9990 while (tmp) {
9991 if (tmp->channel > 0) {
9992 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
9993 } else
9994 ast_copy_string(tmps, "pseudo", sizeof(tmps));
9995 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
9996 tmp = tmp->next;
9998 ast_mutex_unlock(lock);
9999 return RESULT_SUCCESS;
10000 #undef FORMAT
10001 #undef FORMAT2
10004 static int dahdi_show_channel(int fd, int argc, char **argv)
10006 int channel;
10007 struct dahdi_pvt *tmp = NULL;
10008 DAHDI_CONFINFO ci;
10009 DAHDI_PARAMS ps;
10010 int x;
10011 ast_mutex_t *lock;
10012 struct dahdi_pvt *start;
10013 #ifdef HAVE_PRI
10014 char *c;
10015 int trunkgroup;
10016 struct dahdi_pri *pri=NULL;
10017 #endif
10019 lock = &iflock;
10020 start = iflist;
10022 if (argc != 4)
10023 return RESULT_SHOWUSAGE;
10024 #ifdef HAVE_PRI
10025 if ((c = strchr(argv[3], ':'))) {
10026 if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
10027 return RESULT_SHOWUSAGE;
10028 if ((trunkgroup < 1) || (channel < 1))
10029 return RESULT_SHOWUSAGE;
10030 for (x = 0; x < NUM_SPANS; x++) {
10031 if (pris[x].trunkgroup == trunkgroup) {
10032 pri = pris + x;
10033 break;
10036 if (pri) {
10037 start = pri->crvs;
10038 lock = &pri->lock;
10039 } else {
10040 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10041 return RESULT_FAILURE;
10043 } else
10044 #endif
10045 channel = atoi(argv[3]);
10047 ast_mutex_lock(lock);
10048 tmp = start;
10049 while (tmp) {
10050 if (tmp->channel == channel) {
10051 #ifdef HAVE_PRI
10052 if (pri)
10053 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
10054 else
10055 #endif
10056 ast_cli(fd, "Channel: %d\n", tmp->channel);
10057 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
10058 ast_cli(fd, "Span: %d\n", tmp->span);
10059 ast_cli(fd, "Extension: %s\n", tmp->exten);
10060 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
10061 ast_cli(fd, "Context: %s\n", tmp->context);
10062 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
10063 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
10064 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
10065 ast_cli(fd, "Destroy: %d\n", tmp->destroy);
10066 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
10067 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
10068 ast_cli(fd, "Radio: %d\n", tmp->radio);
10069 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
10070 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)" : "");
10071 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)" : "");
10072 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)" : "");
10073 ast_cli(fd, "Confno: %d\n", tmp->confno);
10074 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
10075 ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
10076 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
10077 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
10078 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
10079 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
10080 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
10081 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
10082 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
10083 if (tmp->master)
10084 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
10085 for (x = 0; x < MAX_SLAVES; x++) {
10086 if (tmp->slaves[x])
10087 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
10089 #ifdef HAVE_PRI
10090 if (tmp->pri) {
10091 ast_cli(fd, "PRI Flags: ");
10092 if (tmp->resetting)
10093 ast_cli(fd, "Resetting ");
10094 if (tmp->call)
10095 ast_cli(fd, "Call ");
10096 if (tmp->bearer)
10097 ast_cli(fd, "Bearer ");
10098 ast_cli(fd, "\n");
10099 if (tmp->logicalspan)
10100 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
10101 else
10102 ast_cli(fd, "PRI Logical Span: Implicit\n");
10105 #endif
10106 memset(&ci, 0, sizeof(ci));
10107 ps.channo = tmp->channel;
10108 if (tmp->subs[SUB_REAL].dfd > -1) {
10109 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
10110 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
10112 #ifdef DAHDI_GETCONFMUTE
10113 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
10114 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
10116 #endif
10117 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
10118 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
10119 } else {
10120 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
10123 ast_mutex_unlock(lock);
10124 return RESULT_SUCCESS;
10126 tmp = tmp->next;
10129 ast_cli(fd, "Unable to find given channel %d\n", channel);
10130 ast_mutex_unlock(lock);
10131 return RESULT_FAILURE;
10134 static char dahdi_show_cadences_usage[] =
10135 "Usage: dahdi show cadences\n"
10136 " Shows all cadences currently defined\n";
10138 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
10140 int i, j;
10141 for (i = 0; i < num_cadence; i++) {
10142 char output[1024];
10143 char tmp[16], tmp2[64];
10144 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
10145 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
10147 for (j = 0; j < 16; j++) {
10148 if (cadences[i].ringcadence[j] == 0)
10149 break;
10150 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10151 if (cidrings[i] * 2 - 1 == j)
10152 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10153 else
10154 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10155 if (j != 0)
10156 strncat(output, ",", sizeof(output) - strlen(output) - 1);
10157 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10159 ast_cli(fd,"%s\n",output);
10161 return 0;
10164 /* Based on irqmiss.c */
10165 static int dahdi_show_status(int fd, int argc, char *argv[]) {
10166 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10167 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10169 int span;
10170 int res;
10171 char alarms[50];
10173 int ctl;
10174 DAHDI_SPANINFO s;
10176 #ifdef HAVE_ZAPTEL
10177 ctl = open("/dev/zap/ctl", O_RDWR);
10178 #else
10179 ctl = open("/dev/dahdi/ctl", O_RDWR);
10180 #endif
10181 if (ctl < 0) {
10182 ast_log(LOG_WARNING, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
10183 ast_cli(fd, "No DAHDI interface found.\n");
10184 return RESULT_FAILURE;
10186 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10188 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
10189 s.spanno = span;
10190 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
10191 if (res) {
10192 continue;
10194 alarms[0] = '\0';
10195 if (s.alarms > 0) {
10196 if (s.alarms & DAHDI_ALARM_BLUE)
10197 strcat(alarms, "BLU/");
10198 if (s.alarms & DAHDI_ALARM_YELLOW)
10199 strcat(alarms, "YEL/");
10200 if (s.alarms & DAHDI_ALARM_RED)
10201 strcat(alarms, "RED/");
10202 if (s.alarms & DAHDI_ALARM_LOOPBACK)
10203 strcat(alarms, "LB/");
10204 if (s.alarms & DAHDI_ALARM_RECOVER)
10205 strcat(alarms, "REC/");
10206 if (s.alarms & DAHDI_ALARM_NOTOPEN)
10207 strcat(alarms, "NOP/");
10208 if (!strlen(alarms))
10209 strcat(alarms, "UUU/");
10210 if (strlen(alarms)) {
10211 /* Strip trailing / */
10212 alarms[strlen(alarms) - 1] = '\0';
10214 } else {
10215 if (s.numchans)
10216 strcpy(alarms, "OK");
10217 else
10218 strcpy(alarms, "UNCONFIGURED");
10221 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10223 close(ctl);
10225 return RESULT_SUCCESS;
10226 #undef FORMAT
10227 #undef FORMAT2
10230 static char show_channels_usage[] =
10231 "Usage: dahdi show channels\n"
10232 " Shows a list of available channels\n";
10234 static char show_channel_usage[] =
10235 "Usage: dahdi show channel <chan num>\n"
10236 " Detailed information about a given channel\n";
10238 static char dahdi_show_status_usage[] =
10239 "Usage: dahdi show status\n"
10240 " Shows a list of DAHDI cards with status\n";
10242 static char destroy_channel_usage[] =
10243 "Usage: dahdi destroy channel <chan num>\n"
10244 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
10246 static char dahdi_restart_usage[] =
10247 "Usage: dahdi restart\n"
10248 " Restarts the DAHDI channels: destroys them all and then\n"
10249 " re-reads them from chan_dahdi.conf.\n"
10250 " Note that this will STOP any running CALL on DAHDI channels.\n"
10253 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
10254 { "zap", "show", "cadences", NULL },
10255 handle_dahdi_show_cadences, NULL,
10256 NULL };
10258 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
10259 { "zap", "show", "channels", NULL },
10260 dahdi_show_channels, NULL,
10261 NULL };
10263 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
10264 { "zap", "show", "channel", NULL },
10265 dahdi_show_channel, NULL,
10266 NULL };
10268 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
10269 { "zap", "destroy", "channel", NULL },
10270 dahdi_destroy_channel, NULL,
10271 NULL };
10273 static struct ast_cli_entry cli_zap_restart_deprecated = {
10274 { "zap", "restart", NULL },
10275 dahdi_restart_cmd, NULL,
10276 NULL };
10278 static struct ast_cli_entry cli_zap_show_status_deprecated = {
10279 { "zap", "show", "status", NULL },
10280 dahdi_show_status, NULL,
10281 NULL };
10283 static struct ast_cli_entry dahdi_cli[] = {
10284 { { "dahdi", "show", "cadences", NULL },
10285 handle_dahdi_show_cadences, "List cadences",
10286 dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
10288 { { "dahdi", "show", "channels", NULL},
10289 dahdi_show_channels, "Show active DAHDI channels",
10290 show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
10292 { { "dahdi", "show", "channel", NULL},
10293 dahdi_show_channel, "Show information on a channel",
10294 show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
10296 { { "dahdi", "destroy", "channel", NULL},
10297 dahdi_destroy_channel, "Destroy a channel",
10298 destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
10300 { { "dahdi", "restart", NULL},
10301 dahdi_restart_cmd, "Fully restart DAHDI channels",
10302 dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
10304 { { "dahdi", "show", "status", NULL},
10305 dahdi_show_status, "Show all DAHDI cards status",
10306 dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
10309 #define TRANSFER 0
10310 #define HANGUP 1
10312 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
10314 if (p) {
10315 switch (mode) {
10316 case TRANSFER:
10317 p->fake_event = DAHDI_EVENT_WINKFLASH;
10318 break;
10319 case HANGUP:
10320 p->fake_event = DAHDI_EVENT_ONHOOK;
10321 break;
10322 default:
10323 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
10326 return 0;
10328 static struct dahdi_pvt *find_channel(int channel)
10330 struct dahdi_pvt *p = iflist;
10331 while (p) {
10332 if (p->channel == channel) {
10333 break;
10335 p = p->next;
10337 return p;
10340 static int action_dahdidndon(struct mansession *s, const struct message *m)
10342 struct dahdi_pvt *p = NULL;
10343 const char *channel = astman_get_header(m, "DAHDIChannel");
10345 if (ast_strlen_zero(channel)) {
10346 astman_send_error(s, m, "No channel specified");
10347 return 0;
10349 p = find_channel(atoi(channel));
10350 if (!p) {
10351 astman_send_error(s, m, "No such channel");
10352 return 0;
10354 p->dnd = 1;
10355 astman_send_ack(s, m, "DND Enabled");
10356 return 0;
10359 static int action_dahdidndoff(struct mansession *s, const struct message *m)
10361 struct dahdi_pvt *p = NULL;
10362 const char *channel = astman_get_header(m, "DAHDIChannel");
10364 if (ast_strlen_zero(channel)) {
10365 astman_send_error(s, m, "No channel specified");
10366 return 0;
10368 p = find_channel(atoi(channel));
10369 if (!p) {
10370 astman_send_error(s, m, "No such channel");
10371 return 0;
10373 p->dnd = 0;
10374 astman_send_ack(s, m, "DND Disabled");
10375 return 0;
10378 static int action_transfer(struct mansession *s, const struct message *m)
10380 struct dahdi_pvt *p = NULL;
10381 const char *channel = astman_get_header(m, "DAHDIChannel");
10383 if (ast_strlen_zero(channel)) {
10384 astman_send_error(s, m, "No channel specified");
10385 return 0;
10387 p = find_channel(atoi(channel));
10388 if (!p) {
10389 astman_send_error(s, m, "No such channel");
10390 return 0;
10392 dahdi_fake_event(p,TRANSFER);
10393 astman_send_ack(s, m, "DAHDITransfer");
10394 return 0;
10397 static int action_transferhangup(struct mansession *s, const struct message *m)
10399 struct dahdi_pvt *p = NULL;
10400 const char *channel = astman_get_header(m, "DAHDIChannel");
10402 if (ast_strlen_zero(channel)) {
10403 astman_send_error(s, m, "No channel specified");
10404 return 0;
10406 p = find_channel(atoi(channel));
10407 if (!p) {
10408 astman_send_error(s, m, "No such channel");
10409 return 0;
10411 dahdi_fake_event(p,HANGUP);
10412 astman_send_ack(s, m, "DAHDIHangup");
10413 return 0;
10416 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
10418 struct dahdi_pvt *p = NULL;
10419 const char *channel = astman_get_header(m, "DAHDIChannel");
10420 const char *number = astman_get_header(m, "Number");
10421 int i;
10423 if (ast_strlen_zero(channel)) {
10424 astman_send_error(s, m, "No channel specified");
10425 return 0;
10427 if (ast_strlen_zero(number)) {
10428 astman_send_error(s, m, "No number specified");
10429 return 0;
10431 p = find_channel(atoi(channel));
10432 if (!p) {
10433 astman_send_error(s, m, "No such channel");
10434 return 0;
10436 if (!p->owner) {
10437 astman_send_error(s, m, "Channel does not have it's owner");
10438 return 0;
10440 for (i = 0; i < strlen(number); i++) {
10441 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
10442 dahdi_queue_frame(p, &f, NULL);
10444 astman_send_ack(s, m, "DAHDIDialOffhook");
10445 return 0;
10448 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
10450 struct dahdi_pvt *tmp = NULL;
10451 const char *id = astman_get_header(m, "ActionID");
10452 char idText[256] = "";
10454 astman_send_ack(s, m, "DAHDI channel status will follow");
10455 if (!ast_strlen_zero(id))
10456 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
10458 ast_mutex_lock(&iflock);
10460 tmp = iflist;
10461 while (tmp) {
10462 if (tmp->channel > 0) {
10463 int alarm = get_alarms(tmp);
10464 astman_append(s,
10465 "Event: DAHDIShowChannels\r\n"
10466 "Channel: %d\r\n"
10467 "Signalling: %s\r\n"
10468 "Context: %s\r\n"
10469 "DND: %s\r\n"
10470 "Alarm: %s\r\n"
10471 "%s"
10472 "\r\n",
10473 tmp->channel, sig2str(tmp->sig), tmp->context,
10474 tmp->dnd ? "Enabled" : "Disabled",
10475 alarm2str(alarm), idText);
10478 tmp = tmp->next;
10481 ast_mutex_unlock(&iflock);
10483 astman_append(s,
10484 "Event: DAHDIShowChannelsComplete\r\n"
10485 "%s"
10486 "\r\n",
10487 idText);
10488 return 0;
10491 static int __unload_module(void)
10493 int x;
10494 struct dahdi_pvt *p, *pl;
10496 #ifdef HAVE_PRI
10497 int i;
10498 for (i = 0; i < NUM_SPANS; i++) {
10499 if (pris[i].master != AST_PTHREADT_NULL)
10500 pthread_cancel(pris[i].master);
10502 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
10503 ast_unregister_application(dahdi_send_keypad_facility_app);
10504 #endif
10505 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
10506 ast_manager_unregister( "DAHDIDialOffhook" );
10507 ast_manager_unregister( "DAHDIHangup" );
10508 ast_manager_unregister( "DAHDITransfer" );
10509 ast_manager_unregister( "DAHDIDNDoff" );
10510 ast_manager_unregister( "DAHDIDNDon" );
10511 ast_manager_unregister("DAHDIShowChannels");
10512 ast_manager_unregister("DAHDIRestart");
10513 ast_channel_unregister(&dahdi_tech);
10514 ast_mutex_lock(&iflock);
10515 /* Hangup all interfaces if they have an owner */
10516 p = iflist;
10517 while (p) {
10518 if (p->owner)
10519 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
10520 p = p->next;
10522 ast_mutex_unlock(&iflock);
10523 ast_mutex_lock(&monlock);
10524 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10525 pthread_cancel(monitor_thread);
10526 pthread_kill(monitor_thread, SIGURG);
10527 pthread_join(monitor_thread, NULL);
10529 monitor_thread = AST_PTHREADT_STOP;
10530 ast_mutex_unlock(&monlock);
10532 ast_mutex_lock(&iflock);
10533 /* Destroy all the interfaces and free their memory */
10534 p = iflist;
10535 while (p) {
10536 /* Free any callerid */
10537 if (p->cidspill)
10538 free(p->cidspill);
10539 /* Close the DAHDI thingy */
10540 if (p->subs[SUB_REAL].dfd > -1)
10541 dahdi_close(p->subs[SUB_REAL].dfd);
10542 pl = p;
10543 p = p->next;
10544 x = pl->channel;
10545 /* Free associated memory */
10546 if (pl)
10547 destroy_dahdi_pvt(&pl);
10548 ast_verbose(VERBOSE_PREFIX_3 "Unregistered channel %d\n", x);
10550 iflist = NULL;
10551 ifcount = 0;
10552 ast_mutex_unlock(&iflock);
10553 #ifdef HAVE_PRI
10554 for (i = 0; i < NUM_SPANS; i++) {
10555 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
10556 pthread_join(pris[i].master, NULL);
10557 dahdi_close(pris[i].fds[i]);
10559 #endif
10560 return 0;
10563 static int unload_module(void)
10565 #ifdef HAVE_PRI
10566 int y;
10567 for (y = 0; y < NUM_SPANS; y++)
10568 ast_mutex_destroy(&pris[y].lock);
10569 #endif
10570 return __unload_module();
10573 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
10575 char *c, *chan;
10576 int x, start, finish;
10577 struct dahdi_pvt *tmp;
10578 #ifdef HAVE_PRI
10579 struct dahdi_pri *pri;
10580 int trunkgroup, y;
10581 #endif
10583 if ((reload == 0) && (conf->chan.sig < 0)) {
10584 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
10585 return -1;
10588 c = ast_strdupa(value);
10590 #ifdef HAVE_PRI
10591 pri = NULL;
10592 if (iscrv) {
10593 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
10594 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
10595 return -1;
10597 if (trunkgroup < 1) {
10598 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
10599 return -1;
10601 c += y;
10602 for (y = 0; y < NUM_SPANS; y++) {
10603 if (pris[y].trunkgroup == trunkgroup) {
10604 pri = pris + y;
10605 break;
10608 if (!pri) {
10609 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
10610 return -1;
10613 #endif
10615 while ((chan = strsep(&c, ","))) {
10616 if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
10617 /* Range */
10618 } else if (sscanf(chan, "%d", &start)) {
10619 /* Just one */
10620 finish = start;
10621 } else if (!strcasecmp(chan, "pseudo")) {
10622 finish = start = CHAN_PSEUDO;
10623 if (found_pseudo)
10624 *found_pseudo = 1;
10625 } else {
10626 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
10627 return -1;
10629 if (finish < start) {
10630 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
10631 x = finish;
10632 finish = start;
10633 start = x;
10636 for (x = start; x <= finish; x++) {
10637 #ifdef HAVE_PRI
10638 tmp = mkintf(x, conf, pri, reload);
10639 #else
10640 tmp = mkintf(x, conf, NULL, reload);
10641 #endif
10643 if (tmp) {
10644 if (option_verbose > 2) {
10645 #ifdef HAVE_PRI
10646 if (pri)
10647 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
10648 else
10649 #endif
10650 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
10652 } else {
10653 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
10654 (reload == 1) ? "reconfigure" : "register", value);
10655 return -1;
10660 return 0;
10663 /** The length of the parameters list of 'dahdichan'.
10664 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
10665 #define MAX_CHANLIST_LEN 80
10666 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
10668 struct dahdi_pvt *tmp;
10669 char *ringc; /* temporary string for parsing the dring number. */
10670 int y;
10671 int found_pseudo = 0;
10672 char dahdichan[MAX_CHANLIST_LEN] = {};
10674 for (; v; v = v->next) {
10675 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
10676 continue;
10678 /* Create the interface list */
10679 if (!strcasecmp(v->name, "channel")
10680 #ifdef HAVE_PRI
10681 || !strcasecmp(v->name, "crv")
10682 #endif
10684 int iscrv;
10685 if (skipchannels)
10686 continue;
10687 iscrv = !strcasecmp(v->name, "crv");
10688 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
10689 return -1;
10690 } else if (!strcasecmp(v->name, "dahdichan")) {
10691 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
10692 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
10693 if (ast_true(v->value))
10694 confp->chan.usedistinctiveringdetection = 1;
10695 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
10696 if (ast_true(v->value))
10697 distinctiveringaftercid = 1;
10698 } else if (!strcasecmp(v->name, "dring1context")) {
10699 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
10700 } else if (!strcasecmp(v->name, "dring2context")) {
10701 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
10702 } else if (!strcasecmp(v->name, "dring3context")) {
10703 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
10704 } else if (!strcasecmp(v->name, "dring1")) {
10705 ringc = v->value;
10706 sscanf(ringc, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
10707 } else if (!strcasecmp(v->name, "dring2")) {
10708 ringc = v->value;
10709 sscanf(ringc, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
10710 } else if (!strcasecmp(v->name, "dring3")) {
10711 ringc = v->value;
10712 sscanf(ringc, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
10713 } else if (!strcasecmp(v->name, "usecallerid")) {
10714 confp->chan.use_callerid = ast_true(v->value);
10715 } else if (!strcasecmp(v->name, "cidsignalling")) {
10716 if (!strcasecmp(v->value, "bell"))
10717 confp->chan.cid_signalling = CID_SIG_BELL;
10718 else if (!strcasecmp(v->value, "v23"))
10719 confp->chan.cid_signalling = CID_SIG_V23;
10720 else if (!strcasecmp(v->value, "dtmf"))
10721 confp->chan.cid_signalling = CID_SIG_DTMF;
10722 else if (!strcasecmp(v->value, "smdi"))
10723 confp->chan.cid_signalling = CID_SIG_SMDI;
10724 else if (!strcasecmp(v->value, "v23_jp"))
10725 confp->chan.cid_signalling = CID_SIG_V23_JP;
10726 else if (ast_true(v->value))
10727 confp->chan.cid_signalling = CID_SIG_BELL;
10728 } else if (!strcasecmp(v->name, "cidstart")) {
10729 if (!strcasecmp(v->value, "ring"))
10730 confp->chan.cid_start = CID_START_RING;
10731 else if (!strcasecmp(v->value, "polarity"))
10732 confp->chan.cid_start = CID_START_POLARITY;
10733 else if (ast_true(v->value))
10734 confp->chan.cid_start = CID_START_RING;
10735 } else if (!strcasecmp(v->name, "threewaycalling")) {
10736 confp->chan.threewaycalling = ast_true(v->value);
10737 } else if (!strcasecmp(v->name, "cancallforward")) {
10738 confp->chan.cancallforward = ast_true(v->value);
10739 } else if (!strcasecmp(v->name, "relaxdtmf")) {
10740 if (ast_true(v->value))
10741 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
10742 else
10743 confp->chan.dtmfrelax = 0;
10744 } else if (!strcasecmp(v->name, "mailbox")) {
10745 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
10746 } else if (!strcasecmp(v->name, "hasvoicemail")) {
10747 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
10748 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
10750 } else if (!strcasecmp(v->name, "adsi")) {
10751 confp->chan.adsi = ast_true(v->value);
10752 } else if (!strcasecmp(v->name, "usesmdi")) {
10753 confp->chan.use_smdi = ast_true(v->value);
10754 } else if (!strcasecmp(v->name, "smdiport")) {
10755 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
10756 } else if (!strcasecmp(v->name, "transfer")) {
10757 confp->chan.transfer = ast_true(v->value);
10758 } else if (!strcasecmp(v->name, "canpark")) {
10759 confp->chan.canpark = ast_true(v->value);
10760 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
10761 confp->chan.echocanbridged = ast_true(v->value);
10762 } else if (!strcasecmp(v->name, "busydetect")) {
10763 confp->chan.busydetect = ast_true(v->value);
10764 } else if (!strcasecmp(v->name, "busycount")) {
10765 confp->chan.busycount = atoi(v->value);
10766 } else if (!strcasecmp(v->name, "busypattern")) {
10767 if (sscanf(v->value, "%d,%d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
10768 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength\n");
10770 } else if (!strcasecmp(v->name, "callprogress")) {
10771 if (ast_true(v->value))
10772 confp->chan.callprogress |= 1;
10773 else
10774 confp->chan.callprogress &= ~1;
10775 } else if (!strcasecmp(v->name, "faxdetect")) {
10776 if (!strcasecmp(v->value, "incoming")) {
10777 confp->chan.callprogress |= 4;
10778 confp->chan.callprogress &= ~2;
10779 } else if (!strcasecmp(v->value, "outgoing")) {
10780 confp->chan.callprogress &= ~4;
10781 confp->chan.callprogress |= 2;
10782 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
10783 confp->chan.callprogress |= 6;
10784 else
10785 confp->chan.callprogress &= ~6;
10786 } else if (!strcasecmp(v->name, "echocancel")) {
10787 if (!ast_strlen_zero(v->value)) {
10788 y = atoi(v->value);
10789 } else
10790 y = 0;
10791 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
10792 confp->chan.echocancel = y;
10793 else {
10794 confp->chan.echocancel = ast_true(v->value);
10795 if (confp->chan.echocancel)
10796 confp->chan.echocancel=128;
10798 } else if (!strcasecmp(v->name, "echotraining")) {
10799 if (sscanf(v->value, "%d", &y) == 1) {
10800 if ((y < 10) || (y > 4000)) {
10801 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);
10802 } else {
10803 confp->chan.echotraining = y;
10805 } else if (ast_true(v->value)) {
10806 confp->chan.echotraining = 400;
10807 } else
10808 confp->chan.echotraining = 0;
10809 } else if (!strcasecmp(v->name, "hidecallerid")) {
10810 confp->chan.hidecallerid = ast_true(v->value);
10811 } else if (!strcasecmp(v->name, "hidecalleridname")) {
10812 confp->chan.hidecalleridname = ast_true(v->value);
10813 } else if (!strcasecmp(v->name, "pulsedial")) {
10814 confp->chan.pulse = ast_true(v->value);
10815 } else if (!strcasecmp(v->name, "callreturn")) {
10816 confp->chan.callreturn = ast_true(v->value);
10817 } else if (!strcasecmp(v->name, "callwaiting")) {
10818 confp->chan.callwaiting = ast_true(v->value);
10819 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
10820 confp->chan.callwaitingcallerid = ast_true(v->value);
10821 } else if (!strcasecmp(v->name, "context")) {
10822 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
10823 } else if (!strcasecmp(v->name, "language")) {
10824 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
10825 } else if (!strcasecmp(v->name, "progzone")) {
10826 ast_copy_string(progzone, v->value, sizeof(progzone));
10827 } else if (!strcasecmp(v->name, "mohinterpret")
10828 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
10829 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
10830 } else if (!strcasecmp(v->name, "mohsuggest")) {
10831 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
10832 } else if (!strcasecmp(v->name, "stripmsd")) {
10833 confp->chan.stripmsd = atoi(v->value);
10834 } else if (!strcasecmp(v->name, "jitterbuffers")) {
10835 numbufs = atoi(v->value);
10836 } else if (!strcasecmp(v->name, "group")) {
10837 confp->chan.group = ast_get_group(v->value);
10838 } else if (!strcasecmp(v->name, "callgroup")) {
10839 confp->chan.callgroup = ast_get_group(v->value);
10840 } else if (!strcasecmp(v->name, "pickupgroup")) {
10841 confp->chan.pickupgroup = ast_get_group(v->value);
10842 } else if (!strcasecmp(v->name, "immediate")) {
10843 confp->chan.immediate = ast_true(v->value);
10844 } else if (!strcasecmp(v->name, "transfertobusy")) {
10845 confp->chan.transfertobusy = ast_true(v->value);
10846 } else if (!strcasecmp(v->name, "rxgain")) {
10847 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
10848 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
10850 } else if (!strcasecmp(v->name, "txgain")) {
10851 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
10852 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
10854 } else if (!strcasecmp(v->name, "tonezone")) {
10855 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
10856 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
10858 } else if (!strcasecmp(v->name, "callerid")) {
10859 if (!strcasecmp(v->value, "asreceived")) {
10860 confp->chan.cid_num[0] = '\0';
10861 confp->chan.cid_name[0] = '\0';
10862 } else {
10863 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
10865 } else if (!strcasecmp(v->name, "fullname")) {
10866 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
10867 } else if (!strcasecmp(v->name, "cid_number")) {
10868 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
10869 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
10870 confp->chan.dahditrcallerid = ast_true(v->value);
10871 } else if (!strcasecmp(v->name, "restrictcid")) {
10872 confp->chan.restrictcid = ast_true(v->value);
10873 } else if (!strcasecmp(v->name, "usecallingpres")) {
10874 confp->chan.use_callingpres = ast_true(v->value);
10875 } else if (!strcasecmp(v->name, "accountcode")) {
10876 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
10877 } else if (!strcasecmp(v->name, "amaflags")) {
10878 y = ast_cdr_amaflags2int(v->value);
10879 if (y < 0)
10880 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
10881 else
10882 confp->chan.amaflags = y;
10883 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
10884 confp->chan.polarityonanswerdelay = atoi(v->value);
10885 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
10886 confp->chan.answeronpolarityswitch = ast_true(v->value);
10887 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
10888 confp->chan.hanguponpolarityswitch = ast_true(v->value);
10889 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
10890 confp->chan.sendcalleridafter = atoi(v->value);
10891 } else if (!reload){
10892 if (!strcasecmp(v->name, "signalling")) {
10893 confp->chan.outsigmod = -1;
10894 if (!strcasecmp(v->value, "em")) {
10895 confp->chan.sig = SIG_EM;
10896 } else if (!strcasecmp(v->value, "em_e1")) {
10897 confp->chan.sig = SIG_EM_E1;
10898 } else if (!strcasecmp(v->value, "em_w")) {
10899 confp->chan.sig = SIG_EMWINK;
10900 confp->chan.radio = 0;
10901 } else if (!strcasecmp(v->value, "fxs_ls")) {
10902 confp->chan.sig = SIG_FXSLS;
10903 confp->chan.radio = 0;
10904 } else if (!strcasecmp(v->value, "fxs_gs")) {
10905 confp->chan.sig = SIG_FXSGS;
10906 confp->chan.radio = 0;
10907 } else if (!strcasecmp(v->value, "fxs_ks")) {
10908 confp->chan.sig = SIG_FXSKS;
10909 confp->chan.radio = 0;
10910 } else if (!strcasecmp(v->value, "fxo_ls")) {
10911 confp->chan.sig = SIG_FXOLS;
10912 confp->chan.radio = 0;
10913 } else if (!strcasecmp(v->value, "fxo_gs")) {
10914 confp->chan.sig = SIG_FXOGS;
10915 confp->chan.radio = 0;
10916 } else if (!strcasecmp(v->value, "fxo_ks")) {
10917 confp->chan.sig = SIG_FXOKS;
10918 confp->chan.radio = 0;
10919 } else if (!strcasecmp(v->value, "fxs_rx")) {
10920 confp->chan.sig = SIG_FXSKS;
10921 confp->chan.radio = 1;
10922 } else if (!strcasecmp(v->value, "fxo_rx")) {
10923 confp->chan.sig = SIG_FXOLS;
10924 confp->chan.radio = 1;
10925 } else if (!strcasecmp(v->value, "fxs_tx")) {
10926 confp->chan.sig = SIG_FXSLS;
10927 confp->chan.radio = 1;
10928 } else if (!strcasecmp(v->value, "fxo_tx")) {
10929 confp->chan.sig = SIG_FXOGS;
10930 confp->chan.radio = 1;
10931 } else if (!strcasecmp(v->value, "em_rx")) {
10932 confp->chan.sig = SIG_EM;
10933 confp->chan.radio = 1;
10934 } else if (!strcasecmp(v->value, "em_tx")) {
10935 confp->chan.sig = SIG_EM;
10936 confp->chan.radio = 1;
10937 } else if (!strcasecmp(v->value, "em_rxtx")) {
10938 confp->chan.sig = SIG_EM;
10939 confp->chan.radio = 2;
10940 } else if (!strcasecmp(v->value, "em_txrx")) {
10941 confp->chan.sig = SIG_EM;
10942 confp->chan.radio = 2;
10943 } else if (!strcasecmp(v->value, "sf")) {
10944 confp->chan.sig = SIG_SF;
10945 confp->chan.radio = 0;
10946 } else if (!strcasecmp(v->value, "sf_w")) {
10947 confp->chan.sig = SIG_SFWINK;
10948 confp->chan.radio = 0;
10949 } else if (!strcasecmp(v->value, "sf_featd")) {
10950 confp->chan.sig = SIG_FEATD;
10951 confp->chan.radio = 0;
10952 } else if (!strcasecmp(v->value, "sf_featdmf")) {
10953 confp->chan.sig = SIG_FEATDMF;
10954 confp->chan.radio = 0;
10955 } else if (!strcasecmp(v->value, "sf_featb")) {
10956 confp->chan.sig = SIG_SF_FEATB;
10957 confp->chan.radio = 0;
10958 } else if (!strcasecmp(v->value, "sf")) {
10959 confp->chan.sig = SIG_SF;
10960 confp->chan.radio = 0;
10961 } else if (!strcasecmp(v->value, "sf_rx")) {
10962 confp->chan.sig = SIG_SF;
10963 confp->chan.radio = 1;
10964 } else if (!strcasecmp(v->value, "sf_tx")) {
10965 confp->chan.sig = SIG_SF;
10966 confp->chan.radio = 1;
10967 } else if (!strcasecmp(v->value, "sf_rxtx")) {
10968 confp->chan.sig = SIG_SF;
10969 confp->chan.radio = 2;
10970 } else if (!strcasecmp(v->value, "sf_txrx")) {
10971 confp->chan.sig = SIG_SF;
10972 confp->chan.radio = 2;
10973 } else if (!strcasecmp(v->value, "featd")) {
10974 confp->chan.sig = SIG_FEATD;
10975 confp->chan.radio = 0;
10976 } else if (!strcasecmp(v->value, "featdmf")) {
10977 confp->chan.sig = SIG_FEATDMF;
10978 confp->chan.radio = 0;
10979 } else if (!strcasecmp(v->value, "featdmf_ta")) {
10980 confp->chan.sig = SIG_FEATDMF_TA;
10981 confp->chan.radio = 0;
10982 } else if (!strcasecmp(v->value, "e911")) {
10983 confp->chan.sig = SIG_E911;
10984 confp->chan.radio = 0;
10985 } else if (!strcasecmp(v->value, "fgccama")) {
10986 confp->chan.sig = SIG_FGC_CAMA;
10987 confp->chan.radio = 0;
10988 } else if (!strcasecmp(v->value, "fgccamamf")) {
10989 confp->chan.sig = SIG_FGC_CAMAMF;
10990 confp->chan.radio = 0;
10991 } else if (!strcasecmp(v->value, "featb")) {
10992 confp->chan.sig = SIG_FEATB;
10993 confp->chan.radio = 0;
10994 #ifdef HAVE_PRI
10995 } else if (!strcasecmp(v->value, "pri_net")) {
10996 confp->chan.radio = 0;
10997 confp->chan.sig = SIG_PRI;
10998 confp->pri.nodetype = PRI_NETWORK;
10999 } else if (!strcasecmp(v->value, "pri_cpe")) {
11000 confp->chan.sig = SIG_PRI;
11001 confp->chan.radio = 0;
11002 confp->pri.nodetype = PRI_CPE;
11003 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
11004 confp->chan.sig = SIG_GR303FXOKS;
11005 confp->chan.radio = 0;
11006 confp->pri.nodetype = PRI_NETWORK;
11007 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
11008 confp->chan.sig = SIG_GR303FXSKS;
11009 confp->chan.radio = 0;
11010 confp->pri.nodetype = PRI_CPE;
11011 #endif
11012 } else {
11013 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11015 } else if (!strcasecmp(v->name, "outsignalling")) {
11016 if (!strcasecmp(v->value, "em")) {
11017 confp->chan.outsigmod = SIG_EM;
11018 } else if (!strcasecmp(v->value, "em_e1")) {
11019 confp->chan.outsigmod = SIG_EM_E1;
11020 } else if (!strcasecmp(v->value, "em_w")) {
11021 confp->chan.outsigmod = SIG_EMWINK;
11022 } else if (!strcasecmp(v->value, "sf")) {
11023 confp->chan.outsigmod = SIG_SF;
11024 } else if (!strcasecmp(v->value, "sf_w")) {
11025 confp->chan.outsigmod = SIG_SFWINK;
11026 } else if (!strcasecmp(v->value, "sf_featd")) {
11027 confp->chan.outsigmod = SIG_FEATD;
11028 } else if (!strcasecmp(v->value, "sf_featdmf")) {
11029 confp->chan.outsigmod = SIG_FEATDMF;
11030 } else if (!strcasecmp(v->value, "sf_featb")) {
11031 confp->chan.outsigmod = SIG_SF_FEATB;
11032 } else if (!strcasecmp(v->value, "sf")) {
11033 confp->chan.outsigmod = SIG_SF;
11034 } else if (!strcasecmp(v->value, "featd")) {
11035 confp->chan.outsigmod = SIG_FEATD;
11036 } else if (!strcasecmp(v->value, "featdmf")) {
11037 confp->chan.outsigmod = SIG_FEATDMF;
11038 } else if (!strcasecmp(v->value, "featdmf_ta")) {
11039 confp->chan.outsigmod = SIG_FEATDMF_TA;
11040 } else if (!strcasecmp(v->value, "e911")) {
11041 confp->chan.outsigmod = SIG_E911;
11042 } else if (!strcasecmp(v->value, "fgccama")) {
11043 confp->chan.outsigmod = SIG_FGC_CAMA;
11044 } else if (!strcasecmp(v->value, "fgccamamf")) {
11045 confp->chan.outsigmod = SIG_FGC_CAMAMF;
11046 } else if (!strcasecmp(v->value, "featb")) {
11047 confp->chan.outsigmod = SIG_FEATB;
11048 } else {
11049 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11051 #ifdef HAVE_PRI
11052 } else if (!strcasecmp(v->name, "pridialplan")) {
11053 if (!strcasecmp(v->value, "national")) {
11054 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
11055 } else if (!strcasecmp(v->value, "unknown")) {
11056 confp->pri.dialplan = PRI_UNKNOWN + 1;
11057 } else if (!strcasecmp(v->value, "private")) {
11058 confp->pri.dialplan = PRI_PRIVATE + 1;
11059 } else if (!strcasecmp(v->value, "international")) {
11060 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
11061 } else if (!strcasecmp(v->value, "local")) {
11062 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
11063 } else if (!strcasecmp(v->value, "dynamic")) {
11064 confp->pri.dialplan = -1;
11065 } else {
11066 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11068 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
11069 if (!strcasecmp(v->value, "national")) {
11070 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
11071 } else if (!strcasecmp(v->value, "unknown")) {
11072 confp->pri.localdialplan = PRI_UNKNOWN + 1;
11073 } else if (!strcasecmp(v->value, "private")) {
11074 confp->pri.localdialplan = PRI_PRIVATE + 1;
11075 } else if (!strcasecmp(v->value, "international")) {
11076 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
11077 } else if (!strcasecmp(v->value, "local")) {
11078 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
11079 } else if (!strcasecmp(v->value, "dynamic")) {
11080 confp->pri.localdialplan = -1;
11081 } else {
11082 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11084 } else if (!strcasecmp(v->name, "switchtype")) {
11085 if (!strcasecmp(v->value, "national"))
11086 confp->pri.switchtype = PRI_SWITCH_NI2;
11087 else if (!strcasecmp(v->value, "ni1"))
11088 confp->pri.switchtype = PRI_SWITCH_NI1;
11089 else if (!strcasecmp(v->value, "dms100"))
11090 confp->pri.switchtype = PRI_SWITCH_DMS100;
11091 else if (!strcasecmp(v->value, "4ess"))
11092 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
11093 else if (!strcasecmp(v->value, "5ess"))
11094 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
11095 else if (!strcasecmp(v->value, "euroisdn"))
11096 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
11097 else if (!strcasecmp(v->value, "qsig"))
11098 confp->pri.switchtype = PRI_SWITCH_QSIG;
11099 else {
11100 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
11101 return -1;
11103 } else if (!strcasecmp(v->name, "nsf")) {
11104 if (!strcasecmp(v->value, "sdn"))
11105 confp->pri.nsf = PRI_NSF_SDN;
11106 else if (!strcasecmp(v->value, "megacom"))
11107 confp->pri.nsf = PRI_NSF_MEGACOM;
11108 else if (!strcasecmp(v->value, "tollfreemegacom"))
11109 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
11110 else if (!strcasecmp(v->value, "accunet"))
11111 confp->pri.nsf = PRI_NSF_ACCUNET;
11112 else if (!strcasecmp(v->value, "none"))
11113 confp->pri.nsf = PRI_NSF_NONE;
11114 else {
11115 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
11116 confp->pri.nsf = PRI_NSF_NONE;
11118 } else if (!strcasecmp(v->name, "priindication")) {
11119 if (!strcasecmp(v->value, "outofband"))
11120 confp->chan.priindication_oob = 1;
11121 else if (!strcasecmp(v->value, "inband"))
11122 confp->chan.priindication_oob = 0;
11123 else
11124 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11125 v->value, v->lineno);
11126 } else if (!strcasecmp(v->name, "priexclusive")) {
11127 confp->chan.priexclusive = ast_true(v->value);
11128 } else if (!strcasecmp(v->name, "internationalprefix")) {
11129 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
11130 } else if (!strcasecmp(v->name, "nationalprefix")) {
11131 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
11132 } else if (!strcasecmp(v->name, "localprefix")) {
11133 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
11134 } else if (!strcasecmp(v->name, "privateprefix")) {
11135 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
11136 } else if (!strcasecmp(v->name, "unknownprefix")) {
11137 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
11138 } else if (!strcasecmp(v->name, "resetinterval")) {
11139 if (!strcasecmp(v->value, "never"))
11140 confp->pri.resetinterval = -1;
11141 else if (atoi(v->value) >= 60)
11142 confp->pri.resetinterval = atoi(v->value);
11143 else
11144 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11145 v->value, v->lineno);
11146 } else if (!strcasecmp(v->name, "minunused")) {
11147 confp->pri.minunused = atoi(v->value);
11148 } else if (!strcasecmp(v->name, "minidle")) {
11149 confp->pri.minidle = atoi(v->value);
11150 } else if (!strcasecmp(v->name, "idleext")) {
11151 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
11152 } else if (!strcasecmp(v->name, "idledial")) {
11153 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
11154 } else if (!strcasecmp(v->name, "overlapdial")) {
11155 confp->pri.overlapdial = ast_true(v->value);
11156 } else if (!strcasecmp(v->name, "pritimer")) {
11157 #ifdef PRI_GETSET_TIMERS
11158 char *timerc, *c;
11159 int timer, timeridx;
11160 c = v->value;
11161 timerc = strsep(&c, ",");
11162 if (timerc) {
11163 timer = atoi(c);
11164 if (!timer)
11165 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc);
11166 else {
11167 if ((timeridx = pri_timer2idx(timerc)) >= 0)
11168 pritimers[timeridx] = timer;
11169 else
11170 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc);
11172 } else
11173 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value);
11175 } else if (!strcasecmp(v->name, "facilityenable")) {
11176 confp->pri.facilityenable = ast_true(v->value);
11177 #endif /* PRI_GETSET_TIMERS */
11178 #endif /* HAVE_PRI */
11179 } else if (!strcasecmp(v->name, "cadence")) {
11180 /* setup to scan our argument */
11181 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11182 int i;
11183 struct dahdi_ring_cadence new_cadence;
11184 int cid_location = -1;
11185 int firstcadencepos = 0;
11186 char original_args[80];
11187 int cadence_is_ok = 1;
11189 ast_copy_string(original_args, v->value, sizeof(original_args));
11190 /* 16 cadences allowed (8 pairs) */
11191 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]);
11193 /* Cadence must be even (on/off) */
11194 if (element_count % 2 == 1) {
11195 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
11196 cadence_is_ok = 0;
11199 /* Ring cadences cannot be negative */
11200 for (i = 0; i < element_count; i++) {
11201 if (c[i] == 0) {
11202 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
11203 cadence_is_ok = 0;
11204 break;
11205 } else if (c[i] < 0) {
11206 if (i % 2 == 1) {
11207 /* Silence duration, negative possibly okay */
11208 if (cid_location == -1) {
11209 cid_location = i;
11210 c[i] *= -1;
11211 } else {
11212 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
11213 cadence_is_ok = 0;
11214 break;
11216 } else {
11217 if (firstcadencepos == 0) {
11218 firstcadencepos = i; /* only recorded to avoid duplicate specification */
11219 /* duration will be passed negative to the DAHDI driver */
11220 } else {
11221 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
11222 cadence_is_ok = 0;
11223 break;
11229 /* Substitute our scanned cadence */
11230 for (i = 0; i < 16; i++) {
11231 new_cadence.ringcadence[i] = c[i];
11234 if (cadence_is_ok) {
11235 /* ---we scanned it without getting annoyed; now some sanity checks--- */
11236 if (element_count < 2) {
11237 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
11238 } else {
11239 if (cid_location == -1) {
11240 /* user didn't say; default to first pause */
11241 cid_location = 1;
11242 } else {
11243 /* convert element_index to cidrings value */
11244 cid_location = (cid_location + 1) / 2;
11246 /* ---we like their cadence; try to install it--- */
11247 if (!user_has_defined_cadences++)
11248 /* this is the first user-defined cadence; clear the default user cadences */
11249 num_cadence = 0;
11250 if ((num_cadence+1) >= NUM_CADENCE_MAX)
11251 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
11252 else {
11253 cadences[num_cadence] = new_cadence;
11254 cidrings[num_cadence++] = cid_location;
11255 if (option_verbose > 2)
11256 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
11260 } else if (!strcasecmp(v->name, "ringtimeout")) {
11261 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
11262 } else if (!strcasecmp(v->name, "prewink")) {
11263 confp->timing.prewinktime = atoi(v->value);
11264 } else if (!strcasecmp(v->name, "preflash")) {
11265 confp->timing.preflashtime = atoi(v->value);
11266 } else if (!strcasecmp(v->name, "wink")) {
11267 confp->timing.winktime = atoi(v->value);
11268 } else if (!strcasecmp(v->name, "flash")) {
11269 confp->timing.flashtime = atoi(v->value);
11270 } else if (!strcasecmp(v->name, "start")) {
11271 confp->timing.starttime = atoi(v->value);
11272 } else if (!strcasecmp(v->name, "rxwink")) {
11273 confp->timing.rxwinktime = atoi(v->value);
11274 } else if (!strcasecmp(v->name, "rxflash")) {
11275 confp->timing.rxflashtime = atoi(v->value);
11276 } else if (!strcasecmp(v->name, "debounce")) {
11277 confp->timing.debouncetime = atoi(v->value);
11278 } else if (!strcasecmp(v->name, "toneduration")) {
11279 int toneduration;
11280 int ctlfd;
11281 int res;
11282 DAHDI_DIAL_PARAMS dps;
11284 #ifdef HAVE_ZAPTEL
11285 ctlfd = open("/dev/zap/ctl", O_RDWR);
11286 #else
11287 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
11288 #endif
11290 if (ctlfd == -1) {
11291 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration\n");
11292 return -1;
11295 toneduration = atoi(v->value);
11296 if (toneduration > -1) {
11297 memset(&dps, 0, sizeof(dps));
11299 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
11300 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
11301 if (res < 0) {
11302 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
11303 return -1;
11306 close(ctlfd);
11307 } else if (!strcasecmp(v->name, "defaultcic")) {
11308 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
11309 } else if (!strcasecmp(v->name, "defaultozz")) {
11310 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
11312 } else if (!skipchannels)
11313 ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
11315 if (dahdichan[0]) {
11316 /* The user has set 'dahdichan' */
11317 /*< \todo pass proper line number instead of 0 */
11318 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
11319 return -1;
11322 /*< \todo why check for the pseudo in the per-channel section.
11323 * Any actual use for manual setup of the pseudo channel? */
11324 if (!found_pseudo && reload == 0) {
11325 /* Make sure pseudo isn't a member of any groups if
11326 we're automatically making it. */
11328 confp->chan.group = 0;
11329 confp->chan.callgroup = 0;
11330 confp->chan.pickupgroup = 0;
11332 tmp = mkintf(CHAN_PSEUDO, confp, NULL, reload);
11334 if (tmp) {
11335 if (option_verbose > 2)
11336 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
11337 } else {
11338 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
11341 return 0;
11344 static int setup_dahdi(int reload)
11346 struct ast_config *cfg;
11347 struct ast_variable *v;
11348 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
11349 int res;
11351 #ifdef HAVE_PRI
11352 char *c;
11353 int spanno;
11354 int i, x;
11355 int logicalspan;
11356 int trunkgroup;
11357 int dchannels[NUM_DCHANS];
11358 #endif
11360 #ifdef HAVE_ZAPTEL
11361 cfg = ast_config_load("zapata.conf");
11362 #else
11363 cfg = ast_config_load(config);
11364 #endif
11365 /* Error if we have no config file... */
11366 if (!cfg) {
11367 ast_log(LOG_ERROR, "Unable to load either config %s or zapata.conf\n", config);
11368 return 0;
11371 /* It's a little silly to lock it, but we mind as well just to be sure */
11372 ast_mutex_lock(&iflock);
11373 #ifdef HAVE_PRI
11374 if (!reload) {
11375 /* Process trunkgroups first */
11376 v = ast_variable_browse(cfg, "trunkgroups");
11377 while (v) {
11378 if (!strcasecmp(v->name, "trunkgroup")) {
11379 trunkgroup = atoi(v->value);
11380 if (trunkgroup > 0) {
11381 if ((c = strchr(v->value, ','))) {
11382 i = 0;
11383 memset(dchannels, 0, sizeof(dchannels));
11384 while (c && (i < NUM_DCHANS)) {
11385 dchannels[i] = atoi(c + 1);
11386 if (dchannels[i] < 0) {
11387 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);
11388 } else
11389 i++;
11390 c = strchr(c + 1, ',');
11392 if (i) {
11393 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
11394 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);
11395 } else if (option_verbose > 1)
11396 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");
11397 } else
11398 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11399 } else
11400 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11401 } else
11402 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
11403 } else if (!strcasecmp(v->name, "spanmap")) {
11404 spanno = atoi(v->value);
11405 if (spanno > 0) {
11406 if ((c = strchr(v->value, ','))) {
11407 trunkgroup = atoi(c + 1);
11408 if (trunkgroup > 0) {
11409 if ((c = strchr(c + 1, ',')))
11410 logicalspan = atoi(c + 1);
11411 else
11412 logicalspan = 0;
11413 if (logicalspan >= 0) {
11414 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
11415 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11416 } else if (option_verbose > 1)
11417 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11418 } else
11419 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);
11420 } else
11421 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
11422 } else
11423 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
11424 } else
11425 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
11426 } else {
11427 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
11429 v = v->next;
11432 #endif
11434 /* Copy the default jb config over global_jbconf */
11435 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
11437 v = ast_variable_browse(cfg, "channels");
11438 res = process_dahdi(&conf, "", v, reload, 0);
11439 ast_mutex_unlock(&iflock);
11440 ast_config_destroy(cfg);
11441 if (res)
11442 return res;
11443 cfg = ast_config_load("users.conf");
11444 if (cfg) {
11445 char *cat;
11446 const char *chans;
11447 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
11448 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
11449 if (!strcasecmp(cat, "general"))
11450 continue;
11451 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
11452 if (!ast_strlen_zero(chans)) {
11453 struct dahdi_chan_conf sect_conf;
11454 memcpy(&sect_conf, &conf, sizeof(sect_conf));
11456 process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
11459 ast_config_destroy(cfg);
11461 #ifdef HAVE_PRI
11462 if (!reload) {
11463 for (x = 0; x < NUM_SPANS; x++) {
11464 if (pris[x].pvts[0]) {
11465 if (start_pri(pris + x)) {
11466 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
11467 return -1;
11468 } else if (option_verbose > 1)
11469 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
11473 #endif
11474 /* And start the monitor for the first time */
11475 restart_monitor();
11476 return 0;
11479 static int load_module(void)
11481 int res;
11483 #ifdef HAVE_PRI
11484 int y,i;
11485 memset(pris, 0, sizeof(pris));
11486 for (y = 0; y < NUM_SPANS; y++) {
11487 ast_mutex_init(&pris[y].lock);
11488 pris[y].offset = -1;
11489 pris[y].master = AST_PTHREADT_NULL;
11490 for (i = 0; i < NUM_DCHANS; i++)
11491 pris[y].fds[i] = -1;
11493 pri_set_error(dahdi_pri_error);
11494 pri_set_message(dahdi_pri_message);
11495 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
11496 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
11497 #endif
11498 res = setup_dahdi(0);
11499 /* Make sure we can register our DAHDI channel type */
11500 if (res)
11501 return AST_MODULE_LOAD_DECLINE;
11502 if (ast_channel_register(&dahdi_tech)) {
11503 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
11504 __unload_module();
11505 return -1;
11507 #ifdef HAVE_PRI
11508 ast_string_field_init(&inuse, 16);
11509 ast_string_field_set(&inuse, name, "GR-303InUse");
11510 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
11511 #endif
11512 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
11514 memset(round_robin, 0, sizeof(round_robin));
11515 ast_manager_register("DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
11516 ast_manager_register("DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
11517 ast_manager_register("DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
11518 ast_manager_register("DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
11519 ast_manager_register("DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
11520 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
11521 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
11523 return res;
11526 static int dahdi_sendtext(struct ast_channel *c, const char *text)
11528 #define END_SILENCE_LEN 400
11529 #define HEADER_MS 50
11530 #define TRAILER_MS 5
11531 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11532 #define ASCII_BYTES_PER_CHAR 80
11534 unsigned char *buf,*mybuf;
11535 struct dahdi_pvt *p = c->tech_pvt;
11536 struct pollfd fds[1];
11537 int size,res,fd,len,x;
11538 int bytes=0;
11539 /* Initial carrier (imaginary) */
11540 float cr = 1.0;
11541 float ci = 0.0;
11542 float scont = 0.0;
11543 int index;
11545 index = dahdi_get_index(c, p, 0);
11546 if (index < 0) {
11547 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
11548 return -1;
11550 if (!text[0]) return(0); /* if nothing to send, dont */
11551 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */
11552 if (p->mate)
11553 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
11554 else
11555 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
11556 if (!buf)
11557 return -1;
11558 mybuf = buf;
11559 if (p->mate) {
11560 int codec = AST_LAW(p);
11561 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
11562 PUT_CLID_MARKMS;
11564 /* Put actual message */
11565 for (x = 0; text[x]; x++) {
11566 PUT_CLID(text[x]);
11568 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
11569 PUT_CLID_MARKMS;
11571 len = bytes;
11572 buf = mybuf;
11573 } else {
11574 len = tdd_generate(p->tdd, buf, text);
11575 if (len < 1) {
11576 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
11577 free(mybuf);
11578 return -1;
11581 memset(buf + len, 0x7f, END_SILENCE_LEN);
11582 len += END_SILENCE_LEN;
11583 fd = p->subs[index].dfd;
11584 while (len) {
11585 if (ast_check_hangup(c)) {
11586 free(mybuf);
11587 return -1;
11589 size = len;
11590 if (size > READ_SIZE)
11591 size = READ_SIZE;
11592 fds[0].fd = fd;
11593 fds[0].events = POLLOUT | POLLPRI;
11594 fds[0].revents = 0;
11595 res = poll(fds, 1, -1);
11596 if (!res) {
11597 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
11598 continue;
11600 /* if got exception */
11601 if (fds[0].revents & POLLPRI) {
11602 ast_free(mybuf);
11603 return -1;
11605 if (!(fds[0].revents & POLLOUT)) {
11606 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
11607 continue;
11609 res = write(fd, buf, size);
11610 if (res != size) {
11611 if (res == -1) {
11612 free(mybuf);
11613 return -1;
11615 if (option_debug)
11616 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
11617 break;
11619 len -= size;
11620 buf += size;
11622 free(mybuf);
11623 return(0);
11627 static int reload(void)
11629 int res = 0;
11631 res = setup_dahdi(1);
11632 if (res) {
11633 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
11634 return -1;
11636 return 0;
11639 /* This is a workaround so that menuselect displays a proper description
11640 * AST_MODULE_INFO(, , "DAHDI Telephony"
11643 #ifdef DAHDI_PRI
11644 #define tdesc "DAHDI Telephony w/PRI"
11645 #else
11646 #define tdesc "DAHDI Telephony"
11647 #endif
11649 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
11650 .load = load_module,
11651 .unload = unload_module,
11652 .reload = reload,