]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/asterisk.patch
HinzugefĆ¼gt:
[ipfire-2.x.git] / src / patches / asterisk.patch
CommitLineData
b684b13b
MT
1diff -urN asterisk-1.2.9.1.orig/.version asterisk-1.2.9.1/.version
2--- asterisk-1.2.9.1.orig/.version 2006-06-06 18:19:31.000000000 +0200
3+++ asterisk-1.2.9.1/.version 2006-06-09 10:25:16.000000000 +0200
5e69ef1a 4@@ -1 +1 @@
b684b13b
MT
5-1.2.9.1
6+1.2.9.1-BRIstuffed-0.3.0-PRE-1q
7diff -urN asterisk-1.2.9.1.orig/HARDWARE asterisk-1.2.9.1/HARDWARE
8--- asterisk-1.2.9.1.orig/HARDWARE 2005-11-29 19:24:39.000000000 +0100
9+++ asterisk-1.2.9.1/HARDWARE 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
10@@ -37,6 +37,19 @@
11 * Wildcard TE410P - Quad T1/E1 switchable interface. Supports PRI and
12 RBS signalling, as well as PPP, FR, and HDLC data modes.
13
14+-- Junghanns.NET (Primary author of BRIstuff)
15+ http://www.junghanns.net
16+
17+ * quadBRI PCI ISDN - 4port BRI ISDN interface, supports NT and TE mode
18+
19+ * octoBRI PCI ISDN - 8port BRI ISDN interface, supports NT and TE mode
20+
21+ * singleE1 PCI ISDN - Single E1 interface
22+
23+ * doubleE1 PCI ISDN - Double E1 interface
24+
5f892677 25+ * uno/duo/quad GSM PCI - 1/2/4 channel GSM interface cards
5e69ef1a
MT
26+
27 Non-zaptel compatible hardware
28 ==============================
29
b684b13b
MT
30diff -urN asterisk-1.2.9.1.orig/LICENSE asterisk-1.2.9.1/LICENSE
31--- asterisk-1.2.9.1.orig/LICENSE 2005-11-29 19:24:39.000000000 +0100
32+++ asterisk-1.2.9.1/LICENSE 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
33@@ -1,7 +1,7 @@
34-Asterisk is distributed under the GNU General Public License version 2
35-and is also available under alternative licenses negotiated directly
36-with Digium, Inc. If you obtained Asterisk under the GPL, then the GPL
37-applies to all loadable Asterisk modules used on your system as well,
38+BRIstuffed Asterisk is distributed under the GNU General Public License version 2
39+and is not available under any alternative licenses.
40+If you obtained BRIstuffed Asterisk under the GPL, then the GPL
41+applies to all loadable BRIstuffed Asterisk modules used on your system as well,
42 except as defined below. The GPL (version 2) is included in this
43 source tree in the file COPYING.
44
b684b13b
MT
45diff -urN asterisk-1.2.9.1.orig/Makefile asterisk-1.2.9.1/Makefile
46--- asterisk-1.2.9.1.orig/Makefile 2006-04-30 16:27:56.000000000 +0200
47+++ asterisk-1.2.9.1/Makefile 2006-06-09 10:25:04.000000000 +0200
48@@ -761,6 +761,9 @@
5e69ef1a
MT
49 echo ";astctlowner = root" ; \
50 echo ";astctlgroup = apache" ; \
51 echo ";astctl = asterisk.ctl" ; \
52+ echo "[options]" ; \
53+ echo "uniquename = asterisk" ;\
54+ echo "silence_suppression = yes" ;\
55 ) > $(DESTDIR)$(ASTCONFPATH) ; \
56 else \
57 echo "Skipping asterisk.conf creation"; \
b684b13b
MT
58diff -urN asterisk-1.2.9.1.orig/README asterisk-1.2.9.1/README
59--- asterisk-1.2.9.1.orig/README 2006-03-03 09:12:33.000000000 +0100
60+++ asterisk-1.2.9.1/README 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
61@@ -4,6 +4,8 @@
62
63 Copyright (C) 2001-2005 Digium, Inc.
64 and other copyright holders.
65+Copyright (C) 2002-2005 Junghanns.NET GmbH
66+and other copyright holders.
67 ================================================================
68
69 * SECURITY
b684b13b
MT
70diff -urN asterisk-1.2.9.1.orig/README.chan_capi asterisk-1.2.9.1/README.chan_capi
71--- asterisk-1.2.9.1.orig/README.chan_capi 1970-01-01 01:00:00.000000000 +0100
72+++ asterisk-1.2.9.1/README.chan_capi 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
73@@ -0,0 +1,146 @@
74+(CAPI*) chan_capi a Common ISDN API 2.0 implementation for Asterisk
75+(C) 2002, 2003, 2004, 2005 Junghanns.NET GmbH
76+Klaus-Peter Junghanns <kpj@junghanns.net>
77+
78+This program is free software and may be modified and distributed under
79+the terms of the GNU Public License. There is _NO_ warranty for this!
80+
81+Thanks go to the debuggers and bugfixers (listed in chronological order) :)
82+===========================================================================
83+Lele Forzani <lele@windmill.it>
84+Florian Overkamp <florian@obsimref.com>
85+Gareth Watts <gareth@omnipotent.net>
86+Jeff Noxon <jeff@planetfall.com>
87+Petr Michalek <petr.michalek@aca.cz>
88+Jan Stocker
89+(...and all the others that i forgot..) :-)
90+
91+chan_capi version 0.4.0-PRE1 includes:
92+======================================
93+
94+- multiple controller support
95+- CID,DNID (callling party, called party)
96+- CLIR/CLIP
97+- supplementary services, CD,HOLD,RETRIEVE,ECT
98+- DTMF (dependend on card) + software DTMF support
99+- early B3 connects (always,success,never)
100+- digital audio (what did you think?)
101+- incoming/outgoing calls
102+- overlap sending (dialtone)
103+- E(xplicit) C(all) T(ransfer) (...although it's done implicit .. but dont tell!)
104+- tuneable latency ;) you can configure the size of B3 blocks at compile time
105+ (in chan_capi_pvt.h, AST_CAPI_MAX_B3_BLOCK_SIZE)
106+ the default is 160 samples, for non-VoIP use you can tune it down to 130
107+- use asterisk's internal dsp functions for dtmf
108+- alaw support
109+- ulaw support!
110+- Eicon CAPI echo cancelation (echocancel=1)
111+- reject call waiting (ACO)
112+- DID for Point to Point mode (a.k.a overlap receiving)
113+- experimental echo squelching (echosquelch=1)
114+- call progress, no need to add ||r to your dialstring anymore
115+- rx/tx gains (rxgain=1.0)
116+- call deflection on circuitbusy (makefile option) (deflect=12345678)
117+- (inter)national dialing prefix (for callerid) configurable in capi.conf
118+- CLI command "capi info" shows B channel status
119+- capiECT will announce the callerID since it gets lost on most isdn pbxes
120+ the called party can press # to drop the call
121+- audio syncing (timing outgoing dataB3 on incoming dataB3), supposed to fix
122+ the DATA_B3_REQ (error = 0x1103) problem
123+- catch all MSN (incomingmsn=*)
124+- some configuration enhancements (msn=123,124,125 and controller=1,2,3,4)
125+- accountcode= added.
126+- finally the echo squelching works!
127+- callgroup support
128+- fixed pipe leak
129+- updated to support the new frame->delivery field
130+- compiles with latest cvs with a makefile option (LOOK AT THE MAKEFILE)
131+- fixed channel name bug in p2p mode
132+- added app_capiNoES for disabling the primitive echo suppressor, use this before
133+ you start recording voicemail or your files may get choppy
134+- fixed for latest cvs (AST_MUTEX_DEFINE_STATIC)
135+- fixed for latest cvs (asterisk/parking.h -> asterisk/features.h)
136+- fixed for latest cvs ast_pthread_create
137+
138+- ATTENTION! the dialstring syntax now uses the zaptel dialstring syntax
139+ it used to be: Dial(CAPI/[@]<outgoingMSN>:[b|B]<destination>)
140+
141+ now it is: Dial(CAPI/g<group>/[b|B]<destination>)
142+ or: Dial(CAPI/contr<controller>/[b|B]<destination>)
143+
144+ CLIP/CLIR is now uses the calling presentation of the calling channel, this can
145+ be modified using the CallingPres() application. Use CallinPres(32) for CLIR.
146+ That is why the msn= param in capi.conf is now obsolete. The callerID is also
147+ taken from the calling channel.
148+
149+- fixes for BSD (Jan Stocker)
150+
151+Helper applications
152+===================
153+kapejod says: "No No No, dont use those yet....!" (except maybe HOLD,ECT...)
154+
155+app_capiCD.c forwards an unanswered call to another phone (does not rely on sservice CD)
156+ example:
157+ exten => s,1,Wait,1
158+ exten => s,2,capiCD,12345678
159+
160+app_capiHOLD.c puts an answered call on hold, this has nothing to do with asterisk's onhold thingie (music et al)
161+ after putting a call onhold, never use the Wait application!
162+
163+app_capiRETRIEVE.c gets the holded call back
164+
165+app_capiECT.c explicit call transfer of the holded call (must put call on hold first!)
166+ example:
167+ exten => s,1,Answer
168+ exten => s,2,capiHOLD
169+ exten => s,3,capiECT,55:50
170+ will ECT the call to 50 using 55 as the callerid/outgoing msn
171+
172+
173+Using CLIR
174+==========
175+Use the CallingPres() application before you dial:
176+exten => _X.,1,CallingPres(32)
177+exten => _X.,2,Dial(CAPI/contr1/${EXTEN})
178+
179+Enjoying early B3 connects (inband call progress, tones and announcements)
180+==========================================================================
181+early B3 is now configurable in the dialstring :)
182+if you prefix the destination number with a 'b' early B3 will always be used, also if the call fails
183+because the number is unprovisioned, etc ...
184+if you prefix it with a 'B' early B3 will only be used on successful calls, giving you ring indication,etc...
185+
186+dont use indications in the Dial command, your local exchange will do that for you:
187+exten => _X.,1,Dial(CAPI/contr1/B${EXTEN},30) (early B3 on success)
188+exten => _X.,1,Dial(CAPI/contr1/b${EXTEN},30) (always early B3)
189+exten => _X.,1,Dial(CAPI/contr1/${EXTEN},30,r) (no early B3, fake ring indication)
190+
191+exten => _X.,1,Dial(CAPI/contr1/b${EXTEN},30,r) (always early B3, fake indicatons if the exchange
192+ does not give us indications)
193+exten => _X.,1,Dial(CAPI/contr1/B${EXTEN},30,r) (early B3 on success, fake indicatons if the exchange
194+ does not give us indications)
195+
196+you can totally turn B3 off in the Makefile at buildtime (-DNEVER_EVER_EARLY_B3_CONNECTS).
197+
198+For normal PBX usage you would use the "b" option, always early B3.
199+
200+Overlap sending (a.k.a. real dialtone)
201+======================================
202+when you dial an empty number, and have early B3 enabled, with:
203+ Dial(CAPI/g1/b)
204+the channel will come up at once and give you the dialtone it gets from the local exchange.
205+at this point the channel is like a legacy phone, now you can send dtmf digits to dial.
206+
207+Example context for incoming calls on MSN 12345678:
208+===================================================
209+
210+[capi-in]
211+exten => 12345678,1,Dial(SIP/phone1)
212+exten => 12345678,2,Hangup
213+
214+
215+More information/documentation and commercial support can be found at:
216+ http://www.junghanns.net/asterisk/
217+
218+
219+
b684b13b
MT
220diff -urN asterisk-1.2.9.1.orig/agi/Makefile asterisk-1.2.9.1/agi/Makefile
221--- asterisk-1.2.9.1.orig/agi/Makefile 2006-03-28 22:22:05.000000000 +0200
222+++ asterisk-1.2.9.1/agi/Makefile 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
223@@ -11,7 +11,7 @@
224 # the GNU General Public License
225 #
226
227-AGIS=agi-test.agi eagi-test eagi-sphinx-test
228+AGIS=agi-test.agi eagi-test eagi-sphinx-test xagi-test
229
5f892677 230 CFLAGS+=-DNO_AST_MM
5e69ef1a
MT
231
232@@ -37,7 +37,7 @@
233 $(CC) $(CFLAGS) -o eagi-sphinx-test eagi-sphinx-test.o $(LIBS)
234
235 clean:
236- rm -f *.so *.o look .depend eagi-test eagi-sphinx-test
237+ rm -f *.so *.o look .depend eagi-test eagi-sphinx-test xagi-test
238
239 %.so : %.o
240 $(CC) -shared -Xlinker -x -o $@ $<
b684b13b
MT
241diff -urN asterisk-1.2.9.1.orig/agi/xagi-test.c asterisk-1.2.9.1/agi/xagi-test.c
242--- asterisk-1.2.9.1.orig/agi/xagi-test.c 1970-01-01 01:00:00.000000000 +0100
243+++ asterisk-1.2.9.1/agi/xagi-test.c 2006-06-09 10:25:04.000000000 +0200
5f892677 244@@ -0,0 +1,175 @@
5e69ef1a
MT
245+/*
246+ * Asterisk -- A telephony toolkit for Linux.
247+ *
248+ * XAGI sample script
249+ *
250+ * Copyright (C) 2005 Junghanns.NET GmbH
251+ * Klaus-Peter Junghanns <kpj@junghanns.net>
252+ *
253+ * based on eagi-test.c
254+ *
255+ * This program is free software, distributed under the terms of
256+ * the GNU General Public License
257+ */
258+
259+#include <stdio.h>
260+#include <unistd.h>
261+#include <stdlib.h>
262+#include <errno.h>
263+#include <string.h>
264+#include <sys/select.h>
265+#ifdef SOLARIS
266+#include <solaris-compat/compat.h>
267+#endif
268+
269+#define AUDIO_FILENO_IN (STDERR_FILENO + 1)
270+#define AUDIO_FILENO_OUT (STDERR_FILENO + 2)
271+
272+static int read_environment(void)
273+{
274+ char buf[256];
275+ char *val;
276+ /* Read environment */
277+ for(;;) {
278+ fgets(buf, sizeof(buf), stdin);
279+ if (feof(stdin))
280+ return -1;
281+ buf[strlen(buf) - 1] = '\0';
282+ /* Check for end of environment */
283+ if (!strlen(buf))
284+ return 0;
285+ val = strchr(buf, ':');
286+ if (!val) {
287+ fprintf(stderr, "Invalid environment: '%s'\n", buf);
288+ return -1;
289+ }
290+ *val = '\0';
291+ val++;
292+ val++;
293+ /* Skip space */
294+ // fprintf(stderr, "Environment: '%s' is '%s'\n", buf, val);
295+
296+ /* Load into normal environment */
297+ setenv(buf, val, 1);
298+
299+ }
300+ /* Never reached */
301+ return 0;
302+}
303+
304+static void app_echo(void)
305+{
306+ fd_set fds;
307+ int res;
308+ int bytes = 0;
309+ static char astresp[256];
310+ char audiobuf[16000]; /* 1 second of audio */
311+ for (;;) {
312+ FD_ZERO(&fds);
313+ FD_SET(STDIN_FILENO, &fds);
314+ FD_SET(AUDIO_FILENO_IN, &fds);
315+ /* Wait for *some* sort of I/O */
316+ res = select(AUDIO_FILENO_IN + 1, &fds, NULL, NULL, NULL);
317+ if (res < 0) {
318+ fprintf(stderr, "Error in select: %s\n", strerror(errno));
319+ return;
320+ }
321+ if (FD_ISSET(STDIN_FILENO, &fds)) {
322+ fgets(astresp, sizeof(astresp), stdin);
323+ if (feof(stdin)) {
5f892677 324+ return;
5e69ef1a
MT
325+ }
326+ astresp[strlen(astresp) - 1] = '\0';
327+ fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
5f892677 328+ return;
5e69ef1a
MT
329+ }
330+ if (FD_ISSET(AUDIO_FILENO_IN, &fds)) {
331+ /* what goes in.... */
332+ res = read(AUDIO_FILENO_IN, audiobuf, sizeof(audiobuf));
333+ if (res > 0) {
334+ bytes = res;
335+ /* must come out */
336+ write(AUDIO_FILENO_OUT, audiobuf, bytes);
337+ }
338+ }
339+ }
340+}
341+
342+static char *wait_result(void)
343+{
344+ fd_set fds;
345+ int res;
5e69ef1a
MT
346+ static char astresp[256];
347+ char audiobuf[4096];
348+ for (;;) {
349+ FD_ZERO(&fds);
350+ FD_SET(STDIN_FILENO, &fds);
351+ FD_SET(AUDIO_FILENO_IN, &fds);
352+ /* Wait for *some* sort of I/O */
353+ res = select(AUDIO_FILENO_IN + 1, &fds, NULL, NULL, NULL);
354+ if (res < 0) {
355+ fprintf(stderr, "Error in select: %s\n", strerror(errno));
356+ return NULL;
357+ }
358+ if (FD_ISSET(STDIN_FILENO, &fds)) {
359+ fgets(astresp, sizeof(astresp), stdin);
360+ if (feof(stdin)) {
361+ fprintf(stderr, "Got hungup on apparently\n");
362+ return NULL;
363+ }
364+ astresp[strlen(astresp) - 1] = '\0';
365+ fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
366+ return astresp;
367+ }
368+ if (FD_ISSET(AUDIO_FILENO_IN, &fds)) {
369+ res = read(AUDIO_FILENO_IN, audiobuf, sizeof(audiobuf));
370+ /* drop it, like it's hot */
371+ }
372+ }
373+
374+}
375+
376+static char *run_command(char *command)
377+{
378+ fprintf(stdout, "%s\n", command);
379+ return wait_result();
380+}
381+
382+
383+static int run_script(void)
384+{
385+ char *res;
386+ res = run_command("STREAM FILE demo-echotest \"\"");
387+ if (!res) {
388+ fprintf(stderr, "Failed to execute command\n");
389+ return -1;
390+ }
391+ app_echo();
392+ return 0;
393+}
394+
395+int main(int argc, char *argv[])
396+{
397+ char *tmp;
398+ int ver = 0;
399+ int subver = 0;
400+ /* Setup stdin/stdout for line buffering */
401+ setlinebuf(stdin);
402+ setlinebuf(stdout);
403+ if (read_environment()) {
404+ fprintf(stderr, "Failed to read environment: %s\n", strerror(errno));
405+ exit(1);
406+ }
407+ tmp = getenv("agi_enhanced");
408+ if (tmp) {
409+ if (sscanf(tmp, "%d.%d", &ver, &subver) != 2)
410+ ver = 0;
411+ }
412+ if (ver < 2) {
413+ fprintf(stderr, "No XAGI services available. Use XAGI, not AGI or EAGI\n");
414+ exit(1);
415+ }
416+ if (run_script())
417+ return -1;
418+ exit(0);
419+}
b684b13b
MT
420diff -urN asterisk-1.2.9.1.orig/apps/Makefile asterisk-1.2.9.1/apps/Makefile
421--- asterisk-1.2.9.1.orig/apps/Makefile 2006-04-30 15:38:22.000000000 +0200
422+++ asterisk-1.2.9.1/apps/Makefile 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
423@@ -28,8 +28,15 @@
424 app_test.so app_forkcdr.so app_math.so app_realtime.so \
425 app_dumpchan.so app_waitforsilence.so app_while.so app_setrdnis.so \
426 app_md5.so app_readfile.so app_chanspy.so app_settransfercapability.so \
427+ app_pickup.so app_segfault.so app_callingpres.so app_devstate.so \
428 app_dictate.so app_externalivr.so app_directed_pickup.so \
429- app_mixmonitor.so app_stack.so
430+ app_mixmonitor.so app_stack.so
431+
432+
433+ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/capi20.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/capi20.h),)
434+ APPS+= app_capiNoES.so app_capiCD.so app_capiECT.so
435+endif
436+
437
438 #
439 # Obsolete things...
b684b13b
MT
440diff -urN asterisk-1.2.9.1.orig/apps/app_callingpres.c asterisk-1.2.9.1/apps/app_callingpres.c
441--- asterisk-1.2.9.1.orig/apps/app_callingpres.c 1970-01-01 01:00:00.000000000 +0100
442+++ asterisk-1.2.9.1/apps/app_callingpres.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
443@@ -0,0 +1,70 @@
444+/*
445+ * An application to change the CallingPresentation for an Asterisk channel.
446+ *
447+ * Copyright (C) 2005 Junghanns.NET GmbH
448+ * Klaus-Peter Junghanns <kpj@junghanns.net>
449+ *
450+ * This program is free software, distributed under the terms of
451+ * the GNU General Public License.
452+ *
453+ */
454+
455+#include <stdlib.h>
456+#include <unistd.h>
457+#include <string.h>
458+#include <stdio.h>
459+#include <asterisk/lock.h>
460+#include <asterisk/file.h>
461+#include <asterisk/logger.h>
462+#include <asterisk/channel.h>
463+#include <asterisk/pbx.h>
464+#include <asterisk/module.h>
465+
466+static char *synopsis_callingpres = "Change the presentation for the callerid";
467+static char *descrip_callingpres = "Callingpres(number): Changes the presentation for the callerid. Should be called before placing an outgoing call\n";
468+static char *app_callingpres = "CallingPres";
469+STANDARD_LOCAL_USER;
470+LOCAL_USER_DECL;
471+
472+
473+static int change_callingpres(struct ast_channel *chan, void *data)
474+{
475+ int mode = 0;
476+ struct localuser *u;
477+ LOCAL_USER_ADD(u);
478+ if (data) {
479+ mode = atoi((char *)data);
480+ chan->cid.cid_pres = mode;
481+ } else
482+ ast_log(LOG_NOTICE, "Application %s requres an argument: %s(number)\n", app_callingpres,app_callingpres);
483+ LOCAL_USER_REMOVE(u);
484+ return 0;
485+}
486+
487+int unload_module(void)
488+{
489+ STANDARD_HANGUP_LOCALUSERS;
490+ return ast_unregister_application(app_callingpres);
491+}
492+
493+int load_module(void)
494+{
495+ return ast_register_application(app_callingpres, change_callingpres, synopsis_callingpres, descrip_callingpres);
496+}
497+
498+char *description(void)
499+{
500+ return descrip_callingpres;
501+}
502+
503+int usecount(void)
504+{
505+ int res;
506+ STANDARD_USECOUNT(res);
507+ return res;
508+}
509+
510+char *key()
511+{
512+ return ASTERISK_GPL_KEY;
513+}
b684b13b
MT
514diff -urN asterisk-1.2.9.1.orig/apps/app_capiCD.c asterisk-1.2.9.1/apps/app_capiCD.c
515--- asterisk-1.2.9.1.orig/apps/app_capiCD.c 1970-01-01 01:00:00.000000000 +0100
516+++ asterisk-1.2.9.1/apps/app_capiCD.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
517@@ -0,0 +1,172 @@
518+/*
519+ * (CAPI*)
520+ *
521+ * An implementation of Common ISDN API 2.0 for Asterisk
522+ *
523+ * Call Deflection, inspired by capircvd by Alexander Brickwedde
524+ *
525+ * Copyright (C) 2002,2003,2004,2005 Junghanns.NET GmbH
526+ *
527+ * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
528+ *
529+ * This program is free software and may be modified and
530+ * distributed under the terms of the GNU Public License.
531+ */
532+
533+#include <stdlib.h>
534+#include <unistd.h>
535+#include <string.h>
536+#include <stdio.h>
537+#include <linux/capi.h>
538+#include <capi20.h>
539+
540+#include <asterisk/file.h>
541+#include <asterisk/logger.h>
542+#include <asterisk/channel.h>
543+#include <asterisk/pbx.h>
544+#include <asterisk/module.h>
545+#include <asterisk/chan_capi.h>
546+#include <asterisk/chan_capi_app.h>
547+
548+
549+
550+static char *tdesc = "(CAPI*) Call Deflection, the magic thing.";
551+static char *app = "capiCD";
552+static char *synopsis = "call deflection";
553+
554+STANDARD_LOCAL_USER;
555+
556+LOCAL_USER_DECL;
557+
558+static int capiCD_exec(struct ast_channel *chan, void *data)
559+{
560+ struct ast_capi_pvt *i = chan->tech_pvt;
561+ MESSAGE_EXCHANGE_ERROR Info;
562+ _cmsg CMSG;
563+ char bchaninfo[1];
564+ char fac[60];
565+ int res=0;
566+ int ms=3000;
567+ struct localuser *u;
568+
569+ if (!data) {
570+ ast_log(LOG_WARNING, "cd requires an argument (destination phone number)\n");
571+ return -1;
572+ }
573+ LOCAL_USER_ADD(u);
574+ /* Do our thing here */
575+
576+ if ((i->state == CAPI_STATE_CONNECTED) || (i->state == CAPI_STATE_BCONNECTED)) {
577+ ast_log(LOG_ERROR, "call deflection does not work with calls that are already connected!\n");
578+ LOCAL_USER_REMOVE(u);
579+ return -1;
580+ }
581+ // wait until the channel is alerting, so we dont drop the call and interfer with msgs
582+ while ((ms > 0) && (i->state != CAPI_STATE_ALERTING)) {
583+ sleep(100);
584+ ms -= 100;
585+ }
586+
587+ // make sure we hang up correctly
588+ i->state = CAPI_STATE_CONNECTPENDING;
589+
590+ fac[0]=0; // len
591+ fac[1]=0; //len
592+ fac[2]=0x01; // Use D-Chan
593+ fac[3]=0; // Keypad len
594+ fac[4]=31; // user user data? len = 31 = 29 + 2
595+ fac[5]=0x1c; // magic?
596+ fac[6]=0x1d; // strlen destination + 18 = 29
597+ fac[7]=0x91; // ..
598+ fac[8]=0xA1;
599+ fac[9]=0x1A; // strlen destination + 15 = 26
600+ fac[10]=0x02;
601+ fac[11]=0x01;
602+ fac[12]=0x70;
603+ fac[13]=0x02;
604+ fac[14]=0x01;
605+ fac[15]=0x0d;
606+ fac[16]=0x30;
607+ fac[17]=0x12; // strlen destination + 7 = 18
608+ fac[18]=0x30; // ...hm 0x30
609+ fac[19]=0x0d; // strlen destination + 2
610+ fac[20]=0x80; // CLIP
611+ fac[21]=0x0b; // strlen destination
612+ fac[22]=0x01; // destination start
613+ fac[23]=0x01; //
614+ fac[24]=0x01; //
615+ fac[25]=0x01; //
616+ fac[26]=0x01; //
617+ fac[27]=0x01; //
618+ fac[28]=0x01; //
619+ fac[29]=0x01; //
620+ fac[30]=0x01; //
621+ fac[31]=0x01; //
622+ fac[32]=0x01; //
623+ fac[33]=0x01; // 0x1 = sending complete
624+ fac[34]=0x01;
625+ fac[35]=0x01;
626+
627+ memcpy((unsigned char *)fac+22,data,strlen(data));
628+ fac[22+strlen(data)]=0x01; // fill with 0x01 if number is only 6 numbers (local call)
629+ fac[23+strlen(data)]=0x01;
630+ fac[24+strlen(data)]=0x01;
631+ fac[25+strlen(data)]=0x01;
632+ fac[26+strlen(data)]=0x01;
633+
634+ fac[6]=18+strlen(data);
635+ fac[9]=15+strlen(data);
636+ fac[17]=7+strlen(data);
637+ fac[19]=2+strlen(data);
638+ fac[21]=strlen(data);
639+
640+ bchaninfo[0] = 0x1;
641+ INFO_REQ_HEADER(&CMSG,ast_capi_ApplID,ast_capi_MessageNumber++,0);
642+ INFO_REQ_CONTROLLER(&CMSG) = i->controller;
643+ INFO_REQ_PLCI(&CMSG) = i->PLCI;
644+ INFO_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char*)bchaninfo; // use D-Channel
645+ INFO_REQ_KEYPADFACILITY(&CMSG) = 0;
646+ INFO_REQ_USERUSERDATA(&CMSG) = 0;
647+ INFO_REQ_FACILITYDATAARRAY(&CMSG) = (unsigned char*) fac + 4;
648+
649+ if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
650+ ast_log(LOG_ERROR,"Error sending INFO_REQ\n");
651+ return Info;
652+ } else {
653+ if (capidebug) {
654+ // ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(&CMSG));
655+ ast_log(LOG_NOTICE,"sent INFO_REQ PLCI = %#x\n",i->PLCI);
656+ }
657+ }
658+
659+ LOCAL_USER_REMOVE(u);
660+ return res;
661+}
662+
663+int unload_module(void)
664+{
665+ STANDARD_HANGUP_LOCALUSERS;
666+ return ast_unregister_application(app);
667+}
668+
669+int load_module(void)
670+{
671+ return ast_register_application(app, capiCD_exec,synopsis,tdesc);
672+}
673+
674+char *description(void)
675+{
676+ return tdesc;
677+}
678+
679+int usecount(void)
680+{
681+ int res;
682+ STANDARD_USECOUNT(res);
683+ return res;
684+}
685+
686+char *key()
687+{
688+ return ASTERISK_GPL_KEY;
689+}
b684b13b
MT
690diff -urN asterisk-1.2.9.1.orig/apps/app_capiECT.c asterisk-1.2.9.1/apps/app_capiECT.c
691--- asterisk-1.2.9.1.orig/apps/app_capiECT.c 1970-01-01 01:00:00.000000000 +0100
692+++ asterisk-1.2.9.1/apps/app_capiECT.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
693@@ -0,0 +1,210 @@
694+/*
695+ * (CAPI*)
696+ *
697+ * An implementation of Common ISDN API 2.0 for Asterisk
698+ *
699+ * ECT transfer the held call
700+ *
701+ * Copyright (C) 2002,2003,2004,2005 Junghanns.NET GmbH
702+ *
703+ * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
704+ *
705+ * This program is free software and may be modified and
706+ * distributed under the terms of the GNU Public License.
707+ */
708+
709+#include <stdlib.h>
710+#include <unistd.h>
711+#include <string.h>
712+#include <stdio.h>
713+#include <linux/capi.h>
714+#include <capi20.h>
715+#include <asterisk/file.h>
716+#include <asterisk/logger.h>
717+#include <asterisk/channel.h>
718+#include <asterisk/pbx.h>
719+#include <asterisk/module.h>
720+#include <asterisk/say.h>
721+#include <asterisk/chan_capi.h>
722+#include <asterisk/chan_capi_app.h>
723+
724+
725+static char *tdesc = "(CAPI*) ECT";
726+static char *app = "capiECT";
727+static char *synopsis = "transfer the call that is on hold";
728+
729+STANDARD_LOCAL_USER;
730+
731+LOCAL_USER_DECL;
732+
733+
734+static int capiECT_exec(struct ast_channel *chan, void *data)
735+{
736+ struct ast_capi_pvt *i = chan->tech_pvt;
737+ MESSAGE_EXCHANGE_ERROR Info;
738+ _cmsg CMSG;
739+ unsigned char fac[8];
740+ int res=0;
741+ struct localuser *u;
742+ char *ecodes = "*#";
743+
744+ if (!data) {
745+ ast_log(LOG_WARNING, "ECT requires an argument (destination phone number)\n");
746+ return -1;
747+ }
748+ LOCAL_USER_ADD(u);
749+ /* Do our thing here */
750+ if (i->onholdPLCI <= 0) {
751+ ast_log(LOG_WARNING, "no call on hold that could be transfered\n");
752+ return -1;
753+ }
754+
755+ ast_log(LOG_NOTICE,"ECT to %s\n",(char *)data);
756+ capi_call(chan,data,0);
757+
758+ while ((i->state != CAPI_STATE_BCONNECTED) && (i->onholdPLCI != 0)) {
759+ usleep(10000);
760+ }
761+
762+
763+ if (i->state == CAPI_STATE_BCONNECTED) {
764+ ast_log(LOG_NOTICE,"call was answered\n");
765+
766+ capi_detect_dtmf(chan,1);
767+
768+ // put the stuff to play announcement message here ---> <-----
769+ res = ast_say_digit_str(chan,i->cid,ecodes,chan->language);
770+ if ( res == '#') {
771+ ast_log(LOG_NOTICE,"res = %d\n",res);
772+ // user pressed #, hangup
773+ // first the holded user
774+// ast_exec("capiRETRIEVE",chan);
775+
776+ DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
777+ DISCONNECT_REQ_PLCI(&CMSG) = i->onholdPLCI;
778+
779+ if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
780+ ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",i->onholdPLCI);
781+ } else {
782+ ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",i->onholdPLCI);
783+ }
784+
785+ // then the destination
786+
787+ DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
788+ DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
789+
790+ if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
791+ ast_log(LOG_NOTICE, "error sending DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
792+ } else {
793+ ast_log(LOG_NOTICE, "sent DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
794+ }
795+
796+ // wait for the B3 layer to go down
797+ while (i->state != CAPI_STATE_CONNECTED) {
798+ usleep(10000);
799+ }
800+
801+ DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
802+ DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
803+
804+ if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
805+ ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
806+ } else {
807+ ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
808+ }
809+
810+
811+ LOCAL_USER_REMOVE(u);
812+ return -1;
813+
814+ } else {
815+ // now drop the bchannel
816+ DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
817+ DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
818+
819+ if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
820+ ast_log(LOG_NOTICE, "error sending DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
821+ } else {
822+ ast_log(LOG_NOTICE, "sent DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
823+ }
824+
825+ // wait for the B3 layer to go down
826+ while (i->state != CAPI_STATE_CONNECTED) {
827+ usleep(10000);
828+ }
829+ }
830+ }
831+
832+ // the caller onhold hungup or died away, drop the answered call
833+ if (i->onholdPLCI == 0) {
834+ DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
835+ DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
836+
837+ if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
838+ ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
839+ } else {
840+ ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
841+ }
842+ return -1;
843+ }
844+
845+ ast_log(LOG_NOTICE,"onholdPLCI = %d\n",i->onholdPLCI);
846+
847+
848+ fac[0] = 7; // len
849+ fac[1] = 0x06; // ECT (function)
850+ fac[2] = 0x00;
851+ fac[3] = 4; //len //sservice specific parameter , cstruct
852+ fac[4] = (i->onholdPLCI << 8 ) >> 8;
853+ fac[5] = i->onholdPLCI >> 8;
854+ fac[6] = 0;
855+ fac[7] = 0;
856+
857+ FACILITY_REQ_HEADER(&CMSG,ast_capi_ApplID,ast_capi_MessageNumber++,0);
858+ FACILITY_REQ_CONTROLLER(&CMSG) = i->controller;
859+ FACILITY_REQ_PLCI(&CMSG) = i->onholdPLCI;
860+ FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 0x0003; // sservices
861+ FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = (unsigned char *)&fac;
862+
863+ if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
864+ ast_log(LOG_ERROR,"Error sending FACILITY_REQ\n");
865+ return Info;
866+ } else {
867+ ast_log(LOG_NOTICE,"sent FACILITY_REQ PLCI = %#x (%#x %#x) onholdPLCI = %#x\n ",i->PLCI,fac[4],fac[5],i->onholdPLCI);
868+ ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(&CMSG));
869+ }
870+
871+// i->outgoing = -1; // incoming + outgoing, this is a magic channel :)
872+
873+ LOCAL_USER_REMOVE(u);
874+ return res;
875+}
876+
877+int unload_module(void)
878+{
879+ STANDARD_HANGUP_LOCALUSERS;
880+ return ast_unregister_application(app);
881+}
882+
883+int load_module(void)
884+{
885+ return ast_register_application(app, capiECT_exec,synopsis,tdesc);
886+}
887+
888+char *description(void)
889+{
890+ return tdesc;
891+}
892+
893+int usecount(void)
894+{
895+ int res;
896+ STANDARD_USECOUNT(res);
897+ return res;
898+}
899+
900+char *key()
901+{
902+ return ASTERISK_GPL_KEY;
903+}
b684b13b
MT
904diff -urN asterisk-1.2.9.1.orig/apps/app_capiNoES.c asterisk-1.2.9.1/apps/app_capiNoES.c
905--- asterisk-1.2.9.1.orig/apps/app_capiNoES.c 1970-01-01 01:00:00.000000000 +0100
906+++ asterisk-1.2.9.1/apps/app_capiNoES.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
907@@ -0,0 +1,96 @@
908+/*
909+ * (CAPI*)
910+ *
911+ * An implementation of Common ISDN API 2.0 for Asterisk
912+ *
913+ * Disable echo suppression (useful for fax and voicemail!)
914+ *
915+ * Copyright (C) 2004,2005 Junghanns.NET GmbH
916+ *
917+ * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
918+ *
919+ * This program is free software and may be modified and
920+ * distributed under the terms of the GNU Public License.
921+ */
922+
923+#include <stdlib.h>
924+#include <unistd.h>
925+#include <string.h>
926+#include <stdio.h>
927+#include <linux/capi.h>
928+#include <capi20.h>
929+
930+#include <asterisk/file.h>
931+#include <asterisk/logger.h>
932+#include <asterisk/channel.h>
933+#include <asterisk/pbx.h>
934+#include <asterisk/module.h>
935+#include <asterisk/chan_capi_app.h>
936+
937+
938+
939+#ifdef CAPI_ES
940+static char *tdesc = "(CAPI*) No Echo Suppression.";
941+static char *app = "capiNoES";
942+static char *synopsis = "Disable Echo Suppression";
943+#else
944+static char *tdesc = "(CAPI*) No Echo Suppression at all!";
945+static char *app = "capiNoES";
946+static char *synopsis = "Bogus Application";
947+#endif
948+STANDARD_LOCAL_USER;
949+
950+LOCAL_USER_DECL;
951+
952+static int capiNoES_exec(struct ast_channel *chan, void *data)
953+{
954+ int res=0;
955+ struct localuser *u;
956+ LOCAL_USER_ADD(u);
957+
958+#ifdef CAPI_ES
959+ if (strcasecmp("CAPI",chan->type) == 0) {
960+#ifdef CVS_HEAD
961+ struct ast_capi_pvt *i = chan->tech_pvt;
962+#else
963+ struct ast_capi_pvt *i = chan->pvt->pvt;
964+#endif
965+ if (i->doES == 1) {
966+ i->doES = 0;
967+ }
968+ } else {
969+ ast_log(LOG_WARNING, "capiNoES only works on CAPI channels, check your extensions.conf!\n");
970+ }
971+#endif
972+
973+ LOCAL_USER_REMOVE(u);
974+ return res;
975+}
976+
977+int unload_module(void)
978+{
979+ STANDARD_HANGUP_LOCALUSERS;
980+ return ast_unregister_application(app);
981+}
982+
983+int load_module(void)
984+{
985+ return ast_register_application(app, capiNoES_exec,synopsis,tdesc);
986+}
987+
988+char *description(void)
989+{
990+ return tdesc;
991+}
992+
993+int usecount(void)
994+{
995+ int res;
996+ STANDARD_USECOUNT(res);
997+ return res;
998+}
999+
1000+char *key()
1001+{
1002+ return ASTERISK_GPL_KEY;
1003+}
b684b13b
MT
1004diff -urN asterisk-1.2.9.1.orig/apps/app_chanisavail.c asterisk-1.2.9.1/apps/app_chanisavail.c
1005--- asterisk-1.2.9.1.orig/apps/app_chanisavail.c 2005-11-29 19:24:39.000000000 +0100
1006+++ asterisk-1.2.9.1/apps/app_chanisavail.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
1007@@ -118,7 +118,7 @@
1008 snprintf(trychan, sizeof(trychan), "%s/%s",cur,number);
1009 status = inuse = ast_device_state(trychan);
1010 }
1011- if ((inuse <= 1) && (tempchan = ast_request(tech, chan->nativeformats, number, &status))) {
1012+ if ((inuse <= 1) && (tempchan = ast_request(tech, chan->nativeformats, number, &status, NULL))) {
1013 pbx_builtin_setvar_helper(chan, "AVAILCHAN", tempchan->name);
1014 /* Store the originally used channel too */
1015 snprintf(tmp, sizeof(tmp), "%s/%s", tech, number);
b684b13b
MT
1016diff -urN asterisk-1.2.9.1.orig/apps/app_chanspy.c asterisk-1.2.9.1/apps/app_chanspy.c
1017--- asterisk-1.2.9.1.orig/apps/app_chanspy.c 2006-01-03 18:24:56.000000000 +0100
1018+++ asterisk-1.2.9.1/apps/app_chanspy.c 2006-06-09 10:25:04.000000000 +0200
1019@@ -54,6 +54,7 @@
1020
1021 static const char *synopsis = "Listen to the audio of an active channel\n";
1022 static const char *app = "ChanSpy";
1023+static const char *app2 = "ChanSpyChan";
1024 static const char *desc =
1025 " ChanSpy([chanprefix][|options]): This application is used to listen to the\n"
1026 "audio from an active Asterisk channel. This includes the audio coming in and\n"
1027@@ -141,6 +142,19 @@
1028 return ret;
1029 }
1030
1031+static struct ast_channel *local_get_channel_uniqueid(char *uniqueid)
1032+{
1033+ struct ast_channel *chan = NULL;
1034+ if (uniqueid) {
1035+ ast_mutex_lock(&modlock);
1036+ if ((chan = ast_get_channel_by_uniqueid_locked(uniqueid))) {
1037+ ast_mutex_unlock(&chan->lock);
1038+ }
1039+ ast_mutex_unlock(&modlock);
1040+ }
1041+ return chan;
1042+}
1043+
1044 static void *spy_alloc(struct ast_channel *chan, void *data)
1045 {
1046 /* just store the data pointer in the channel structure */
1047@@ -553,11 +567,87 @@
1048 ALL_DONE(u, res);
1049 }
1050
1051+static int chanspychan_exec(struct ast_channel *chan, void *data)
1052+{
1053+ struct localuser *u;
1054+ struct ast_channel *peer=NULL;
1055+ char *args,
1056+ *uniqueid = NULL,
1057+ *argv[5];
1058+ int res = -1,
1059+ volfactor = 0,
1060+ argc = 0,
1061+ oldrf = 0,
1062+ oldwf = 0,
1063+ fd = 0;
1064+ signed char zero_volume = 0;
1065+
1066+ if (!(args = ast_strdupa((char *)data))) {
1067+ ast_log(LOG_ERROR, "Out of memory!\n");
1068+ return -1;
1069+ }
1070+
1071+ LOCAL_USER_ADD(u);
1072+
1073+ oldrf = chan->readformat;
1074+ oldwf = chan->writeformat;
1075+ if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) {
1076+ ast_log(LOG_ERROR, "Could Not Set Read Format.\n");
1077+ LOCAL_USER_REMOVE(u);
1078+ return -1;
1079+ }
1080+
1081+ if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
1082+ ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1083+ LOCAL_USER_REMOVE(u);
1084+ return -1;
1085+ }
1086+
1087+
1088+ if ((argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
1089+ uniqueid = argv[0];
1090+ if (ast_strlen_zero(uniqueid)) {
1091+ LOCAL_USER_REMOVE(u);
1092+ return -1;
1093+ }
1094+ }
1095+
1096+ ast_answer(chan);
1097+
1098+ ast_set_flag(chan, AST_FLAG_SPYING); /* so nobody can spy on us while we are spying */
1099+
1100+ peer = local_get_channel_uniqueid(uniqueid);
1101+ if (peer && (peer != chan) && !ast_check_hangup(peer) && !ast_test_flag(peer, AST_FLAG_SPYING)) {
1102+ res = channel_spy(chan, peer, &volfactor, fd);
1103+ } else {
1104+ ast_log(LOG_NOTICE, "no channel found with uniqueid %s\n", uniqueid);
1105+ }
1106+
1107+ if (fd > 0) {
1108+ close(fd);
1109+ }
1110+
1111+ if (oldrf && ast_set_read_format(chan, oldrf) < 0) {
1112+ ast_log(LOG_ERROR, "Could Not Set Read Format.\n");
1113+ }
1114+
1115+ if (oldwf && ast_set_write_format(chan, oldwf) < 0) {
1116+ ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1117+ }
1118+
1119+ ast_clear_flag(chan, AST_FLAG_SPYING);
1120+
1121+ ast_channel_setoption(chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0);
1122+
1123+ ALL_DONE(u, res);
1124+}
1125+
1126 int unload_module(void)
1127 {
1128 int res;
1129
1130- res = ast_unregister_application(app);
1131+ ast_unregister_application(app);
1132+ res = ast_unregister_application(app2);
1133
1134 STANDARD_HANGUP_LOCALUSERS;
1135
1136@@ -566,7 +656,8 @@
1137
1138 int load_module(void)
1139 {
1140- return ast_register_application(app, chanspy_exec, synopsis, desc);
1141+ ast_register_application(app, chanspy_exec, synopsis, desc);
1142+ return ast_register_application(app2, chanspychan_exec, synopsis, desc);
1143 }
1144
1145 char *description(void)
1146diff -urN asterisk-1.2.9.1.orig/apps/app_devstate.c asterisk-1.2.9.1/apps/app_devstate.c
1147--- asterisk-1.2.9.1.orig/apps/app_devstate.c 1970-01-01 01:00:00.000000000 +0100
1148+++ asterisk-1.2.9.1/apps/app_devstate.c 2006-06-09 10:25:04.000000000 +0200
1149@@ -0,0 +1,225 @@
5e69ef1a
MT
1150+/*
1151+ * Devstate application
1152+ *
1153+ * Since we like the snom leds so much, a little app to
1154+ * light the lights on the snom on demand ....
1155+ *
1156+ * Copyright (C) 2005, Druid Software
1157+ *
1158+ * This program is free software, distributed under the terms of
1159+ * the GNU General Public License
1160+ */
1161+
1162+#include <stdlib.h>
1163+#include <unistd.h>
1164+#include <string.h>
1165+#include <stdio.h>
1166+#include <asterisk/lock.h>
1167+#include <asterisk/file.h>
1168+#include <asterisk/logger.h>
1169+#include <asterisk/channel.h>
1170+#include <asterisk/pbx.h>
1171+#include <asterisk/module.h>
1172+#include <asterisk/astdb.h>
1173+#include <asterisk/utils.h>
1174+#include <asterisk/cli.h>
1175+#include <asterisk/manager.h>
1176+#include <asterisk/devicestate.h>
1177+
1178+
1179+static char type[] = "DS";
1180+static char tdesc[] = "Application for sending device state messages";
1181+
1182+static char app[] = "Devstate";
1183+
1184+static char synopsis[] = "Generate a device state change event given the input parameters";
1185+
1186+static char descrip[] = " Devstate(device|state): Generate a device state change event given the input parameters. Returns 0. State values match the asterisk device states. They are 0 = unknown, 1 = not inuse, 2 = inuse, 3 = busy, 4 = invalid, 5 = unavailable, 6 = ringing\n";
1187+
1188+static char devstate_cli_usage[] =
1189+"Usage: devstate device state\n"
1190+" Generate a device state change event given the input parameters.\n Mainly used for lighting the LEDs on the snoms.\n";
1191+
1192+static int devstate_cli(int fd, int argc, char *argv[]);
1193+static struct ast_cli_entry cli_dev_state =
1194+ { { "devstate", NULL }, devstate_cli, "Set the device state on one of the \"pseudo devices\".", devstate_cli_usage };
1195+
1196+STANDARD_LOCAL_USER;
1197+
1198+LOCAL_USER_DECL;
1199+
1200+
1201+static int devstate_cli(int fd, int argc, char *argv[])
1202+{
1203+ char devName[128];
b684b13b 1204+ if ((argc != 3) && (argc != 4) && (argc != 5))
5e69ef1a
MT
1205+ return RESULT_SHOWUSAGE;
1206+
1207+ if (ast_db_put("DEVSTATES", argv[1], argv[2]))
1208+ {
1209+ ast_log(LOG_DEBUG, "ast_db_put failed\n");
1210+ }
1211+ snprintf(devName, sizeof(devName), "DS/%s", argv[1]);
1212+ if (argc == 4) {
1213+ ast_log(LOG_NOTICE, "devname %s cid %s\n", devName, argv[3]);
1214+ ast_device_state_changed_literal(devName, argv[3], NULL);
b684b13b
MT
1215+ } else if (argc == 5) {
1216+ ast_log(LOG_NOTICE, "devname %s cid %s cidname %s\n", devName, argv[3], argv[4]);
1217+ ast_device_state_changed_literal(devName, argv[3], argv[4]);
5e69ef1a
MT
1218+ } else {
1219+ ast_device_state_changed_literal(devName, NULL, NULL);
1220+ }
1221+ return RESULT_SUCCESS;
1222+}
1223+
1224+static int devstate_exec(struct ast_channel *chan, void *data)
1225+{
1226+ struct localuser *u;
1227+ char *device, *state, *info;
1228+ char devName[128];
1229+ if (!(info = ast_strdupa(data))) {
1230+ ast_log(LOG_WARNING, "Unable to dupe data :(\n");
1231+ return -1;
1232+ }
1233+ LOCAL_USER_ADD(u);
1234+
1235+ device = info;
1236+ state = strchr(info, '|');
1237+ if (state) {
1238+ *state = '\0';
1239+ state++;
1240+ }
1241+ else
1242+ {
1243+ ast_log(LOG_DEBUG, "No state argument supplied\n");
1244+ return -1;
1245+ }
1246+
1247+ if (ast_db_put("DEVSTATES", device, state))
1248+ {
1249+ ast_log(LOG_DEBUG, "ast_db_put failed\n");
1250+ }
1251+
1252+ snprintf(devName, sizeof(devName), "DS/%s", device);
1253+ ast_device_state_changed_literal(devName, NULL, NULL);
1254+
1255+ LOCAL_USER_REMOVE(u);
1256+ return 0;
1257+}
1258+
1259+
1260+static int ds_devicestate(void *data)
1261+{
1262+ char *dest = data;
1263+ char stateStr[16];
1264+ if (ast_db_get("DEVSTATES", dest, stateStr, sizeof(stateStr)))
1265+ {
1266+ ast_log(LOG_DEBUG, "ds_devicestate couldnt get state in astdb\n");
1267+ return 0;
1268+ }
1269+ else
1270+ {
1271+ ast_log(LOG_DEBUG, "ds_devicestate dev=%s returning state %d\n",
1272+ dest, atoi(stateStr));
1273+ return (atoi(stateStr));
1274+ }
1275+}
1276+
1277+static struct ast_channel_tech devstate_tech = {
1278+ .type = type,
1279+ .description = tdesc,
1280+ .capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
1281+ .devicestate = ds_devicestate,
1282+ .requester = NULL,
1283+ .send_digit = NULL,
1284+ .send_text = NULL,
1285+ .call = NULL,
1286+ .hangup = NULL,
1287+ .answer = NULL,
1288+ .read = NULL,
1289+ .write = NULL,
1290+ .bridge = NULL,
1291+ .exception = NULL,
1292+ .indicate = NULL,
1293+ .fixup = NULL,
1294+ .setoption = NULL,
1295+};
1296+
1297+static char mandescr_devstate[] =
1298+"Description: Put a value into astdb\n"
1299+"Variables: \n"
1300+" Family: ...\n"
1301+" Key: ...\n"
1302+" Value: ...\n";
1303+
1304+static int action_devstate(struct mansession *s, struct message *m)
1305+{
1306+ char *devstate = astman_get_header(m, "Devstate");
1307+ char *value = astman_get_header(m, "Value");
1308+ char *id = astman_get_header(m,"ActionID");
b684b13b
MT
1309+ char *cid_num = astman_get_header(m, "CallerID");
1310+ char *cid_name = astman_get_header(m, "CallerIDName");
5e69ef1a
MT
1311+ char devName[128];
1312+
1313+ if (!strlen(devstate)) {
1314+ astman_send_error(s, m, "No Devstate specified");
1315+ return 0;
1316+ }
1317+ if (!strlen(value)) {
1318+ astman_send_error(s, m, "No Value specified");
1319+ return 0;
1320+ }
1321+
1322+ if (!ast_db_put("DEVSTATES", devstate, value)) {
1323+ snprintf(devName, sizeof(devName), "DS/%s", devstate);
b684b13b
MT
1324+// ast_device_state_changed(devName);
1325+ ast_device_state_changed_literal(devName, cid_num, cid_name);
5e69ef1a
MT
1326+ ast_cli(s->fd, "Response: Success\r\n");
1327+ } else {
1328+ ast_log(LOG_DEBUG, "ast_db_put failed\n");
1329+ ast_cli(s->fd, "Response: Failed\r\n");
1330+ }
1331+ if (id && !ast_strlen_zero(id))
1332+ ast_cli(s->fd, "ActionID: %s\r\n",id);
1333+ ast_cli(s->fd, "\r\n");
1334+ return 0;
1335+}
1336+
1337+int load_module(void)
1338+{
1339+ if (ast_channel_register(&devstate_tech)) {
1340+ ast_log(LOG_DEBUG, "Unable to register channel class %s\n", type);
1341+ return -1;
1342+ }
1343+ ast_cli_register(&cli_dev_state);
1344+ ast_manager_register2( "Devstate", EVENT_FLAG_CALL, action_devstate, "Change a device state", mandescr_devstate );
1345+ return ast_register_application(app, devstate_exec, synopsis, descrip);
1346+}
1347+
1348+int unload_module(void)
1349+{
1350+ int res = 0;
1351+ STANDARD_HANGUP_LOCALUSERS;
1352+ ast_manager_unregister( "Devstate");
1353+ ast_cli_unregister(&cli_dev_state);
1354+ res = ast_unregister_application(app);
1355+ ast_channel_unregister(&devstate_tech);
1356+ return res;
1357+}
1358+
1359+char *description(void)
1360+{
1361+ return tdesc;
1362+}
1363+
1364+int usecount(void)
1365+{
1366+ int res;
1367+ STANDARD_USECOUNT(res);
1368+ return res;
1369+}
1370+
1371+char *key()
1372+{
1373+ return ASTERISK_GPL_KEY;
1374+}
b684b13b
MT
1375diff -urN asterisk-1.2.9.1.orig/apps/app_dial.c asterisk-1.2.9.1/apps/app_dial.c
1376--- asterisk-1.2.9.1.orig/apps/app_dial.c 2006-05-24 21:44:26.000000000 +0200
1377+++ asterisk-1.2.9.1/apps/app_dial.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
1378@@ -11,6 +11,10 @@
1379 * the project provides a web site, mailing lists and IRC
1380 * channels for your use.
1381 *
1382+ * Copyright (C) 2004, Junghanns.NET GmbH
1383+ *
1384+ * Klaus-Peter Junghanns <kpj@junghanns.net>
1385+ *
1386 * This program is free software, distributed under the terms of
1387 * the GNU General Public License Version 2. See the LICENSE file
1388 * at the top of the source tree.
b684b13b
MT
1389@@ -115,7 +119,8 @@
1390 " action post answer options in conjunction with this option.\n"
5e69ef1a
MT
1391 " h - Allow the called party to hang up by sending the '*' DTMF digit.\n"
1392 " H - Allow the calling party to hang up by hitting the '*' DTMF digit.\n"
1393-" j - Jump to priority n+101 if all of the requested channels were busy.\n"
1394+" j - Jump to priority n+101 if the called party was busy.\n"
1395+" Jump to priority n+201 if all of the requested channels were busy.\n"
1396 " L(x[:y][:z]) - Limit the call to 'x' ms. Play a warning when 'y' ms are\n"
1397 " left. Repeat the warning every 'z' ms. The following special\n"
1398 " variables can be used with this option:\n"
b684b13b 1399@@ -162,8 +167,11 @@
5e69ef1a
MT
1400 " family/key is not specified.\n"
1401 " r - Indicate ringing to the calling party. Pass no audio to the calling\n"
1402 " party until the called channel has answered.\n"
1403+" R - indicate ringing to the calling party when the called party indicates\n"
1404+" ringing, pass no audio until answered.\n"
1405 " S(x) - Hang up the call after 'x' seconds *after* the called party has\n"
1406-" answered the call.\n"
1407+" answered the call.\n"
1408+" c - callback initiation, ring once and hangup.\n"
1409 " t - Allow the called party to transfer the calling party by sending the\n"
1410 " DTMF sequence defined in features.conf.\n"
1411 " T - Allow the calling party to transfer the called party by sending the\n"
b684b13b 1412@@ -214,6 +222,8 @@
5e69ef1a
MT
1413 OPT_CALLEE_MONITOR = (1 << 21),
1414 OPT_CALLER_MONITOR = (1 << 22),
1415 OPT_GOTO = (1 << 23),
1416+ OPT_NOINBAND = (1 << 24),
1417+ OPT_CALLBACK_INIT = (1 << 25),
1418 } dial_exec_option_flags;
1419
1420 #define DIAL_STILLGOING (1 << 30)
b684b13b 1421@@ -252,6 +262,8 @@
5e69ef1a
MT
1422 AST_APP_OPTION('p', OPT_SCREENING),
1423 AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
1424 AST_APP_OPTION('r', OPT_RINGBACK),
1425+ AST_APP_OPTION('R', OPT_NOINBAND),
1426+ AST_APP_OPTION('c', OPT_CALLBACK_INIT),
1427 AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
1428 AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
1429 AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
b684b13b 1430@@ -389,7 +401,7 @@
5e69ef1a
MT
1431 char *context = NULL;
1432 char cidname[AST_MAX_EXTENSION];
1433
1434- single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK));
1435+ single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK | OPT_NOINBAND));
1436
1437 if (single) {
1438 /* Turn off hold music, etc */
b684b13b 1439@@ -468,7 +480,7 @@
5e69ef1a
MT
1440 if (option_verbose > 2)
1441 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
1442 /* Setup parameters */
1443- o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
1444+ o->chan = ast_request(tech, in->nativeformats, stuff, &cause, NULL);
1445 if (!o->chan)
1446 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
b684b13b
MT
1447 else
1448@@ -586,12 +598,18 @@
5f892677
MT
1449 HANDLE_CAUSE(AST_CAUSE_CONGESTION, in);
1450 break;
1451 case AST_CONTROL_RINGING:
1452- if (option_verbose > 2)
1453- ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
1454- if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) {
1455- ast_indicate(in, AST_CONTROL_RINGING);
1456- (*sentringing)++;
1457- }
1458+ if (ast_test_flag(peerflags, OPT_CALLBACK_INIT)) {
1459+ if (option_verbose > 2)
1460+ ast_verbose( VERBOSE_PREFIX_3 "%s is ringing, hanging up.\n", o->chan->name);
1461+ return NULL;
1462+ } else {
1463+ if (option_verbose > 2)
1464+ ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
1465+ if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) {
1466+ ast_indicate(in, AST_CONTROL_RINGING);
1467+ (*sentringing)++;
1468+ }
1469+ }
1470 break;
1471 case AST_CONTROL_PROGRESS:
1472 if (option_verbose > 2)
b684b13b 1473@@ -766,6 +784,7 @@
5f892677
MT
1474 int digit = 0, result = 0;
1475 time_t start_time, answer_time, end_time;
1476 struct ast_app *app = NULL;
b684b13b 1477+/* char *aoceunits; */
5f892677
MT
1478
1479 char *parse;
1480 AST_DECLARE_APP_ARGS(args,
b684b13b 1481@@ -939,13 +958,13 @@
5e69ef1a
MT
1482 }
1483
1484 if( privdb_val == AST_PRIVACY_DENY ) {
b684b13b 1485- strcpy(status, "NOANSWER");
5e69ef1a
MT
1486+ ast_copy_string(status, "NOANSWER", sizeof(status));
1487 ast_verbose( VERBOSE_PREFIX_3 "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
1488 res=0;
1489 goto out;
1490 }
1491 else if( privdb_val == AST_PRIVACY_KILL ) {
b684b13b 1492- strcpy(status, "DONTCALL");
5e69ef1a 1493+ ast_copy_string(status, "DONTCALL", sizeof(status));
b684b13b
MT
1494 if (option_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
1495 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
1496 }
1497@@ -953,7 +972,7 @@
5e69ef1a
MT
1498 goto out; /* Is this right? */
1499 }
1500 else if( privdb_val == AST_PRIVACY_TORTURE ) {
b684b13b 1501- strcpy(status, "TORTURE");
5e69ef1a 1502+ ast_copy_string(status, "TORTURE", sizeof(status));
b684b13b
MT
1503 if (option_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
1504 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 301);
1505 }
1506@@ -992,7 +1011,7 @@
5f892677
MT
1507 /* If a channel group has been specified, get it for use when we create peer channels */
1508 outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
1509
1510- ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP);
1511+ ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP| OPT_CALLBACK_INIT | OPT_NOINBAND);
1512 cur = args.peers;
1513 do {
1514 /* Remember where to start next time */
b684b13b 1515@@ -1034,7 +1053,7 @@
5e69ef1a
MT
1516 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
1517 }
1518 /* Request the peer */
1519- tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
1520+ tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause, NULL);
1521 if (!tmp->chan) {
1522 /* If we can't, just go on to the next call */
1523 ast_log(LOG_NOTICE, "Unable to create channel of type '%s' (cause %d - %s)\n", tech, cause, ast_cause2str(cause));
b684b13b 1524@@ -1065,7 +1084,7 @@
5e69ef1a
MT
1525 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
1526 ast_hangup(tmp->chan);
1527 /* Setup parameters */
1528- tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
1529+ tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause, NULL);
1530 if (!tmp->chan)
1531 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
b684b13b
MT
1532 else
1533@@ -1178,7 +1197,7 @@
1534
1535 if (outgoing) {
1536 /* Our status will at least be NOANSWER */
1537- strcpy(status, "NOANSWER");
1538+ ast_copy_string(status, "NOANSWER", sizeof(status));
1539 if (ast_test_flag(outgoing, OPT_MUSICBACK)) {
1540 moh=1;
1541 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK]);
1542@@ -1186,8 +1205,11 @@
5e69ef1a
MT
1543 ast_indicate(chan, AST_CONTROL_RINGING);
1544 sentringing++;
1545 }
1546- } else
b684b13b 1547- strcpy(status, "CHANUNAVAIL");
5e69ef1a 1548+ } else {
b684b13b 1549+ ast_copy_string(status, "CHANUNAVAIL", sizeof(status));
5e69ef1a
MT
1550+ /* See if there is a special message */
1551+ ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
1552+ }
1553
1554 time(&start_time);
1555 peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, ast_test_flag(&opts, OPT_PRIORITY_JUMP), &result);
b684b13b 1556@@ -1599,7 +1621,15 @@
5f892677
MT
1557 }
1558 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
1559 pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
1560-
1561+
1562+ /* forward AOC-E units from peer, if possible */
b684b13b 1563+/* aoceunits = pbx_builtin_getvar_helper(peer, "AOCEUNITS");
5f892677
MT
1564+
1565+ if (aoceunits) {
1566+ snprintf(toast, sizeof(toast), "%d", atoi(aoceunits));
5f892677 1567+ pbx_builtin_setvar_helper(chan, "AOCEUNITS", toast);
b684b13b 1568+ } */
5f892677
MT
1569+
1570 if (res != AST_PBX_NO_HANGUP_PEER) {
1571 if (!chan->_softhangup)
1572 chan->hangupcause = peer->hangupcause;
b684b13b
MT
1573diff -urN asterisk-1.2.9.1.orig/apps/app_directed_pickup.c asterisk-1.2.9.1/apps/app_directed_pickup.c
1574--- asterisk-1.2.9.1.orig/apps/app_directed_pickup.c 2006-04-06 19:00:10.000000000 +0200
1575+++ asterisk-1.2.9.1/apps/app_directed_pickup.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
1576@@ -41,7 +41,7 @@
1577 #include "asterisk/app.h"
1578
1579 static const char *tdesc = "Directed Call Pickup Application";
1580-static const char *app = "Pickup";
1581+static const char *app = "DPickup";
1582 static const char *synopsis = "Directed Call Pickup";
1583 static const char *descrip =
1584 " Pickup(extension[@context]): This application can pickup any ringing channel\n"
b684b13b
MT
1585diff -urN asterisk-1.2.9.1.orig/apps/app_meetme.c asterisk-1.2.9.1/apps/app_meetme.c
1586--- asterisk-1.2.9.1.orig/apps/app_meetme.c 2006-05-25 22:03:11.000000000 +0200
1587+++ asterisk-1.2.9.1/apps/app_meetme.c 2006-06-09 10:25:04.000000000 +0200
1588@@ -453,7 +453,7 @@
5e69ef1a
MT
1589 ast_copy_string(cnf->pin, pin, sizeof(cnf->pin));
1590 ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin));
1591 cnf->markedusers = 0;
1592- cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo", NULL);
1593+ cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo", NULL, NULL);
1594 if (cnf->chan) {
1595 cnf->fd = cnf->chan->fds[0]; /* for use by conf_play() */
1596 } else {
b684b13b 1597@@ -823,8 +823,9 @@
5e69ef1a
MT
1598 char exitcontext[AST_MAX_CONTEXT] = "";
1599 char recordingtmp[AST_MAX_EXTENSION] = "";
1600 int dtmf;
1601+ int dyna_buff = CONF_SIZE;
1602 ZT_BUFFERINFO bi;
1603- char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
1604+ char __buf[ZT_MAX_BUF_SPACE / ZT_DEFAULT_NUM_BUFS + AST_FRIENDLY_OFFSET];
1605 char *buf = __buf + AST_FRIENDLY_OFFSET;
1606
1607 if (!user) {
b684b13b 1608@@ -990,7 +991,7 @@
5e69ef1a
MT
1609 }
1610 /* Setup buffering information */
1611 memset(&bi, 0, sizeof(bi));
1612- bi.bufsize = CONF_SIZE/2;
1613+ bi.bufsize = dyna_buff / 2;
1614 bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
1615 bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
1616 bi.numbufs = audio_buffers;
b684b13b 1617@@ -1275,6 +1276,14 @@
5e69ef1a
MT
1618 f = ast_read(c);
1619 if (!f)
1620 break;
1621+ if (f->datalen && f->datalen != dyna_buff) {
1622+ ast_log(LOG_NOTICE, "Audio bytes: %d Buffer size: %d\n", f->datalen, dyna_buff);
1623+ if (f->datalen < ZT_MAX_BUF_SPACE/audio_buffers) { /* skip too large frame to avoid overflow */
1624+ dyna_buff = f->datalen;
1625+ close(fd);
1626+ goto zapretry;
1627+ }
1628+ }
1629 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) {
1630 if (user->talk.actual)
1631 ast_frame_adjust_volume(f, user->talk.actual);
b684b13b 1632@@ -1506,7 +1515,7 @@
5e69ef1a
MT
1633 }
1634 ast_frfree(f);
1635 } else if (outfd > -1) {
1636- res = read(outfd, buf, CONF_SIZE);
1637+ res = read(outfd, buf, dyna_buff);
1638 if (res > 0) {
1639 memset(&fr, 0, sizeof(fr));
1640 fr.frametype = AST_FRAME_VOICE;
b684b13b
MT
1641diff -urN asterisk-1.2.9.1.orig/apps/app_milliwatt.c asterisk-1.2.9.1/apps/app_milliwatt.c
1642--- asterisk-1.2.9.1.orig/apps/app_milliwatt.c 2006-01-19 05:17:45.000000000 +0100
1643+++ asterisk-1.2.9.1/apps/app_milliwatt.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
1644@@ -74,20 +74,28 @@
1645 {
1646 struct ast_frame wf;
1647 unsigned char buf[AST_FRIENDLY_OFFSET + 640];
1648+ const int maxsamples = (sizeof (buf) - AST_FRIENDLY_OFFSET) / sizeof (buf[0]);
1649 int i,*indexp = (int *) data;
1650
1651- if (len + AST_FRIENDLY_OFFSET > sizeof(buf))
1652- {
1653- ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",(int)(sizeof(buf) - AST_FRIENDLY_OFFSET),len);
1654- len = sizeof(buf) - AST_FRIENDLY_OFFSET;
1655- }
1656+ /* Instead of len, use samples, because channel.c generator_force
1657+ * generate(chan, tmp, 0, 160) ignores len. In any case, len is
1658+ * a multiple of samples, given by number of samples times bytes per
1659+ * sample. In the case of ulaw, len = samples. for signed linear
1660+ * len = 2 * samples */
1661+
1662+ if (samples > maxsamples)
1663+ {
1664+ ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n", maxsamples, samples);
1665+ samples = maxsamples;
1666+ }
1667+ len = samples * sizeof (buf[0]);
1668 wf.frametype = AST_FRAME_VOICE;
1669 wf.subclass = AST_FORMAT_ULAW;
1670 wf.offset = AST_FRIENDLY_OFFSET;
1671 wf.mallocd = 0;
1672 wf.data = buf + AST_FRIENDLY_OFFSET;
1673 wf.datalen = len;
1674- wf.samples = wf.datalen;
1675+ wf.samples = samples;
1676 wf.src = "app_milliwatt";
1677 wf.delivery.tv_sec = 0;
1678 wf.delivery.tv_usec = 0;
b684b13b
MT
1679diff -urN asterisk-1.2.9.1.orig/apps/app_page.c asterisk-1.2.9.1/apps/app_page.c
1680--- asterisk-1.2.9.1.orig/apps/app_page.c 2006-04-13 19:40:21.000000000 +0200
1681+++ asterisk-1.2.9.1/apps/app_page.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
1682@@ -85,7 +85,7 @@
1683 {
1684 struct calloutdata *cd = data;
1685 ast_pbx_outgoing_app(cd->tech, AST_FORMAT_SLINEAR, cd->resource, 30000,
5f892677
MT
1686- "MeetMe", cd->meetmeopts, NULL, 0, cd->cidnum, cd->cidname, cd->variables, NULL, NULL);
1687+ "MeetMe", cd->meetmeopts, NULL, 0, 0, cd->cidnum, cd->cidname, cd->variables, NULL, NULL, NULL);
5e69ef1a
MT
1688 free(cd);
1689 return NULL;
1690 }
b684b13b
MT
1691diff -urN asterisk-1.2.9.1.orig/apps/app_parkandannounce.c asterisk-1.2.9.1/apps/app_parkandannounce.c
1692--- asterisk-1.2.9.1.orig/apps/app_parkandannounce.c 2005-11-29 19:24:39.000000000 +0100
1693+++ asterisk-1.2.9.1/apps/app_parkandannounce.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
1694@@ -183,7 +183,7 @@
1695
1696 memset(&oh, 0, sizeof(oh));
1697 oh.parent_channel = chan;
1698- dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->cid.cid_num, chan->cid.cid_name, &oh);
1699+ dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, 0, chan->cid.cid_num, chan->cid.cid_name, &oh, NULL);
1700
1701 if(dchan) {
1702 if(dchan->_state == AST_STATE_UP) {
b684b13b
MT
1703diff -urN asterisk-1.2.9.1.orig/apps/app_pickup.c asterisk-1.2.9.1/apps/app_pickup.c
1704--- asterisk-1.2.9.1.orig/apps/app_pickup.c 1970-01-01 01:00:00.000000000 +0100
1705+++ asterisk-1.2.9.1/apps/app_pickup.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
1706@@ -0,0 +1,319 @@
1707+/*
1708+ * Asterisk -- A telephony toolkit for Linux.
1709+ *
1710+ * Pickup, channel independent call pickup
1711+ *
1712+ * Copyright (C) 2004, Junghanns.NET GmbH
1713+ *
1714+ * Klaus-Peter Junghanns <kpj@junghanns.net>
1715+ *
1716+ * Copyright (C) 2004, Florian Overkamp <florian@obsimref.com>
1717+ *
1718+ * This program is free software, distributed under the terms of
1719+ * the GNU General Public License
1720+ */
1721+
1722+#include <stdlib.h>
1723+#include <unistd.h>
1724+#include <string.h>
1725+#include <stdio.h>
1726+#include <signal.h>
1727+#include <pthread.h>
1728+#include <asterisk/lock.h>
1729+#include <asterisk/file.h>
1730+#include <asterisk/logger.h>
1731+#include <asterisk/channel.h>
1732+#include <asterisk/pbx.h>
1733+#include <asterisk/module.h>
1734+#include <asterisk/features.h>
1735+#include <asterisk/options.h>
1736+
1737+
1738+static char *tdesc = "PickUp/PickDown/Steal/PickupChan/StealChan";
1739+
1740+static char *app = "PickUp";
1741+
1742+static char *synopsis = "Channel independent call pickup.";
1743+
1744+static char *descrip =
1745+" PickDown([group]): Tries to pickup the first ringing channel with callgroup == group.\n"
1746+" If called without the group argument, the pickupgroup of the channel will be used.\n";
1747+
1748+static char *app2 = "Steal";
1749+
1750+static char *synopsis2 = "Channel independent call stealing. Just like pickup but for answered channels.";
1751+
1752+static char *descrip2 =
1753+" Steal([group]): Tries to steal the first bridged channel with callgroup == group.\n"
1754+" If called without the group argument, the pickupgroup of the channel will be used.\n";
1755+
1756+static char *app3 = "PickDown";
1757+
1758+static char *synopsis3 = "Channel independent call pickdown.";
1759+
1760+static char *descrip3 =
1761+" PickDown([group]): Tries to hangup the first ringing channel with callgroup == group.\n"
1762+" If called without the group argument, the pickupgroup of the channel will be used.\n";
1763+
1764+static char *app4 = "PickupChan";
1765+
1766+static char *synopsis4 = "Channel independent call pickup.";
1767+
1768+static char *descrip4 =
1769+" PickupChan(Technology/resource[&Technology2/resource2...]): Tries to pickup the first ringing channel in the parameter list.\n";
1770+
1771+static char *app5 = "StealChan";
1772+
1773+static char *synopsis5 = "Channel independent call stealing. Just like pickup but for answered channels.";
1774+
1775+static char *descrip5 =
1776+" StealChan(Technology/resource[&Technology2/resource2...]): Tries to steal the first ringing channel in the parameter list.\n";
1777+
1778+STANDARD_LOCAL_USER;
1779+
1780+LOCAL_USER_DECL;
1781+
1782+static int my_pickup_call(struct ast_channel *chan, unsigned int pickupgroup, int chanstate, int bridge) {
1783+ struct ast_channel *cur;
1784+ int res = -1;
1785+ cur = ast_channel_walk_locked(NULL);
1786+ while(cur) {
1787+ if ((cur != chan) &&
1788+ (pickupgroup & cur->callgroup) &&
1789+ (cur->_state == chanstate)) {
1790+ break;
1791+ }
1792+ ast_mutex_unlock(&cur->lock);
1793+ cur = ast_channel_walk_locked(cur);
1794+ }
1795+ if (cur) {
1796+ if(option_verbose > 2) {
1797+ if (chanstate == AST_STATE_RINGING) {
1798+ if (bridge == 1) {
1799+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
1800+ } else {
1801+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
1802+ }
1803+ } else {
1804+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
1805+ }
1806+ }
1807+ if (bridge == 1) {
1808+ if (chan->_state != AST_STATE_UP) {
1809+ ast_answer(chan);
1810+ }
1811+ if (ast_channel_masquerade(cur, chan)) {
1812+ ast_log(LOG_ERROR, "unable to masquerade\n");
1813+ }
1814+ ast_mutex_unlock(&cur->lock);
1815+ ast_mutex_unlock(&chan->lock);
1816+ } else {
1817+ cur->_softhangup = AST_SOFTHANGUP_DEV;
1818+ ast_mutex_unlock(&cur->lock);
1819+ }
1820+ } else {
1821+ if(option_verbose > 2) {
1822+ ast_verbose(VERBOSE_PREFIX_3 "No channel found %d.\n",pickupgroup);
1823+ }
1824+ }
1825+ return res;
1826+}
1827+
1828+static int my_pickup_channel(struct ast_channel *chan, void *data, int chanstate, int bridge) {
1829+ struct ast_channel *cur;
1830+ char channels[256];
1831+ char evalchan[256];
1832+ char *endptr;
1833+ int res = -1;
1834+ cur = ast_channel_walk_locked(NULL);
1835+ strncpy(channels, (char *)data, sizeof(channels) - 1);
1836+ while(cur) {
1837+ if ((cur != chan) &&
1838+ (cur->_state == chanstate)) {
1839+ /* This call is a candidate (correct ringstate and not ourselves), now check if the channel is in our list */
1840+ strncpy(evalchan, (char *)cur->name, sizeof(evalchan) - 1);
1841+ /* strip the subchannel tag */
1842+ endptr = strrchr(evalchan, '-');
1843+ if(endptr) {
1844+ *endptr = '\0';
1845+ }
1846+ endptr = strrchr(evalchan, '/');
1847+ if(endptr) {
1848+ *endptr = '\0';
1849+ }
1850+ /* check for each of the members if they match (probably a stristr will do ?) */
1851+ /* if we match the code, break */
1852+ if(strstr(channels, evalchan) != NULL) {
1853+ ast_verbose(VERBOSE_PREFIX_1 "Nice channel, I'll take it: %s\n",evalchan);
1854+ break;
1855+ }
1856+ }
1857+ ast_mutex_unlock(&cur->lock);
1858+ cur = ast_channel_walk_locked(cur);
1859+ }
1860+ if (cur) {
1861+ if(option_verbose > 2) {
1862+ if (chanstate == AST_STATE_RINGING) {
1863+ if (bridge == 1) {
1864+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
1865+ } else {
1866+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
1867+ }
1868+ } else {
1869+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
1870+ }
1871+ }
1872+ if (bridge == 1) {
1873+ if (chan->_state != AST_STATE_UP) {
1874+ ast_answer(chan);
1875+ }
1876+ if (ast_channel_masquerade(cur, chan)) {
1877+ ast_log(LOG_ERROR, "unable to masquerade\n");
1878+ }
1879+ ast_mutex_unlock(&cur->lock);
1880+ ast_mutex_unlock(&chan->lock);
1881+ } else {
1882+ cur->_softhangup = AST_SOFTHANGUP_DEV;
1883+ ast_mutex_unlock(&cur->lock);
1884+ }
1885+ } else {
1886+ if(option_verbose > 2) {
1887+ ast_verbose(VERBOSE_PREFIX_3 "No channel found %s.\n",channels);
1888+ }
1889+ }
1890+ return res;
1891+}
1892+
1893+
1894+static int pickup_exec(struct ast_channel *chan, void *data)
1895+{
1896+ int res=0;
1897+ unsigned int pickupgroup=0;
1898+ struct localuser *u;
1899+ if (!data || !strlen(data)) {
1900+ pickupgroup = chan->pickupgroup;
1901+ } else {
1902+ pickupgroup = ast_get_group(data);
1903+ }
1904+ LOCAL_USER_ADD(u);
1905+ if (!res) {
1906+ res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 1);
1907+ }
1908+ if (res > 0)
1909+ res = 0;
1910+ LOCAL_USER_REMOVE(u);
1911+ return res;
1912+}
1913+
1914+static int steal_exec(struct ast_channel *chan, void *data)
1915+{
1916+ int res=0;
1917+ unsigned int pickupgroup=0;
1918+ struct localuser *u;
1919+ if (!data || !strlen(data)) {
1920+ pickupgroup = chan->pickupgroup;
1921+ } else {
1922+ pickupgroup = ast_get_group(data);
1923+ }
1924+ LOCAL_USER_ADD(u);
1925+ if (!res) {
1926+ res = my_pickup_call(chan, pickupgroup, AST_STATE_UP, 1);
1927+ }
1928+ if (res > 0)
1929+ res = 0;
1930+ LOCAL_USER_REMOVE(u);
1931+ return res;
1932+}
1933+
1934+static int pickdown_exec(struct ast_channel *chan, void *data)
1935+{
1936+ int res=0;
1937+ unsigned int pickupgroup=0;
1938+ struct localuser *u;
1939+ if (!data || !strlen(data)) {
1940+ pickupgroup = chan->pickupgroup;
1941+ } else {
1942+ pickupgroup = ast_get_group(data);
1943+ }
1944+ LOCAL_USER_ADD(u);
1945+ if (!res) {
1946+ res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 0);
1947+ }
1948+ if (res > 0)
1949+ res = 0;
1950+ LOCAL_USER_REMOVE(u);
1951+ return res;
1952+}
1953+
1954+static int pickupchan_exec(struct ast_channel *chan, void *data) {
1955+ int res=0;
1956+ struct localuser *u;
1957+ if (!data) {
1958+ ast_log(LOG_WARNING, "PickupChan requires an argument (technology1/number1&technology2/number2...)\n");
1959+ return -1;
1960+ }
1961+ LOCAL_USER_ADD(u);
1962+ if (!res) {
1963+ res = my_pickup_channel(chan, data, AST_STATE_RINGING, 1);
1964+ }
1965+ if (res > 0)
1966+ res = 0;
1967+ LOCAL_USER_REMOVE(u);
1968+ return res;
1969+}
1970+
1971+static int stealchan_exec(struct ast_channel *chan, void *data)
1972+{
1973+ int res=0;
1974+ struct localuser *u;
1975+ if (!data) {
1976+ ast_log(LOG_WARNING, "StealChan requires an argument (technology1/number1&technology2/number2...)\n");
1977+ return -1;
1978+ }
1979+
1980+ LOCAL_USER_ADD(u);
1981+ if (!res) {
1982+ res = my_pickup_channel(chan, data, AST_STATE_UP, 1);
1983+ }
1984+ if (res > 0)
1985+ res = 0;
1986+ LOCAL_USER_REMOVE(u);
1987+ return res;
1988+}
1989+
1990+
1991+int unload_module(void)
1992+{
1993+ STANDARD_HANGUP_LOCALUSERS;
1994+ ast_unregister_application(app5);
1995+ ast_unregister_application(app4);
1996+ ast_unregister_application(app3);
1997+ ast_unregister_application(app2);
1998+ return ast_unregister_application(app);
1999+}
2000+
2001+int load_module(void)
2002+{
2003+ ast_register_application(app5, stealchan_exec, synopsis5, descrip5);
2004+ ast_register_application(app4, pickupchan_exec, synopsis4, descrip4);
2005+ ast_register_application(app3, pickdown_exec, synopsis3, descrip3);
2006+ ast_register_application(app2, steal_exec, synopsis2, descrip2);
2007+ return ast_register_application(app, pickup_exec, synopsis, descrip);
2008+}
2009+
2010+char *description(void)
2011+{
2012+ return tdesc;
2013+}
2014+
2015+int usecount(void)
2016+{
2017+ int res;
2018+ STANDARD_USECOUNT(res);
2019+ return res;
2020+}
2021+
2022+char *key()
2023+{
2024+ return ASTERISK_GPL_KEY;
2025+}
b684b13b
MT
2026diff -urN asterisk-1.2.9.1.orig/apps/app_queue.c asterisk-1.2.9.1/apps/app_queue.c
2027--- asterisk-1.2.9.1.orig/apps/app_queue.c 2006-06-04 05:43:35.000000000 +0200
2028+++ asterisk-1.2.9.1/apps/app_queue.c 2006-06-09 10:25:04.000000000 +0200
2029@@ -526,7 +526,7 @@
5e69ef1a
MT
2030 return NULL;
2031 }
2032
2033-static int statechange_queue(const char *dev, int state, void *ign)
2034+static int statechange_queue(const char *dev, int state, void *ign, char *cid_num, char *cid_name)
2035 {
2036 /* Avoid potential for deadlocks by spawning a new thread to handle
2037 the event */
b684b13b 2038@@ -1512,7 +1512,7 @@
5e69ef1a
MT
2039 location = "";
2040
2041 /* Request the peer */
2042- tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status);
2043+ tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status, NULL);
2044 if (!tmp->chan) { /* If we can't, just go on to the next call */
2045 #if 0
2046 ast_log(LOG_NOTICE, "Unable to create channel of type '%s' for Queue\n", cur->tech);
b684b13b 2047@@ -1819,7 +1819,7 @@
5e69ef1a
MT
2048 if (option_verbose > 2)
2049 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
2050 /* Setup parameters */
2051- o->chan = ast_request(tech, in->nativeformats, stuff, &status);
2052+ o->chan = ast_request(tech, in->nativeformats, stuff, &status, NULL);
2053 if (status != o->oldstatus)
2054 update_dial_status(qe->parent, o->member, status);
2055 if (!o->chan) {
b684b13b
MT
2056@@ -2363,14 +2363,14 @@
2057 else
2058 which = peer;
2059 if (monitorfilename)
2060- ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1 );
2061+ ast_monitor_start(which, qe->parent->monfmt, monitorfilename, NULL, NULL, 1 );
2062 else if (qe->chan->cdr)
2063- ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1 );
2064+ ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, NULL, NULL, 1 );
2065 else {
2066 /* Last ditch effort -- no CDR, make up something */
2067 char tmpid[256];
2068 snprintf(tmpid, sizeof(tmpid), "chan-%x", rand());
2069- ast_monitor_start(which, qe->parent->monfmt, tmpid, 1 );
2070+ ast_monitor_start(which, qe->parent->monfmt, tmpid, NULL, NULL, 1 );
2071 }
2072 if (qe->parent->monjoin)
2073 ast_monitor_setjoinfiles(which, 1);
2074diff -urN asterisk-1.2.9.1.orig/apps/app_readfile.c asterisk-1.2.9.1/apps/app_readfile.c
2075--- asterisk-1.2.9.1.orig/apps/app_readfile.c 2006-03-23 21:13:48.000000000 +0100
2076+++ asterisk-1.2.9.1/apps/app_readfile.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
2077@@ -40,7 +40,7 @@
2078 #include "asterisk/app.h"
2079 #include "asterisk/module.h"
2080
2081-static char *tdesc = "Stores output of file into a variable";
2082+static char *tdesc = "Stores content of file into a variable";
2083
2084 static char *app_readfile = "ReadFile";
2085
b684b13b
MT
2086diff -urN asterisk-1.2.9.1.orig/apps/app_segfault.c asterisk-1.2.9.1/apps/app_segfault.c
2087--- asterisk-1.2.9.1.orig/apps/app_segfault.c 1970-01-01 01:00:00.000000000 +0100
2088+++ asterisk-1.2.9.1/apps/app_segfault.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
2089@@ -0,0 +1,75 @@
2090+/*
2091+ * Segfault application
2092+ *
2093+ * An application to provoke a segmentation fault from the dialplan.
2094+ * (I know what you are thinking now...., but since Asterisk is too stable...
2095+ * I needed something to test my failover switches.)
2096+ *
2097+ * Copyright (C) 2005 Junghanns.NET GmbH
2098+ * Klaus-Peter Junghanns <kpj@junghanns.net>
2099+ *
2100+ * This program is free software, distributed under the terms of
2101+ * the GNU General Public License. THIS APPLICATION _WILL_ CRASH YOUR
2102+ * ASTERISK SERVER SO OF COURSE THERE IS NOT LIABILITY FOR NOTHING!
2103+ */
2104+
2105+#include <stdlib.h>
2106+#include <unistd.h>
2107+#include <string.h>
2108+#include <stdio.h>
2109+#include <asterisk/lock.h>
2110+#include <asterisk/file.h>
2111+#include <asterisk/logger.h>
2112+#include <asterisk/channel.h>
2113+#include <asterisk/pbx.h>
2114+#include <asterisk/module.h>
2115+
2116+static char *tdesc = "Application for crashing Asterisk with a segmentation fault";
2117+
2118+static char *app = "Segfault";
2119+
2120+static char *synopsis = "This application will crash Asterisk with a segmentation fault.";
2121+
2122+static char *descrip =
2123+" Segfault(): Crash with a segfault. Never returns nufin.\n";
2124+
2125+STANDARD_LOCAL_USER;
2126+
2127+LOCAL_USER_DECL;
2128+
2129+static int segfault_exec(struct ast_channel *chan, void *data)
2130+{
2131+ struct localuser *u;
2132+ LOCAL_USER_ADD(u);
2133+ ((char *)0)[0] = 0;
2134+ LOCAL_USER_REMOVE(u);
2135+ return 0;
2136+}
2137+
2138+int unload_module(void)
2139+{
2140+ STANDARD_HANGUP_LOCALUSERS;
2141+ return ast_unregister_application(app);
2142+}
2143+
2144+int load_module(void)
2145+{
2146+ return ast_register_application(app, segfault_exec, synopsis, descrip);
2147+}
2148+
2149+char *description(void)
2150+{
2151+ return tdesc;
2152+}
2153+
2154+int usecount(void)
2155+{
2156+ int res;
2157+ STANDARD_USECOUNT(res);
2158+ return res;
2159+}
2160+
2161+char *key()
2162+{
2163+ return ASTERISK_GPL_KEY;
2164+}
b684b13b
MT
2165diff -urN asterisk-1.2.9.1.orig/apps/app_zapras.c asterisk-1.2.9.1/apps/app_zapras.c
2166--- asterisk-1.2.9.1.orig/apps/app_zapras.c 2006-05-01 22:44:24.000000000 +0200
2167+++ asterisk-1.2.9.1/apps/app_zapras.c 2006-06-09 10:25:04.000000000 +0200
2168@@ -186,7 +186,7 @@
5e69ef1a
MT
2169 }
2170 }
2171 /* Throw back into audio mode */
2172- x = 1;
2173+ x = 0;
2174 ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
2175
2176 /* Restore saved values */
b684b13b
MT
2177diff -urN asterisk-1.2.9.1.orig/asterisk.c asterisk-1.2.9.1/asterisk.c
2178--- asterisk-1.2.9.1.orig/asterisk.c 2006-05-19 21:01:17.000000000 +0200
2179+++ asterisk-1.2.9.1/asterisk.c 2006-06-13 10:10:50.000000000 +0200
5f892677 2180@@ -228,6 +228,7 @@
5e69ef1a
MT
2181 char ast_config_AST_CTL_OWNER[AST_CONFIG_MAX_PATH] = "\0";
2182 char ast_config_AST_CTL_GROUP[AST_CONFIG_MAX_PATH] = "\0";
2183 char ast_config_AST_CTL[AST_CONFIG_MAX_PATH] = "asterisk.ctl";
2184+char ast_config_AST_SYMBOLIC_NAME[20];
2185
2186 static char *_argv[256];
2187 static int shuttingdown = 0;
b684b13b 2188@@ -1893,6 +1894,7 @@
5e69ef1a
MT
2189 ast_copy_string(ast_config_AST_PID, AST_PID, sizeof(ast_config_AST_PID));
2190 ast_copy_string(ast_config_AST_SOCKET, AST_SOCKET, sizeof(ast_config_AST_SOCKET));
2191 ast_copy_string(ast_config_AST_RUN_DIR, AST_RUN_DIR, sizeof(ast_config_AST_RUN_DIR));
2192+ ast_copy_string(ast_config_AST_SYMBOLIC_NAME, AST_SYMBOLIC_NAME, sizeof(ast_config_AST_SYMBOLIC_NAME));
2193
2194 /* no asterisk.conf? no problem, use buildtime config! */
2195 if (!cfg) {
b684b13b
MT
2196@@ -2007,6 +2009,8 @@
2197 /* What group to run as */
2198 } else if (!strcasecmp(v->name, "rungroup")) {
2199 ast_copy_string(ast_config_AST_RUN_GROUP, v->value, sizeof(ast_config_AST_RUN_GROUP));
5e69ef1a
MT
2200+ } else if (!strcasecmp(v->name, "uniquename")) {
2201+ strncpy(ast_config_AST_SYMBOLIC_NAME,v->value,sizeof(ast_config_AST_SYMBOLIC_NAME));
2202 }
2203 v = v->next;
2204 }
b684b13b
MT
2205diff -urN asterisk-1.2.9.1.orig/build_tools/make_defaults_h asterisk-1.2.9.1/build_tools/make_defaults_h
2206--- asterisk-1.2.9.1.orig/build_tools/make_defaults_h 2005-06-20 19:26:08.000000000 +0200
2207+++ asterisk-1.2.9.1/build_tools/make_defaults_h 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
2208@@ -16,6 +16,7 @@
2209 #define AST_KEY_DIR "${INSTALL_PATH}${ASTVARLIBDIR}/keys"
2210 #define AST_DB "${INSTALL_PATH}${ASTVARLIBDIR}/astdb"
2211 #define AST_TMP_DIR "${INSTALL_PATH}${ASTSPOOLDIR}/tmp"
2212+#define AST_SYMBOLIC_NAME "asterisk"
2213
2214 #define AST_CONFIG_FILE "${INSTALL_PATH}${ASTCONFPATH}"
2215
b684b13b
MT
2216diff -urN asterisk-1.2.9.1.orig/channel.c asterisk-1.2.9.1/channel.c
2217--- asterisk-1.2.9.1.orig/channel.c 2006-06-01 22:27:50.000000000 +0200
2218+++ asterisk-1.2.9.1/channel.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
2219@@ -94,8 +94,8 @@
2220 */
2221 static int shutting_down = 0;
2222
2223-AST_MUTEX_DEFINE_STATIC(uniquelock);
2224 static int uniqueint = 0;
2225+AST_MUTEX_DEFINE_EXPORTED(uniquelock);
2226
2227 unsigned long global_fin = 0, global_fout = 0;
2228
2229@@ -512,6 +512,17 @@
2230 .description = "Null channel (should not see this)",
2231 };
2232
2233+char *ast_alloc_uniqueid(void) {
2234+ char *uniqueid;
2235+ uniqueid = malloc(64);
2236+ if (!uniqueid) return NULL;
2237+ ast_mutex_lock(&uniquelock);
2238+ snprintf(uniqueid, 63, "%s-%d-%li.%d", ast_config_AST_SYMBOLIC_NAME, ast_mainpid, (long)time(NULL), uniqueint++);
2239+ ast_mutex_unlock(&uniquelock);
2240+ return uniqueid;
2241+}
2242+
2243+
2244 /*--- ast_channel_alloc: Create a new channel structure */
2245 struct ast_channel *ast_channel_alloc(int needqueue)
2246 {
2247@@ -519,6 +530,7 @@
2248 int x;
2249 int flags;
2250 struct varshead *headp;
2251+ char *tmpuniqueid;
2252
2253
2254 /* If shutting down, don't allocate any new channels */
2255@@ -584,9 +596,12 @@
2256 tmp->data = NULL;
2257 tmp->fin = global_fin;
2258 tmp->fout = global_fout;
2259- ast_mutex_lock(&uniquelock);
2260- snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), "%li.%d", (long) time(NULL), uniqueint++);
2261- ast_mutex_unlock(&uniquelock);
2262+ tmpuniqueid = ast_alloc_uniqueid();
2263+ snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), tmpuniqueid);
2264+ if (tmpuniqueid) {
2265+ free(tmpuniqueid);
2266+ tmpuniqueid = NULL;
2267+ }
2268 headp = &tmp->varshead;
2269 ast_mutex_init(&tmp->lock);
2270 AST_LIST_HEAD_INIT_NOLOCK(headp);
2271@@ -729,7 +744,7 @@
2272 */
2273 static struct ast_channel *channel_find_locked(const struct ast_channel *prev,
2274 const char *name, const int namelen,
2275- const char *context, const char *exten)
2276+ const char *context, const char *exten, const char *uniqueid)
2277 {
2278 const char *msg = prev ? "deadlock" : "initial deadlock";
2279 int retries, done;
2280@@ -740,9 +755,14 @@
2281 for (c = channels; c; c = c->next) {
2282 if (!prev) {
2283 /* want head of list */
2284- if (!name && !exten)
2285+ if (!name && !exten && !uniqueid)
2286 break;
2287- if (name) {
2288+ if (uniqueid) {
2289+ if (!strcasecmp(c->uniqueid, uniqueid))
2290+ break;
2291+ else
2292+ continue;
2293+ } else if (name) {
2294 /* want match by full name */
2295 if (!namelen) {
2296 if (!strcasecmp(c->name, name))
2297@@ -793,33 +813,39 @@
2298 /*--- ast_channel_walk_locked: Browse channels in use */
2299 struct ast_channel *ast_channel_walk_locked(const struct ast_channel *prev)
2300 {
2301- return channel_find_locked(prev, NULL, 0, NULL, NULL);
2302+ return channel_find_locked(prev, NULL, 0, NULL, NULL, NULL);
2303 }
2304
2305 /*--- ast_get_channel_by_name_locked: Get channel by name and lock it */
2306 struct ast_channel *ast_get_channel_by_name_locked(const char *name)
2307 {
2308- return channel_find_locked(NULL, name, 0, NULL, NULL);
2309+ return channel_find_locked(NULL, name, 0, NULL, NULL, NULL);
2310 }
2311
2312 /*--- ast_get_channel_by_name_prefix_locked: Get channel by name prefix and lock it */
2313 struct ast_channel *ast_get_channel_by_name_prefix_locked(const char *name, const int namelen)
2314 {
2315- return channel_find_locked(NULL, name, namelen, NULL, NULL);
2316+ return channel_find_locked(NULL, name, namelen, NULL, NULL, NULL);
2317 }
2318
2319 /*--- ast_walk_channel_by_name_prefix_locked: Get next channel by name prefix and lock it */
2320 struct ast_channel *ast_walk_channel_by_name_prefix_locked(struct ast_channel *chan, const char *name, const int namelen)
2321 {
2322- return channel_find_locked(chan, name, namelen, NULL, NULL);
2323+ return channel_find_locked(chan, name, namelen, NULL, NULL, NULL);
2324 }
2325
2326 /*--- ast_get_channel_by_exten_locked: Get channel by exten (and optionally context) and lock it */
2327 struct ast_channel *ast_get_channel_by_exten_locked(const char *exten, const char *context)
2328 {
2329- return channel_find_locked(NULL, NULL, 0, context, exten);
2330+ return channel_find_locked(NULL, NULL, 0, context, exten, NULL);
2331 }
2332
2333+struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid)
2334+{
2335+ return channel_find_locked(NULL, NULL, 0, NULL, NULL, uniqueid);
2336+}
2337+
2338+
2339 /*--- ast_safe_sleep_conditional: Wait, look for hangups and condition arg */
2340 int ast_safe_sleep_conditional( struct ast_channel *chan, int ms,
2341 int (*cond)(void*), void *data )
2342@@ -912,8 +938,10 @@
2343 free(chan->tech_pvt);
2344 }
2345
2346- if (chan->sched)
2347- sched_context_destroy(chan->sched);
2348+ if (chan->sched) {
2349+ sched_context_destroy(chan->sched);
2350+ chan->sched = NULL;
2351+ }
2352
2353 ast_copy_string(name, chan->name, sizeof(name));
2354
2355@@ -956,10 +984,11 @@
2356 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries)))
2357 ast_var_delete(vardata);
2358
2359+
2360 free(chan);
2361 ast_mutex_unlock(&chlock);
2362
2363- ast_device_state_changed_literal(name);
2364+ ast_device_state_changed_literal(name, NULL, NULL);
2365 }
2366
2367 int ast_channel_spy_add(struct ast_channel *chan, struct ast_channel_spy *spy)
b684b13b 2368@@ -2364,7 +2393,7 @@
5e69ef1a
MT
2369 &chan->writetrans, 1);
2370 }
2371
2372-struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, struct outgoing_helper *oh)
2373+struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, int callingpres, const char *cid_num, const char *cid_name, struct outgoing_helper *oh, char* uniqueid)
2374 {
2375 int state = 0;
2376 int cause = 0;
b684b13b 2377@@ -2372,7 +2401,7 @@
5e69ef1a
MT
2378 struct ast_frame *f;
2379 int res = 0;
2380
2381- chan = ast_request(type, format, data, &cause);
2382+ chan = ast_request(type, format, data, &cause, uniqueid);
2383 if (chan) {
2384 if (oh) {
2385 if (oh->vars)
b684b13b 2386@@ -2386,6 +2415,7 @@
5e69ef1a
MT
2387 }
2388 ast_set_callerid(chan, cid_num, cid_name, cid_num);
2389
2390+ chan->cid.cid_pres = callingpres;
2391 if (!ast_call(chan, data, 0)) {
5f892677
MT
2392 res = 1; /* in case chan->_state is already AST_STATE_UP */
2393 while (timeout && (chan->_state != AST_STATE_UP)) {
b684b13b 2394@@ -2409,6 +2439,7 @@
5e69ef1a
MT
2395 if (f->subclass == AST_CONTROL_RINGING)
2396 state = AST_CONTROL_RINGING;
2397 else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
2398+ res = 0;
2399 state = f->subclass;
2400 ast_frfree(f);
2401 break;
b684b13b 2402@@ -2478,12 +2509,12 @@
5e69ef1a
MT
2403 return chan;
2404 }
2405
2406-struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, const char *cidnum, const char *cidname)
2407+struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, int callingpres, const char *cidnum, const char *cidname, char *uniqueid)
2408 {
2409- return __ast_request_and_dial(type, format, data, timeout, outstate, cidnum, cidname, NULL);
2410+ return __ast_request_and_dial(type, format, data, timeout, outstate, 0, cidnum, cidname, NULL, uniqueid);
2411 }
2412
2413-struct ast_channel *ast_request(const char *type, int format, void *data, int *cause)
2414+struct ast_channel *ast_request(const char *type, int format, void *data, int *cause, char *uniqueid)
2415 {
2416 struct chanlist *chan;
2417 struct ast_channel *c;
b684b13b 2418@@ -2520,6 +2551,7 @@
5e69ef1a
MT
2419 if (!(c = chan->tech->requester(type, capabilities, data, cause)))
2420 return NULL;
2421
2422+ if (uniqueid) strncpy(c->uniqueid, uniqueid, sizeof(c->uniqueid));
2423 if (c->_state == AST_STATE_DOWN) {
2424 manager_event(EVENT_FLAG_CALL, "Newchannel",
2425 "Channel: %s\r\n"
b684b13b 2426@@ -2775,6 +2807,29 @@
5e69ef1a
MT
2427 return res;
2428 }
2429
2430+int ast_channel_masquerade_locked(struct ast_channel *original, struct ast_channel *clone)
2431+{
2432+ struct ast_frame null = { AST_FRAME_NULL, };
2433+ int res = -1;
2434+ ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n",
2435+ clone->name, original->name);
2436+ if (original->masq) {
2437+ ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n",
2438+ original->masq->name, original->name);
2439+ } else if (clone->masqr) {
2440+ ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n",
2441+ clone->name, clone->masqr->name);
2442+ } else {
2443+ original->masq = clone;
2444+ clone->masqr = original;
2445+ ast_queue_frame(original, &null);
2446+ ast_queue_frame(clone, &null);
2447+ ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name);
2448+ res = 0;
2449+ }
2450+ return res;
2451+}
2452+
2453 void ast_change_name(struct ast_channel *chan, char *newname)
2454 {
2455 char tmp[256];
b684b13b
MT
2456@@ -2914,7 +2969,7 @@
2457 ast_copy_string(clone->name, masqn, sizeof(clone->name));
2458
2459 /* Notify any managers of the change, first the masq then the other */
2460- manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", newn, masqn, clone->uniqueid);
2461+ manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\nNewUniqueid: %s\r\n", newn, masqn, clone->uniqueid, original->uniqueid);
2462 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", orig, newn, original->uniqueid);
2463
2464 /* Swap the technlogies */
2465@@ -3141,15 +3196,14 @@
5e69ef1a
MT
2466 );
2467 }
2468
2469-int ast_setstate(struct ast_channel *chan, int state)
2470-{
2471+int ast_setstate_and_cid(struct ast_channel *chan, int state, char *cid_num, char *cid_name) {
2472 int oldstate = chan->_state;
2473
2474 if (oldstate == state)
2475 return 0;
2476
2477 chan->_state = state;
2478- ast_device_state_changed_literal(chan->name);
2479+ ast_device_state_changed_literal(chan->name, cid_num, cid_name);
2480 manager_event(EVENT_FLAG_CALL,
2481 (oldstate == AST_STATE_DOWN) ? "Newchannel" : "Newstate",
2482 "Channel: %s\r\n"
b684b13b 2483@@ -3165,6 +3219,10 @@
5e69ef1a
MT
2484 return 0;
2485 }
2486
2487+int ast_setstate(struct ast_channel *chan, int state) {
2488+ return ast_setstate_and_cid(chan, state, NULL, NULL);
2489+}
2490+
2491 /*--- Find bridged channel */
2492 struct ast_channel *ast_bridged_channel(struct ast_channel *chan)
2493 {
b684b13b 2494@@ -3342,6 +3400,7 @@
5e69ef1a
MT
2495 char callee_warning = 0;
2496 int to;
2497
2498+
2499 if (c0->_bridge) {
2500 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n",
2501 c0->name, c0->_bridge->name);
b684b13b 2502@@ -3352,6 +3411,10 @@
5e69ef1a
MT
2503 c1->name, c1->_bridge->name);
2504 return -1;
2505 }
2506+
2507+ if (IS_DIGITAL(c0->transfercapability) || IS_DIGITAL(c1->transfercapability)) {
2508+ config->flags = 0;
2509+ }
2510
2511 /* Stop if we're a zombie or need a soft hangup */
2512 if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) ||
b684b13b
MT
2513diff -urN asterisk-1.2.9.1.orig/channels/Makefile asterisk-1.2.9.1/channels/Makefile
2514--- asterisk-1.2.9.1.orig/channels/Makefile 2006-04-30 16:27:56.000000000 +0200
2515+++ asterisk-1.2.9.1/channels/Makefile 2006-06-09 10:25:04.000000000 +0200
5f892677
MT
2516@@ -102,6 +102,11 @@
2517 ZAPR2=-lmfcr2
2518 endif
2519
2520+ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/lib/libgsmat.so.1)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/lib/libgsmat.so.1),)
2521+ CFLAGS+=-DZAPATA_GSM
2522+ ZAPGSM=-lgsmat
2523+endif
2524+
2525 ALSA_SRC=chan_alsa.c
2526
2527 ifneq ($(wildcard alsa-monitor.h),)
2528@@ -122,6 +127,35 @@
5e69ef1a
MT
2529 endif
2530 endif # WITHOUT_ZAPTEL
2531
2532+ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/capi20.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/capi20.h),)
2533+ CHANNEL_LIBS+=chan_capi.so
2534+# uncomment the following line if you really never ever want early b3 connects,
2535+# you can also configure it in the dialstring, this is just for performance
2536+# NOTE: this is probably obsolete by using the "R" dial option
2537+#CFLAGS+=-DCAPI_NEVER_EVER_EARLY_B3_CONNECTS
2538+
2539+# uncommnet next line to force dtmf software detection/generation, can also be configured
2540+# in capi.conf on a perdevice basis (softdtmf=1)
2541+#CFLAGS+=-DCAPI_FORCE_SOFTWARE_DTMF
2542+
2543+# uncomment the next line if you are in the ulaw world
2544+#CFLAGS+=-DCAPI_ULAW
2545+
2546+# very experimental echo squelching
2547+CFLAGS+=-DCAPI_ES
2548+
2549+#gains
2550+CFLAGS+=-DCAPI_GAIN
2551+
2552+# what do to with call waiting connect indications?
2553+# uncomment the next line for call deflection in that case
2554+CFLAGS+=-DCAPI_DEFLECT_ON_CIRCUITBUSY
2555+
2556+# audio sync
2557+CFLAGS+=-DCAPI_SYNC
2558+
2559+endif
2560+
2561 ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/vpbapi.h),)
2562 CHANNEL_LIBS+=chan_vpb.so
2563 CFLAGS+=-DLINUX
5f892677
MT
2564@@ -204,7 +238,7 @@
2565 $(CC) -c $(CFLAGS) -o chan_zap.o chan_zap.c
2566
2567 chan_zap.so: chan_zap.o
2568- $(CC) $(SOLINK) -o $@ $< $(ZAPPRI) $(ZAPR2) -ltonezone
2569+ $(CC) $(SOLINK) -o $@ $< $(ZAPPRI) $(ZAPGSM) $(ZAPR2) -ltonezone
2570
2571 chan_sip.so: chan_sip.o
2572 $(CC) $(SOLINK) -o $@ ${CYGSOLINK} chan_sip.o ${CYGSOLIB}
2573@@ -220,6 +254,9 @@
5e69ef1a
MT
2574 chan_nbs.so: chan_nbs.o
2575 $(CC) $(SOLINK) -o $@ $< -lnbs
2576
2577+chan_capi.so: chan_capi.o
2578+ $(CC) $(SOLINK) -o $@ $< -lcapi20
2579+
2580 chan_vpb.o: chan_vpb.c
2581 $(CXX) -c $(CFLAGS) -o $@ chan_vpb.c
2582
b684b13b
MT
2583diff -urN asterisk-1.2.9.1.orig/channels/chan_agent.c asterisk-1.2.9.1/channels/chan_agent.c
2584--- asterisk-1.2.9.1.orig/channels/chan_agent.c 2006-05-08 16:12:20.000000000 +0200
2585+++ asterisk-1.2.9.1/channels/chan_agent.c 2006-06-09 10:25:04.000000000 +0200
2586@@ -440,7 +440,7 @@
2587 if ((pointer = strchr(filename, '.')))
2588 *pointer = '-';
2589 snprintf(tmp, sizeof(tmp), "%s%s",savecallsin ? savecallsin : "", filename);
2590- ast_monitor_start(ast, recordformat, tmp, needlock);
2591+ ast_monitor_start(ast, recordformat, tmp, NULL, NULL, needlock);
2592 ast_monitor_setjoinfiles(ast, 1);
2593 snprintf(tmp2, sizeof(tmp2), "%s%s.%s", urlprefix ? urlprefix : "", filename, recordformatext);
2594 #if 0
5e69ef1a
MT
2595@@ -1331,7 +1331,7 @@
2596 chan = agent_new(p, AST_STATE_DOWN);
2597 } else if (!p->owner && !ast_strlen_zero(p->loginchan)) {
2598 /* Adjustable agent */
2599- p->chan = ast_request("Local", format, p->loginchan, cause);
2600+ p->chan = ast_request("Local", format, p->loginchan, cause, NULL);
2601 if (p->chan)
2602 chan = agent_new(p, AST_STATE_DOWN);
2603 }
b684b13b
MT
2604diff -urN asterisk-1.2.9.1.orig/channels/chan_capi.c asterisk-1.2.9.1/channels/chan_capi.c
2605--- asterisk-1.2.9.1.orig/channels/chan_capi.c 1970-01-01 01:00:00.000000000 +0100
2606+++ asterisk-1.2.9.1/channels/chan_capi.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
2607@@ -0,0 +1,2888 @@
2608+/*
2609+ * (CAPI*)
2610+ *
2611+ * An implementation of Common ISDN API 2.0 for Asterisk
2612+ *
2613+ * Copyright (C) 2002, 2003, 2004, 2005 Junghanns.NET GmbH
2614+ *
2615+ * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
2616+ *
2617+ * This program is free software and may be modified and
2618+ * distributed under the terms of the GNU Public License.
2619+ */
2620+
2621+#include <sys/time.h>
2622+#include <sys/signal.h>
2623+#include <stdlib.h>
2624+#include <stdio.h>
2625+#include <string.h>
2626+#include <errno.h>
2627+#include <unistd.h>
2628+#include <fcntl.h>
2629+#include <sys/types.h>
2630+#include <asterisk/lock.h>
2631+#include <asterisk/frame.h>
2632+#include <asterisk/channel.h>
2633+#include <asterisk/logger.h>
2634+#include <asterisk/module.h>
2635+#include <asterisk/pbx.h>
2636+#include <asterisk/config.h>
2637+#include <asterisk/options.h>
2638+#include <asterisk/features.h>
2639+#include <asterisk/utils.h>
2640+#include <asterisk/cli.h>
2641+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
2642+#include <capi_bsd.h>
2643+#else
2644+#include <linux/capi.h>
2645+#endif
2646+#include <capi20.h>
2647+#include <asterisk/dsp.h>
2648+#include <asterisk/xlaw.h>
2649+#include <asterisk/chan_capi.h>
2650+
2651+unsigned ast_capi_ApplID;
2652+_cword ast_capi_MessageNumber=1;
2653+static char desc[] = "Common ISDN API for Asterisk";
2654+#ifdef CAPI_ULAW
2655+static char tdesc[] = "Common ISDN API Driver (0.4.0) muLaw";
2656+#else
2657+static char tdesc[] = "Common ISDN API Driver (0.4.0) aLaw ";
2658+#endif
2659+static char type[] = "CAPI";
2660+
2661+
2662+static int usecnt;
2663+AST_MUTEX_DEFINE_STATIC(usecnt_lock);
2664+AST_MUTEX_DEFINE_STATIC(iflock);
2665+AST_MUTEX_DEFINE_STATIC(pipelock);
2666+AST_MUTEX_DEFINE_STATIC(monlock);
2667+AST_MUTEX_DEFINE_STATIC(contrlock);
2668+AST_MUTEX_DEFINE_STATIC(capi_send_buffer_lock);
2669+AST_MUTEX_DEFINE_STATIC(capi_put_lock);
2670+
2671+#ifdef CAPI_ULAW
2672+static int capi_capability = AST_FORMAT_ULAW;
2673+#else
2674+static int capi_capability = AST_FORMAT_ALAW;
2675+#endif
2676+
2677+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
2678+static CAPIProfileBuffer_t profile;
2679+#else
2680+static struct ast_capi_profile profile;
2681+#endif
2682+static pthread_t monitor_thread = -1;
2683+
2684+static struct ast_capi_pvt *iflist = NULL;
2685+static struct capi_pipe *pipelist = NULL;
2686+static int capi_last_plci = 0;
2687+static struct ast_capi_controller *capi_controllers[AST_CAPI_MAX_CONTROLLERS];
2688+static int capi_num_controllers = 0;
2689+static int capi_counter = 0;
2690+static unsigned long capi_used_controllers=0;
2691+
2692+static char capi_send_buffer[AST_CAPI_MAX_B3_BLOCKS * AST_CAPI_MAX_B3_BLOCK_SIZE];
2693+static int capi_send_buffer_handle = 0;
2694+
2695+char capi_national_prefix[AST_MAX_EXTENSION];
2696+char capi_international_prefix[AST_MAX_EXTENSION];
2697+
2698+int capidebug = 0;
2699+
2700+static const struct ast_channel_tech capi_tech;
2701+
2702+MESSAGE_EXCHANGE_ERROR _capi_put_cmsg(_cmsg *CMSG) {
2703+ MESSAGE_EXCHANGE_ERROR error;
2704+ if (ast_mutex_lock(&capi_put_lock)) {
2705+ ast_log(LOG_WARNING,"Unable to lock capi put!\n");
2706+ return -1;
2707+ }
2708+ error = capi20_put_cmsg(CMSG);
2709+ if (ast_mutex_unlock(&capi_put_lock)) {
2710+ ast_log(LOG_WARNING,"Unable to unlock capi put!\n");
2711+ return -1;
2712+ }
2713+ return error;
2714+}
2715+
2716+
2717+MESSAGE_EXCHANGE_ERROR check_wait_get_cmsg(_cmsg *CMSG) {
2718+ MESSAGE_EXCHANGE_ERROR Info;
2719+ struct timeval tv;
2720+ tv.tv_sec = 0;
2721+ tv.tv_usec = 10000;
2722+ Info = capi20_waitformessage(ast_capi_ApplID,&tv);
2723+ if ((Info != 0x0000) && (Info != 0x1104)) {
2724+ if (capidebug) {
2725+ ast_log(LOG_DEBUG, "Error waiting for cmsg... INFO = %#x\n", Info);
2726+ }
2727+ return Info;
2728+ }
2729+
2730+ if (Info == 0x0000) {
2731+ Info = capi_get_cmsg(CMSG,ast_capi_ApplID);
2732+ }
2733+ return Info;
2734+}
2735+
2736+
2737+unsigned ListenOnController(unsigned long CIPmask,unsigned controller) {
2738+ MESSAGE_EXCHANGE_ERROR error;
2739+ _cmsg CMSG,CMSG2;
2740+
2741+ LISTEN_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, controller);
2742+#ifdef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
2743+ LISTEN_REQ_INFOMASK(&CMSG) = 0x00ff; // lots of info ;)
2744+#else
2745+ LISTEN_REQ_INFOMASK(&CMSG) = 0x03ff; // lots of info ;) + early B3 connect
2746+#endif
2747+ LISTEN_REQ_CIPMASK(&CMSG) = CIPmask;
2748+ if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2749+ return error;
2750+ }
2751+ while (!IS_LISTEN_CONF(&CMSG2)) {
2752+ error = check_wait_get_cmsg(&CMSG2);
2753+ }
2754+ return 0;
2755+}
2756+
2757+// Echo cancellation is for cards w/ integrated echo cancellation only
2758+// (i.e. Eicon active cards support it)
2759+
2760+#define EC_FUNCTION_ENABLE 1
2761+#define EC_FUNCTION_DISABLE 2
2762+#define EC_FUNCTION_FREEZE 3
2763+#define EC_FUNCTION_RESUME 4
2764+#define EC_FUNCTION_RESET 5
2765+#define EC_OPTION_DISABLE_NEVER 0
2766+#define EC_OPTION_DISABLE_G165 (1<<1)
2767+#define EC_OPTION_DISABLE_G164_OR_G165 (1<<1 | 1<<2)
2768+#define EC_DEFAULT_TAIL 64
2769+
2770+static int capi_echo_canceller(struct ast_channel *c, int function) {
2771+ struct ast_capi_pvt *i = c->tech_pvt;
2772+ MESSAGE_EXCHANGE_ERROR error;
2773+ _cmsg CMSG;
2774+ unsigned char buf[7];
2775+
2776+ /* If echo cancellation is not requested or supported, don't attempt to enable it */
2777+ ast_mutex_lock(&contrlock);
2778+ if (!capi_controllers[i->controller]->echocancel || !i->doEC) {
2779+ ast_mutex_unlock(&contrlock);
2780+ return 0;
2781+ }
2782+ ast_mutex_unlock(&contrlock);
2783+
2784+ if (option_verbose > 2)
2785+ ast_verbose(VERBOSE_PREFIX_3 "Setting up echo canceller (PLCI=%#x, function=%d, options=%d, tail=%d)\n",i->PLCI,function,i->ecOption,i->ecTail);
2786+
2787+ FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
2788+ FACILITY_REQ_NCCI(&CMSG) = i->NCCI;
2789+ FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 6; /* Echo canceller */
2790+
2791+ buf[0]=6; /* msg size */
2792+ buf[1]=function;
2793+ if (function == EC_FUNCTION_ENABLE) {
2794+ buf[3]=i->ecOption; /* bit field - ignore echo canceller disable tone */
2795+ buf[5]=i->ecTail; /* Tail length, ms */
2796+ }
2797+ else {
2798+ buf[3]=0;
2799+ buf[5]=0;
2800+ }
2801+
2802+ // Always null:
2803+ buf[2]=0;
2804+ buf[4]=0;
2805+ buf[6]=0;
2806+
2807+ FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = buf;
2808+
2809+ if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2810+ ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
2811+ return error;
2812+ }
2813+
2814+ if (option_verbose > 5)
2815+ ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_REQ (PLCI=%#x)\n",i->PLCI);
2816+
2817+ return 0;
2818+}
2819+
2820+int capi_detect_dtmf(struct ast_channel *c, int flag) {
2821+ struct ast_capi_pvt *i = c->tech_pvt;
2822+#ifndef CAPI_FORCE_SOFTWARE_DTMF
2823+ MESSAGE_EXCHANGE_ERROR error;
2824+ _cmsg CMSG;
2825+ unsigned char buf[9];
2826+ // does the controller support dtmf? and do we want to use it?
2827+ ast_mutex_lock(&contrlock);
2828+ if ((capi_controllers[i->controller]->dtmf == 1) && (i->doDTMF == 0)) {
2829+ ast_mutex_unlock(&contrlock);
2830+ FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
2831+ FACILITY_REQ_PLCI(&CMSG) = i->PLCI;
2832+ FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 1;
2833+ buf[0] = 8;
2834+ if (flag == 1) {
2835+ buf[1] = 1;
2836+ } else {
2837+ buf[1] = 2;
2838+ }
2839+ buf[2] = 0;
2840+ buf[3] = AST_CAPI_DTMF_DURATION;
2841+ buf[4] = 0;
2842+ buf[5] = AST_CAPI_DTMF_DURATION;
2843+ buf[6] = 0;
2844+ buf[7] = 0;
2845+ buf[8] = 0;
2846+ FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = buf;
2847+
2848+ if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2849+ ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
2850+ return error;
2851+ } else {
2852+ if (option_verbose > 5) {
2853+ ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_REQ (PLCI=%#x)\n",i->PLCI);
2854+ }
2855+ }
2856+ } else {
2857+ ast_mutex_unlock(&contrlock);
2858+
2859+#endif
2860+ // do software dtmf detection
2861+ i->doDTMF = 1; // just being paranoid again...
2862+#ifndef CAPI_FORCE_SOFTWARE_DTMF
2863+ }
2864+#endif
2865+ return 0;
2866+}
2867+static int capi_send_digit(struct ast_channel *c,char digit) {
2868+ struct ast_capi_pvt *i = c->tech_pvt;
2869+ MESSAGE_EXCHANGE_ERROR error;
2870+ _cmsg CMSG;
2871+ unsigned char buf[10];
2872+
2873+ if (i->state != CAPI_STATE_BCONNECTED) {
2874+ return 0;
2875+ }
2876+
2877+
2878+#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
2879+ if(i->earlyB3 == 1)
2880+ /* we should really test for the network saying the number is incomplete
2881+ since i'm only doing a test and this is true at the right time
2882+ i'm going with this */
2883+ {
2884+
2885+ INFO_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
2886+ INFO_REQ_PLCI(&CMSG) = i->PLCI;
2887+ buf[0] = 2;
2888+ buf[1] = 0x80;
2889+ buf[2] = digit;
2890+ INFO_REQ_CALLEDPARTYNUMBER(&CMSG) = buf;
2891+
2892+
2893+ if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2894+ ast_log(LOG_ERROR,"error sending CALLEDPARTYNUMBER INFO (error=%#x)\n",error);
2895+ return error;
2896+ } else {
2897+ if (option_verbose > 5) {
2898+ ast_verbose(VERBOSE_PREFIX_4 "sent CALLEDPARTYNUMBER INFO digit = %c (PLCI=%#x)\n", digit, i->PLCI);
2899+ }
2900+ }
2901+
2902+ } else {
2903+#endif
2904+#ifndef CAPI_FORCE_SOFTWARE_DTMF
2905+ ast_mutex_lock(&contrlock);
2906+ if ((capi_controllers[i->controller]->dtmf == 0) || (i->doDTMF == 1)) {
2907+#endif
2908+ // let * fake it
2909+#ifndef CAPI_FORCE_SOFTWARE_DTMF
2910+ ast_mutex_unlock(&contrlock);
2911+#endif
2912+ return -1;
2913+#ifndef CAPI_FORCE_SOFTWARE_DTMF
2914+ }
2915+ ast_mutex_unlock(&contrlock);
2916+
2917+ FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
2918+ FACILITY_REQ_PLCI(&CMSG) = i->NCCI;
2919+ FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 1;
2920+ buf[0] = 8;
2921+
2922+ buf[1] = 3;
2923+ buf[2] = 0;
2924+
2925+ buf[3] = AST_CAPI_DTMF_DURATION;
2926+ buf[4] = 0;
2927+
2928+ buf[5] = AST_CAPI_DTMF_DURATION;
2929+ buf[6] = 0;
2930+
2931+ buf[7] = 1;
2932+ buf[8] = digit;
2933+ buf[9] = 0;
2934+ FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = buf;
2935+
2936+ if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2937+ ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
2938+ return error;
2939+ } else {
2940+ if (option_verbose > 4) {
2941+ ast_verbose(VERBOSE_PREFIX_3 "sent dtmf '%c'\n",digit);
2942+ }
2943+ }
2944+#endif
2945+#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
2946+ }
2947+#endif
2948+ return 0;
2949+}
2950+
2951+static int capi_alert(struct ast_channel *c) {
2952+ struct ast_capi_pvt *i = c->tech_pvt;
2953+ MESSAGE_EXCHANGE_ERROR error;
2954+ _cmsg CMSG;
2955+
2956+ ALERT_REQ_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
2957+ ALERT_REQ_PLCI(&CMSG) = i->PLCI;
2958+
2959+ if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2960+ ast_log(LOG_ERROR,"error sending ALERT_REQ PLCI = %#x\n",i->PLCI);
2961+ return -1;
2962+ } else {
2963+ if (option_verbose > 5) {
2964+ ast_verbose(VERBOSE_PREFIX_4 "sent ALERT_REQ PLCI = %#x\n",i->PLCI);
2965+ }
2966+ }
2967+
2968+ i->state = CAPI_STATE_ALERTING;
2969+ return 0;
2970+}
2971+
2972+#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
2973+static int capi_deflect(struct ast_channel *chan, void *data)
2974+{
2975+ struct ast_capi_pvt *i = chan->tech_pvt;
2976+ MESSAGE_EXCHANGE_ERROR Info;
2977+ _cmsg CMSG;
2978+ char bchaninfo[1];
2979+ char fac[60];
2980+ int res=0;
2981+ int ms=3000;
2982+
2983+ if (!data) {
2984+ ast_log(LOG_WARNING, "cd requires an argument (destination phone number)\n");
2985+ return -1;
2986+ }
2987+
2988+ if ((i->state == CAPI_STATE_CONNECTED) || (i->state == CAPI_STATE_BCONNECTED)) {
2989+ ast_log(LOG_ERROR, "call deflection does not work with calls that are already connected!\n");
2990+ return -1;
2991+ }
2992+ // wait until the channel is alerting, so we dont drop the call and interfer with msgs
2993+ while ((ms > 0) && (i->state != CAPI_STATE_ALERTING)) {
2994+ sleep(100);
2995+ ms -= 100;
2996+ }
2997+
2998+ // make sure we hang up correctly
2999+ i->state = CAPI_STATE_CONNECTPENDING;
3000+
3001+ fac[0]=0; // len
3002+ fac[1]=0; //len
3003+ fac[2]=0x01; // Use D-Chan
3004+ fac[3]=0; // Keypad len
3005+ fac[4]=31; // user user data? len = 31 = 29 + 2
3006+ fac[5]=0x1c; // magic?
3007+ fac[6]=0x1d; // strlen destination + 18 = 29
3008+ fac[7]=0x91; // ..
3009+ fac[8]=0xA1;
3010+ fac[9]=0x1A; // strlen destination + 15 = 26
3011+ fac[10]=0x02;
3012+ fac[11]=0x01;
3013+ fac[12]=0x70;
3014+ fac[13]=0x02;
3015+ fac[14]=0x01;
3016+ fac[15]=0x0d;
3017+ fac[16]=0x30;
3018+ fac[17]=0x12; // strlen destination + 7 = 18
3019+ fac[18]=0x30; // ...hm 0x30
3020+ fac[19]=0x0d; // strlen destination + 2
3021+ fac[20]=0x80; // CLIP
3022+ fac[21]=0x0b; // strlen destination
3023+ fac[22]=0x01; // destination start
3024+ fac[23]=0x01; //
3025+ fac[24]=0x01; //
3026+ fac[25]=0x01; //
3027+ fac[26]=0x01; //
3028+ fac[27]=0x01; //
3029+ fac[28]=0x01; //
3030+ fac[29]=0x01; //
3031+ fac[30]=0x01; //
3032+ fac[31]=0x01; //
3033+ fac[32]=0x01; //
3034+ fac[33]=0x01; // 0x1 = sending complete
3035+ fac[34]=0x01;
3036+ fac[35]=0x01;
3037+
3038+ memcpy((unsigned char *)fac+22,data,strlen(data));
3039+ fac[22+strlen(data)]=0x01; // fill with 0x01 if number is only 6 numbers (local call)
3040+ fac[23+strlen(data)]=0x01;
3041+ fac[24+strlen(data)]=0x01;
3042+ fac[25+strlen(data)]=0x01;
3043+ fac[26+strlen(data)]=0x01;
3044+
3045+ fac[6]=18+strlen(data);
3046+ fac[9]=15+strlen(data);
3047+ fac[17]=7+strlen(data);
3048+ fac[19]=2+strlen(data);
3049+ fac[21]=strlen(data);
3050+
3051+ bchaninfo[0] = 0x1;
3052+ INFO_REQ_HEADER(&CMSG,ast_capi_ApplID,ast_capi_MessageNumber++,0);
3053+ INFO_REQ_CONTROLLER(&CMSG) = i->controller;
3054+ INFO_REQ_PLCI(&CMSG) = i->PLCI;
3055+ INFO_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char*)bchaninfo; // use D-Channel
3056+ INFO_REQ_KEYPADFACILITY(&CMSG) = 0;
3057+ INFO_REQ_USERUSERDATA(&CMSG) = 0;
3058+ INFO_REQ_FACILITYDATAARRAY(&CMSG) = (unsigned char*) fac + 4;
3059+
3060+ if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
3061+ ast_log(LOG_ERROR,"Error sending INFO_REQ\n");
3062+ return Info;
3063+ } else {
3064+ if (capidebug) {
3065+ // ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(&CMSG));
3066+ ast_log(LOG_NOTICE,"sent INFO_REQ PLCI = %#x\n",i->PLCI);
3067+ }
3068+ }
3069+
3070+ return res;
3071+}
3072+#endif
3073+
3074+void remove_pipe(int PLCI) {
3075+ struct capi_pipe *p,*ptmp;
3076+
3077+ ast_mutex_lock(&pipelock);
3078+ p = pipelist;
3079+ ptmp = NULL;
3080+ while (p) {
3081+ if (p->PLCI == PLCI) {
3082+ if (ptmp == NULL) {
3083+ // mypipe == head of pipelist
3084+ pipelist = p->next;
3085+ if(p->fd > -1) close(p->fd);
3086+ if(p->i != NULL && p->i->fd > -1) close(p->i->fd);
3087+ free(p);
3088+ if (option_verbose > 4) {
3089+ ast_verbose(VERBOSE_PREFIX_3 "removed pipe for PLCI = %#x\n",PLCI);
3090+ }
3091+ break;
3092+ } else {
3093+ // somehwere inbetween or at the end
3094+ ptmp->next = p->next;
3095+ if (p->next == NULL) {
3096+ capi_last_plci = p->PLCI;
3097+ }
3098+ if(p->fd > -1) close(p->fd);
3099+ if(p->i != NULL && p->i->fd > -1) close(p->i->fd);
3100+ free(p);
3101+ if (option_verbose > 4) {
3102+ ast_verbose(VERBOSE_PREFIX_3 "removed pipe for PLCI = %#x\n",PLCI);
3103+ }
3104+ break;
3105+ }
3106+ }
3107+ ptmp = p;
3108+ p = p->next;
3109+ }
3110+ ast_mutex_unlock(&pipelock);
3111+}
3112+
3113+static int capi_activehangup(struct ast_channel *c) {
3114+ struct ast_capi_pvt *i = c->tech_pvt;
3115+ MESSAGE_EXCHANGE_ERROR error;
3116+ _cmsg CMSG;
3117+
3118+ if (option_verbose > 2) {
3119+ if (capidebug)
3120+ ast_verbose(VERBOSE_PREFIX_4 "activehangingup\n");
3121+ }
3122+
3123+ if (i == NULL) {
3124+ return 0;
3125+ }
3126+
3127+ if (c->_state == AST_STATE_RING) {
3128+ CONNECT_RESP_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
3129+ CONNECT_RESP_PLCI(&CMSG) = i->PLCI;
3130+ CONNECT_RESP_REJECT(&CMSG) = 2;
3131+ if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3132+ ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",i->PLCI);
3133+ } else {
3134+ if (option_verbose > 5) {
3135+ ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",i->PLCI);
3136+ }
3137+ }
3138+ return 0;
3139+ }
3140+
3141+ // active disconnect
3142+ if (i->state == CAPI_STATE_BCONNECTED) {
3143+ DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
3144+ DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
3145+
3146+ if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3147+ ast_log(LOG_ERROR, "error sending DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
3148+ } else {
3149+ if (option_verbose > 5) {
3150+ ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
3151+ }
3152+ }
3153+ // wait for the B3 layer to go down
3154+ while (i->state != CAPI_STATE_CONNECTED) {
3155+ usleep(10000);
3156+ }
3157+ }
3158+ if ((i->state == CAPI_STATE_CONNECTED) || (i->state == CAPI_STATE_CONNECTPENDING)){
3159+ DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
3160+ DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
3161+
3162+ if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3163+ ast_log(LOG_ERROR, "error sending DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
3164+ } else {
3165+ if (option_verbose > 5) {
3166+ ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
3167+ }
3168+ }
3169+ // wait for the B1 layer to go down
3170+ while (i->state != CAPI_STATE_DISCONNECTED) {
3171+ usleep(10000);
3172+ }
3173+ }
3174+ return 0;
3175+}
3176+
3177+static int capi_hangup(struct ast_channel *c) {
3178+ struct ast_capi_pvt *i = c->tech_pvt;
3179+
3180+ // hmm....ok...this is called to free the capi interface (passive disconnect)
3181+ // or to bring down the channel (active disconnect)
3182+
3183+ if (option_verbose > 3)
3184+ ast_verbose(VERBOSE_PREFIX_3 "CAPI Hangingup\n");
3185+
3186+ if (i == NULL) {
3187+ ast_log(LOG_ERROR,"channel has no interface!\n");
3188+ return -1;
3189+ }
3190+
3191+ // are we down, yet?
3192+ if (i->state != CAPI_STATE_DISCONNECTED) {
3193+ // no
3194+ capi_activehangup(c);
3195+ }
3196+
3197+ remove_pipe(i->PLCI);
3198+ i->PLCI = 0;
3199+ i->NCCI = 0;
3200+ if ((i->doDTMF == 1) && (i->vad != NULL)) {
3201+ ast_dsp_free(i->vad);
3202+ }
3203+ ast_smoother_free(i->smoother); // discard any frames left hanging
3204+ i->smoother=ast_smoother_new(AST_CAPI_MAX_B3_BLOCK_SIZE * 2);
3205+ memset(i->cid,0,sizeof(i->cid));
3206+ i->owner=NULL;
3207+ ast_mutex_lock(&usecnt_lock);
3208+ usecnt--;
3209+ ast_mutex_unlock(&usecnt_lock);
3210+ ast_update_use_count();
3211+ i->mypipe = NULL;
3212+ i = NULL;
3213+ c->tech_pvt = NULL;
3214+ ast_setstate(c,AST_STATE_DOWN);
3215+ return 0;
3216+}
3217+
3218+static char *capi_number(char *data,int strip) {
3219+ unsigned len = *data;
3220+ // XXX fix me
3221+ // convert a capi struct to a \0 terminated string
3222+ if (!len || len < (unsigned int) strip) return NULL;
3223+ len = len - strip;
3224+ data = (char *)(data + 1 + strip);
3225+ return strndup((char *)data,len);
3226+}
3227+
3228+int capi_call(struct ast_channel *c, char *idest, int timeout)
3229+{
3230+ struct ast_capi_pvt *i;
3231+ struct capi_pipe *p = NULL;
3232+ int fds[2];
3233+ char *dest,*interface;
3234+ char buffer[AST_MAX_EXTENSION];
3235+ char called[AST_MAX_EXTENSION],calling[AST_MAX_EXTENSION];
3236+ char bchaninfo[3];
3237+ long flags;
3238+
3239+ _cmsg CMSG;
3240+ MESSAGE_EXCHANGE_ERROR error;
3241+
3242+ strncpy(buffer,idest,sizeof(buffer)-1);
3243+ interface = strtok(buffer, "/");
3244+ dest = strtok(NULL, "/");
3245+
3246+
3247+ if (!dest) {
3248+ ast_log(LOG_WARNING, "Destination %s requires a real destination\n", idest);
3249+ return -1;
3250+ }
3251+ i = c->tech_pvt;
3252+ i->doB3 = AST_CAPI_B3_DONT; // <homer>DOH</homer>
3253+
3254+ // always B3
3255+ if (((char *)dest)[0] == 'b') {
3256+ i->doB3 = AST_CAPI_B3_ALWAYS;
3257+ }
3258+ // only do B3 on successfull calls
3259+ if (((char *)dest)[0] == 'B') {
3260+ i->doB3 = AST_CAPI_B3_ON_SUCCESS;
3261+ }
3262+
3263+ if (i->doB3 != AST_CAPI_B3_DONT) {
3264+ dest++;
3265+ }
3266+
3267+ if (option_verbose > 1) {
3268+ if (capidebug)
3269+ ast_verbose(VERBOSE_PREFIX_2 "CAPI Call %s %s", c->name, i->doB3?"with B3":"");
3270+ }
3271+ switch (c->cid.cid_pres) {
3272+ case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
3273+ case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
3274+ case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
3275+ case PRES_ALLOWED_NETWORK_NUMBER:
3276+ case PRES_NUMBER_NOT_AVAILABLE:
3277+ i->CLIR = 0;
3278+ break;
3279+ case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
3280+ case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
3281+ case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
3282+ case PRES_PROHIB_NETWORK_NUMBER:
3283+ i->CLIR = 1;
3284+ break;
3285+ default:
3286+ i->CLIR = 0;
3287+ }
3288+
3289+ if (pipe(fds) == 0) {
3290+ ast_mutex_lock(&pipelock);
3291+ i->fd = fds[0];
3292+ flags = fcntl(i->fd,F_GETFL);
3293+ fcntl(i->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
3294+ p = malloc(sizeof(struct capi_pipe));
3295+ memset(p, 0, sizeof(struct capi_pipe));
3296+ p->fd = fds[1];
3297+ flags = fcntl(i->fd,F_GETFL);
3298+ fcntl(p->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
3299+ c->fds[0] = i->fd;
3300+ p->PLCI = -1;
3301+ p->i = i;
3302+ p->c = c;
3303+ i->mypipe = p;
3304+ p->next = pipelist;
3305+ pipelist = p;
3306+ if (option_verbose > 4) {
3307+ ast_verbose(VERBOSE_PREFIX_3 "creating pipe for PLCI=-1\n");
3308+ }
3309+ ast_mutex_unlock(&pipelock);
3310+ }
3311+ i->outgoing = 1;
3312+
3313+ i->MessageNumber = ast_capi_MessageNumber++;
3314+ CONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, i->controller);
3315+ CONNECT_REQ_CONTROLLER(&CMSG) = i->controller;
3316+ CONNECT_REQ_CIPVALUE(&CMSG) = 0x10; // Telephony, could also use 0x04 (3.1Khz audio)
3317+ called[0] = strlen(dest)+1;
3318+ called[1] = 0x80;
3319+ strncpy(&called[2],dest,sizeof(called)-2);
3320+ CONNECT_REQ_CALLEDPARTYNUMBER(&CMSG) = (unsigned char *)called;
3321+ CONNECT_REQ_CALLEDPARTYSUBADDRESS(&CMSG) = NULL;
3322+
3323+ if (c->cid.cid_num) {
3324+ calling[0] = strlen(c->cid.cid_num)+2;
3325+ calling[1] = 0x0;
3326+ } else {
3327+ calling[0] = 0x0;
3328+ calling[1] = 0x0;
3329+ }
3330+
3331+ if (i->CLIR == 1) {
3332+ calling[2] = 0xA0; // CLIR
3333+ } else {
3334+ calling[2] = 0x80; // CLIP
3335+ }
3336+
3337+ if (c->cid.cid_num) {
3338+ strncpy(&calling[3],c->cid.cid_num,sizeof(calling)-3);
3339+ }
3340+ CONNECT_REQ_CALLINGPARTYNUMBER(&CMSG) = (unsigned char *)calling;
3341+ CONNECT_REQ_CALLINGPARTYSUBADDRESS(&CMSG) = NULL;
3342+
3343+ CONNECT_REQ_B1PROTOCOL(&CMSG) = 1;
3344+ CONNECT_REQ_B2PROTOCOL(&CMSG) = 1; // 1
3345+ CONNECT_REQ_B3PROTOCOL(&CMSG) = 0;
3346+
3347+ bchaninfo[0] = 2;
3348+ bchaninfo[1] = 0x0;
3349+ bchaninfo[2] = 0x0;
3350+ CONNECT_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char *)bchaninfo; // 0
3351+
3352+ if ((error = _capi_put_cmsg(&CMSG))) {
3353+ ast_log(LOG_ERROR,"error sending CONNECT_REQ (error=%#x)\n",error);
3354+ return error;
3355+ } else {
3356+ if (option_verbose > 5) {
3357+ ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_REQ MN =%#x\n",CMSG.Messagenumber);
3358+ }
3359+ }
3360+
3361+ i->state = CAPI_STATE_CONNECTPENDING;
3362+
3363+ ast_setstate(c, AST_STATE_DIALING);
3364+
3365+ // XXX fixme, not nice:
3366+/* if (i->controller > 0) {
3367+ capi_controllers[i->controller]->nfreebchannels--;
3368+ } */
3369+
3370+ // now we shall return .... the rest has to be done by handle_msg
3371+ return 0;
3372+}
3373+
3374+
3375+static int capi_answer(struct ast_channel *c) {
3376+ struct ast_capi_pvt *i = c->tech_pvt;
3377+ MESSAGE_EXCHANGE_ERROR error;
3378+ _cmsg CMSG;
3379+ char buf[AST_MAX_EXTENSION];
3380+ char *dnid;
3381+
3382+ if (i->isdnmode && (strlen(i->incomingmsn)<strlen(i->dnid)))
3383+ dnid = i->dnid + strlen(i->incomingmsn);
3384+ else
3385+ dnid = i->dnid;
3386+
3387+ CONNECT_RESP_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
3388+ CONNECT_RESP_PLCI(&CMSG) = i->PLCI;
3389+ CONNECT_RESP_REJECT(&CMSG) = 0;
3390+ buf[0] = strlen(dnid)+2;
3391+ buf[1] = 0x0;
3392+ buf[2] = 0x80;
3393+ strncpy(&buf[3],dnid,sizeof(buf)-4);
3394+ CONNECT_RESP_CONNECTEDNUMBER(&CMSG) = (unsigned char *)buf;
3395+ CONNECT_RESP_CONNECTEDSUBADDRESS(&CMSG) = NULL;
3396+ CONNECT_RESP_LLC(&CMSG) = NULL;
3397+ CONNECT_RESP_B1PROTOCOL(&CMSG) = 1;
3398+ CONNECT_RESP_B2PROTOCOL(&CMSG) = 1;
3399+ CONNECT_RESP_B3PROTOCOL(&CMSG) = 0;
3400+
3401+ if (option_verbose > 3)
3402+ ast_verbose(VERBOSE_PREFIX_3 "CAPI Answering for MSN %s\n", dnid);
3403+ if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3404+ return -1;
3405+ } else {
3406+ if (option_verbose > 5) {
3407+ if (capidebug)
3408+ ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP PLCI = %#x DNID = %s\n",i->PLCI,i->dnid);
3409+ }
3410+ }
3411+
3412+ i->state = CAPI_STATE_ANSWERING;
3413+ i->doB3 = AST_CAPI_B3_DONT;
3414+ i->outgoing = 0;
3415+ i->earlyB3 = -1;
3416+
3417+ return 0;
3418+}
3419+
3420+struct ast_frame *capi_read(struct ast_channel *c) {
3421+ struct ast_capi_pvt *i = c->tech_pvt;
3422+ int readsize = 0;
3423+
3424+ if ((i->state == CAPI_STATE_REMOTE_HANGUP)) {
3425+ ast_log(LOG_ERROR,"this channel is not connected\n");
3426+ return NULL;
3427+ }
3428+ if (i->state == CAPI_STATE_ONHOLD) {
3429+ i->fr.frametype = AST_FRAME_NULL;
3430+ return &i->fr;
3431+ }
3432+
3433+ if (i == NULL) {
3434+ ast_log(LOG_ERROR,"channel has no interface\n");
3435+ return NULL;
3436+ }
3437+ i->fr.frametype = AST_FRAME_NULL;
3438+ i->fr.subclass = 0;
3439+ i->fr.delivery.tv_sec = 0;
3440+ i->fr.delivery.tv_usec = 0;
3441+ readsize = read(i->fd,&i->fr,sizeof(struct ast_frame));
3442+ if (readsize != sizeof(struct ast_frame)) {
3443+ ast_log(LOG_ERROR,"did not read a whole frame\n");
3444+ }
3445+ if (i->fr.frametype == AST_FRAME_VOICE) {
3446+ readsize = read(i->fd,i->fr.data,i->fr.datalen);
3447+ if (readsize != i->fr.datalen) {
3448+ ast_log(LOG_ERROR,"did not read whole frame data\n");
3449+ }
3450+ }
3451+ i->fr.mallocd = 0;
3452+ if (i->fr.frametype == AST_FRAME_NULL) {
3453+ return NULL;
3454+ }
3455+ if ((i->fr.frametype == AST_FRAME_DTMF) && (i->fr.subclass == 'f')) {
3456+ if (strcmp(c->exten, "fax")) {
3457+ if (ast_exists_extension(c, ast_strlen_zero(c->macrocontext) ? c->context : c->macrocontext, "fax", 1, c->cid.cid_num)) {
3458+ if (option_verbose > 2)
3459+ ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", c->name);
3460+ /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
3461+ pbx_builtin_setvar_helper(c,"FAXEXTEN",c->exten);
3462+ if (ast_async_goto(c, c->context, "fax", 1))
3463+ ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", c->name, c->context);
3464+ } else {
3465+ ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
3466+ }
3467+ } else {
3468+ ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
3469+ }
3470+ }
3471+ return &i->fr;
3472+}
3473+
3474+int capi_write(struct ast_channel *c, struct ast_frame *f) {
3475+ struct ast_capi_pvt *i = c->tech_pvt;
3476+ _cmsg CMSG;
3477+ MESSAGE_EXCHANGE_ERROR error;
3478+ int j=0;
3479+ char buf[1000];
3480+ struct ast_frame *fsmooth;
3481+#ifdef CAPI_ES
3482+ int txavg=0;
3483+#endif
3484+
3485+#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
3486+ // dont send audio to the local exchange!
3487+ if (i->earlyB3 == 1 || !i->NCCI) {
3488+ return 0;
3489+ }
3490+#endif
3491+
3492+ if (!i) {
3493+ ast_log(LOG_ERROR,"channel has no interface\n");
3494+ return -1;
3495+ }
3496+
3497+ if (f->frametype == AST_FRAME_NULL) {
3498+ return 0;
3499+ }
3500+ if (f->frametype == AST_FRAME_DTMF) {
3501+ ast_log(LOG_ERROR,"dtmf frame should be written\n");
3502+ return 0;
3503+ }
3504+ if (f->frametype != AST_FRAME_VOICE) {
3505+ ast_log(LOG_ERROR,"not a voice frame\n");
3506+ return -1;
3507+ }
3508+ if (f->subclass != capi_capability) {
3509+ ast_log(LOG_ERROR,"dont know how to write subclass %d\n",f->subclass);
3510+ return -1;
3511+ }
3512+// ast_log(LOG_NOTICE,"writing frame %d %d\n",f->frametype,f->subclass);
3513+
3514+ if (ast_smoother_feed(i->smoother, f)!=0) {
3515+ ast_log(LOG_ERROR,"failed to fill smoother\n");
3516+ return -1;
3517+ }
3518+
3519+ fsmooth=ast_smoother_read(i->smoother);
3520+ while(fsmooth != NULL) {
3521+ DATA_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
3522+ DATA_B3_REQ_NCCI(&CMSG) = i->NCCI;
3523+ DATA_B3_REQ_DATALENGTH(&CMSG) = fsmooth->datalen;
3524+ DATA_B3_REQ_FLAGS(&CMSG) = 0;
3525+
3526+ if (ast_mutex_lock(&capi_send_buffer_lock)) {
3527+ ast_log(LOG_WARNING,"Unable to lock B3 send buffer!\n");
3528+ return -1;
3529+ }
3530+#ifndef CAPI_ES
3531+#ifdef CAPI_GAIN
3532+ for (j=0;j<fsmooth->datalen;j++) {
3533+ buf[j] = i->g.txgains[reversebits[((unsigned char *)fsmooth->data)[j]]];
3534+ }
3535+#else
3536+ for (j=0;j<fsmooth->datalen;j++) {
3537+ buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ];
3538+ }
3539+#endif
3540+#else
3541+ if ((i->doES == 1)) {
3542+ for (j=0;j<fsmooth->datalen;j++) {
3543+ buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ];
3544+ txavg += abs( capiXLAW2INT(reversebits[ ((unsigned char*)fsmooth->data)[j]]) );
3545+ }
3546+ txavg = txavg/j;
3547+ for(j=0;j<ECHO_TX_COUNT-1;j++) {
3548+ i->txavg[j] = i->txavg[j+1];
3549+ }
3550+ i->txavg[ECHO_TX_COUNT-1] = txavg;
3551+
3552+// ast_log(LOG_NOTICE,"txavg = %d\n",txavg);
3553+ } else {
3554+#ifdef CAPI_GAIN
3555+ for (j=0;j<fsmooth->datalen;j++) {
3556+ buf[j] = i->g.txgains[reversebits[((unsigned char *)fsmooth->data)[j]]];
3557+ }
3558+#else
3559+ for (j=0;j<fsmooth->datalen;j++) {
3560+ buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ];
3561+ }
3562+#endif
3563+ }
3564+#endif
3565+
3566+ DATA_B3_REQ_DATAHANDLE(&CMSG) = capi_send_buffer_handle;
3567+ memcpy((char *)&capi_send_buffer[(capi_send_buffer_handle % AST_CAPI_MAX_B3_BLOCKS) * AST_CAPI_MAX_B3_BLOCK_SIZE],&buf,fsmooth->datalen);
3568+ DATA_B3_REQ_DATA(&CMSG) = (unsigned char *)&capi_send_buffer[(capi_send_buffer_handle % AST_CAPI_MAX_B3_BLOCKS) * AST_CAPI_MAX_B3_BLOCK_SIZE];
3569+ capi_send_buffer_handle++;
3570+
3571+ if (ast_mutex_unlock(&capi_send_buffer_lock)) {
3572+ ast_log(LOG_WARNING,"Unable to unlock B3 send buffer!\n");
3573+ return -1;
3574+ }
3575+
3576+
3577+#ifdef CAPI_SYNC
3578+ ast_mutex_lock(&i->lockB3in);
3579+ if ((i->B3in >= 1) && (i->B3in <= AST_CAPI_MAX_B3_BLOCKS)) {
3580+ i->B3in--;
3581+ ast_mutex_unlock(&i->lockB3in);
3582+ if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3583+ ast_log(LOG_ERROR,"error sending DATA_B3_REQ (error=%#x, datalen=%d) B3in=%d\n",error,fsmooth->datalen,i->B3in);
3584+// ast_log(LOG_NOTICE,"f: timelen %d b = %d MN = %d \n",fsmooth->timelen,b,CMSG.Messagenumber);
3585+ } else {
3586+ if (option_verbose > 5) {
3587+ if (capidebug)
3588+ ast_verbose(VERBOSE_PREFIX_4 "sent DATA_B3_REQ (NCCI=%#x) (%d bytes)\n",i->NCCI,fsmooth->datalen);
3589+ }
3590+ }
3591+ } else {
3592+ if (i->B3in > 0) i->B3in--;
3593+ ast_mutex_unlock(&i->lockB3in);
3594+ }
3595+#else
3596+ if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3597+ ast_log(LOG_ERROR,"error sending DATA_B3_REQ (error=%#x, datalen=%d)\n",error,fsmooth->datalen);
3598+// ast_log(LOG_NOTICE,"f: timelen %d b = %d MN = %d \n",fsmooth->timelen,b,CMSG.Messagenumber);
3599+ } else {
3600+ if (option_verbose > 5) {
3601+ if (capidebug)
3602+ ast_verbose(VERBOSE_PREFIX_4 "sent DATA_B3_REQ (NCCI=%#x) (%d bytes)\n",i->NCCI,fsmooth->datalen);
3603+ }
3604+ }
3605+#endif
3606+
3607+// ast_frfree(fsmooth);
3608+
3609+ fsmooth=ast_smoother_read(i->smoother);
3610+ }
3611+ return 0;
3612+}
3613+
3614+static int capi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan) {
3615+ struct ast_capi_pvt *p = newchan->tech_pvt;
3616+ p->owner = newchan;
3617+ return 0;
3618+}
3619+
3620+int capi_indicate(struct ast_channel *c,int condition) {
3621+ return -1;
3622+}
3623+
3624+int capi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc) {
3625+ return -1;
3626+}
3627+
3628+
3629+struct ast_channel *capi_new(struct ast_capi_pvt *i,int state) {
3630+ struct ast_channel *tmp;
3631+ int fmt;
3632+
3633+ tmp = ast_channel_alloc(1);
3634+ if (tmp != NULL) {
3635+ snprintf(tmp->name,sizeof(tmp->name),"CAPI/contr%d/%s-%d",i->controller,i->dnid,capi_counter++);
3636+ tmp->type = type;
3637+ tmp->tech = &capi_tech;
3638+ tmp->nativeformats = capi_capability;
3639+ ast_setstate(tmp,state);
3640+ tmp->fds[0] = i->fd;
3641+ i->smoother = ast_smoother_new(AST_CAPI_MAX_B3_BLOCK_SIZE);
3642+ if (i->smoother == NULL) {
3643+ ast_log(LOG_ERROR, "smoother NULL!\n");
3644+ }
3645+ i->fr.frametype = 0;
3646+ i->fr.subclass = 0;
3647+ i->fr.delivery.tv_sec = 0;
3648+ i->fr.delivery.tv_usec = 0;
3649+ i->state = CAPI_STATE_DISCONNECTED;
3650+ i->CLIR = 0;
3651+ i->calledPartyIsISDN = 0; // let's be pessimistic
3652+ i->earlyB3 = -1;
3653+ i->doB3 = AST_CAPI_B3_DONT;
3654+ i->outgoing = 0;
3655+ i->onholdPLCI = 0;
3656+#ifdef CAPI_SYNC
3657+ i->B3in = 0;
3658+ ast_mutex_init(&i->lockB3in);
3659+#endif
3660+#ifdef CAPI_ES
3661+ memset(i->txavg,0,ECHO_TX_COUNT);
3662+#endif
3663+
3664+#ifndef CAPI_FORCE_SOFTWARE_DTMF
3665+ if (i->doDTMF == 1) {
3666+#endif
3667+ i->vad = ast_dsp_new();
3668+ ast_dsp_set_features(i->vad, DSP_FEATURE_DTMF_DETECT);
3669+#ifndef CAPI_FORCE_SOFTWARE_DTMF
3670+ }
3671+#endif
3672+
3673+ tmp->tech_pvt = i;
3674+ tmp->callgroup = i->callgroup;
3675+ tmp->nativeformats = capi_capability;
3676+ fmt = ast_best_codec(tmp->nativeformats);
3677+// fmt = capi_capability;
3678+ tmp->readformat = fmt;
3679+ tmp->writeformat = fmt;
3680+ tmp->rawreadformat = fmt;
3681+ tmp->rawwriteformat = fmt;
3682+ strncpy(tmp->context,i->context,sizeof(tmp->context)-1);
3683+ tmp->cid.cid_num = strdup(i->cid);
3684+ tmp->cid.cid_dnid = strdup(i->dnid);
3685+ strncpy(tmp->exten,i->dnid,sizeof(tmp->exten)-1);
3686+ strncpy(tmp->accountcode,i->accountcode,sizeof(tmp->accountcode)-1);
3687+ i->owner = tmp;
3688+ ast_mutex_lock(&usecnt_lock);
3689+ usecnt++;
3690+ ast_mutex_unlock(&usecnt_lock);
3691+ ast_update_use_count();
3692+ if (state != AST_STATE_DOWN) {
3693+ // we are alerting (phones ringing)
3694+ if (state == AST_STATE_RING)
3695+ capi_alert(tmp);
3696+ if (ast_pbx_start(tmp)) {
3697+ ast_log(LOG_ERROR,"Unable to start pbx on channel!\n");
3698+ ast_hangup(tmp);
3699+ tmp = NULL;
3700+ } else {
3701+ if (option_verbose > 2) {
3702+ ast_verbose(VERBOSE_PREFIX_3 "started pbx on channel (callgroup=%d)!\n",tmp->callgroup);
3703+ }
3704+ }
3705+ }
3706+ } else {
3707+ ast_log(LOG_ERROR,"Unable to allocate channel!\n");
3708+ }
3709+ return tmp;
3710+}
3711+
3712+
3713+struct ast_channel *capi_request(const char *type, int format, void *data, int *cause)
3714+{
3715+ struct ast_capi_pvt *i;
3716+ struct ast_channel *tmp = NULL;
3717+ char *dest,*interface;
3718+ char buffer[AST_MAX_EXTENSION];
3719+ unsigned int capigroup=0, controller=0;
3720+ int notfound = 1;
3721+
3722+ if (option_verbose > 1) {
3723+ if (capidebug)
3724+ ast_verbose(VERBOSE_PREFIX_3 "data = %s\n",(char *)data);
3725+ }
3726+ strncpy(buffer,(char *)data,sizeof(buffer)-1);
3727+
3728+ interface = strtok(buffer, "/");
3729+ dest = strtok(NULL, "/");
3730+
3731+
3732+ if (((char *)interface)[0] == 'g') {
3733+ interface++;
3734+ capigroup = atoi(interface);
3735+ if (option_verbose > 1) {
3736+ if (capidebug)
3737+ ast_verbose(VERBOSE_PREFIX_3 "capi request group = %d\n",capigroup);
3738+ }
3739+ } else if (!strncmp(interface,"contr",5)) {
3740+ interface += 5;
3741+ controller = atoi(interface);
3742+ if (option_verbose > 1) {
3743+ if (capidebug)
3744+ ast_verbose(VERBOSE_PREFIX_3 "capi request controller = %d\n",controller);
3745+ }
3746+ } else {
3747+ ast_log(LOG_ERROR,"Syntax error in dialstring. read the docs!\n");
3748+ }
3749+
3750+ ast_mutex_lock(&iflock);
3751+ i = iflist;
3752+ while (i && notfound) {
3753+ // unused channel
3754+ if (!i->owner) {
3755+ if (controller && (i->controllers & (1 << controller))) {
3756+ // DIAL(CAPI/contrX/...)
3757+ ast_mutex_lock(&contrlock);
3758+ if (capi_controllers[controller]->nfreebchannels > 0) {
3759+ strncpy(i->dnid,dest,sizeof(i->dnid)-1);
3760+ i->controller = controller;
3761+ tmp = capi_new(i, AST_STATE_DOWN);
3762+ i->PLCI = -1;
3763+ i->datahandle = 0;
3764+ i->outgoing = 1; // this is an outgoing line
3765+ i->earlyB3 = -1;
3766+ // capi_detect_dtmf(tmp,1);
3767+ ast_mutex_unlock(&contrlock);
3768+ ast_mutex_unlock(&iflock);
3769+ return tmp;
3770+ } else {
3771+ // keep on running!
3772+ ast_mutex_unlock(&contrlock);
3773+ }
3774+ } else if (capigroup && (i->group & (1 << capigroup))) {
3775+ int c;
3776+ // DIAL(CAPI/gX/...)
3777+ ast_mutex_lock(&contrlock);
3778+ for (c=1;c<=capi_num_controllers;c++) {
3779+ if (i->controllers & (1 << c)) {
3780+ if (capi_controllers[c]->nfreebchannels > 0) {
3781+ strncpy(i->dnid,dest,sizeof(i->dnid)-1);
3782+ i->controller = c;
3783+ tmp = capi_new(i, AST_STATE_DOWN);
3784+ i->PLCI = -1;
3785+ i->datahandle = 0;
3786+ i->outgoing = 1; // this is an outgoing line
3787+ i->earlyB3 = -1;
3788+ // capi_detect_dtmf(tmp,1);
3789+ ast_mutex_unlock(&contrlock);
3790+ ast_mutex_unlock(&iflock);
3791+ return tmp;
3792+ } else {
3793+ // keep on running!
3794+ }
3795+ }
3796+ }
3797+ ast_mutex_unlock(&contrlock);
3798+ }
3799+ }
3800+// ast_log(LOG_NOTICE,"not contr %d group %d\n",i->controllers, i->group);
3801+ i = i->next;
3802+ }
3803+ ast_mutex_unlock(&iflock);
3804+ ast_log(LOG_NOTICE,"didn't find capi device with controller = %d or group = %d.\n",controller, capigroup);
3805+ return NULL;
3806+}
3807+
3808+
3809+struct capi_pipe *find_pipe(int PLCI,int MN) {
3810+ struct capi_pipe *p;
3811+ // find a pipe by PLCI or by MessageNumber (in case this is a CONNECT_CONF)
3812+ ast_mutex_lock(&pipelock);
3813+ p = pipelist;
3814+ if ((p == NULL) && (capi_last_plci != PLCI)){
3815+ if (capidebug) {
3816+ ast_log(LOG_NOTICE,"PLCI doesnt match last pipe (PLCI = %#x)\n",PLCI);
3817+ }
3818+ ast_mutex_unlock(&pipelock);
3819+ return NULL;
3820+ }
3821+ while(p != NULL) {
3822+ if ((p->PLCI == PLCI) || ( (p->PLCI == -1) && (p->i->MessageNumber == MN) ) ){
3823+ ast_mutex_unlock(&pipelock);
3824+ return p;
3825+ }
3826+ p = p->next;
3827+ }
3828+ if (capidebug) {
3829+ ast_log(LOG_ERROR,"unable to find a pipe for PLCI = %#x MN = %#x\n",PLCI,MN);
3830+ }
3831+ ast_mutex_unlock(&pipelock);
3832+ return NULL;
3833+}
3834+
3835+int pipe_frame(struct capi_pipe *p,struct ast_frame *f) {
3836+ fd_set wfds;
3837+ int written=0;
3838+ struct timeval tv;
3839+ FD_ZERO(&wfds);
3840+ FD_SET(p->fd,&wfds);
3841+ tv.tv_sec = 0;
3842+ tv.tv_usec = 10;
3843+ if ((f->frametype == AST_FRAME_VOICE) && (p->i->doDTMF == 1) && (p->i->vad != NULL)) {
3844+ f = ast_dsp_process(p->c,p->i->vad,f);
3845+ if (f->frametype == AST_FRAME_NULL) {
3846+ return 0;
3847+ }
3848+ }
3849+ // we dont want the monitor thread to block
3850+ if (select(p->fd + 1,NULL,&wfds,NULL,&tv) == 1) {
3851+ written = write(p->fd,f,sizeof(struct ast_frame));
3852+ if (written < (signed int) sizeof(struct ast_frame)) {
3853+ ast_log(LOG_ERROR,"wrote %d bytes instead of %d\n", written, (int)sizeof(struct ast_frame));
3854+ return -1;
3855+ }
3856+ if (f->frametype == AST_FRAME_VOICE) {
3857+ written = write(p->fd,f->data,f->datalen);
3858+ if (written < f->datalen) {
3859+ ast_log(LOG_ERROR,"wrote %d bytes instead of %d\n",written,f->datalen);
3860+ return -1;
3861+ }
3862+ }
3863+ } else {
3864+ return 0;
3865+ }
3866+ return -1;
3867+}
3868+
3869+static int search_did(struct ast_channel *c)
3870+{
3871+ // Returns
3872+ // -1 = Failure
3873+ // 0 = Match
3874+ // 1 = possible match
3875+ struct ast_capi_pvt *i = c->tech_pvt;
3876+ char *exten;
3877+
3878+ if (strlen(i->dnid)<strlen(i->incomingmsn))
3879+ return -1;
3880+
3881+// exten = i->dnid + strlen(i->incomingmsn);
3882+ exten = i->dnid;
3883+
3884+ if (ast_exists_extension(NULL, c->context, exten, 1, NULL)) {
3885+ c->priority = 1;
3886+ strncpy(c->exten, exten, sizeof(c->exten) - 1);
3887+ return 0;
3888+ }
3889+
3890+ if (ast_canmatch_extension(NULL, c->context, exten, 1, NULL)) {
3891+ return 1;
3892+ }
3893+
3894+
3895+ return -1;
3896+}
3897+
3898+int pipe_msg(int PLCI,_cmsg *CMSG) {
3899+ struct capi_pipe *p;
3900+ _cmsg CMSG2;
3901+ MESSAGE_EXCHANGE_ERROR error;
3902+ struct ast_frame fr;
3903+ char b3buf[1024];
3904+ int j;
3905+ int b3len=0;
3906+ char dtmf;
3907+ unsigned dtmflen;
3908+#ifdef CAPI_ES
3909+ int rxavg = 0;
3910+ int txavg = 0;
3911+#endif
3912+
3913+ p = find_pipe(PLCI,CMSG->Messagenumber);
3914+ if (p == NULL) {
3915+ if (IS_DISCONNECT_IND(CMSG)) {
3916+ DISCONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber , 0);
3917+ DISCONNECT_RESP_PLCI(&CMSG2) = PLCI;
3918+ if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
3919+ ast_log(LOG_NOTICE, "error sending DISCONNECT_RESP PLCI=%#x\n",PLCI);
3920+ } else {
3921+ if (option_verbose > 5) {
3922+ if (capidebug)
3923+ ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_RESP PLCI=%#x\n",PLCI);
3924+ }
3925+ }
3926+ return 0;
3927+ }
3928+ if (capidebug) {
3929+ ast_log(LOG_NOTICE,"%s",capi_cmsg2str(CMSG));
3930+ }
3931+ return -1;
3932+ }
3933+
3934+ if (CMSG != NULL) {
3935+ switch (CMSG->Subcommand) {
3936+ case CAPI_IND:
3937+ switch (CMSG->Command) {
3938+ case CAPI_DISCONNECT_B3:
3939+// ast_log(LOG_NOTICE,"DISCONNECT_B3_IND\n");
3940+
3941+ DISCONNECT_B3_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
3942+ DISCONNECT_B3_RESP_NCCI(&CMSG2) = DISCONNECT_B3_IND_NCCI(CMSG);
3943+
3944+ if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
3945+ ast_log(LOG_NOTICE, "error sending DISCONNECT_B3_RESP NCCI=%#x\n",(int)DISCONNECT_B3_IND_NCCI(CMSG));
3946+ } else {
3947+ if (option_verbose > 5) {
3948+ if (capidebug)
3949+ ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_B3_RESP NCCI=%#x\n",(int)DISCONNECT_B3_IND_NCCI(CMSG));
3950+ }
3951+ }
3952+ if (p->i->state == CAPI_STATE_BCONNECTED) {
3953+ // passive disconnect
3954+ p->i->state = CAPI_STATE_CONNECTED;
3955+ } else
3956+ if (p->i->state == CAPI_STATE_DISCONNECTING) {
3957+ // active disconnect
3958+ memset(&CMSG2,0,sizeof(_cmsg));
3959+ DISCONNECT_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
3960+ DISCONNECT_REQ_PLCI(&CMSG2) = PLCI;
3961+
3962+ if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
3963+ ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",PLCI);
3964+ } else {
3965+ if (option_verbose > 5) {
3966+ if (capidebug)
3967+ ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_REQ PLCI=%#x\n",PLCI);
3968+ }
3969+ }
3970+ } else
3971+ if (p->i->state == CAPI_STATE_ONHOLD) {
3972+ // no hangup
3973+ }
3974+ ast_mutex_lock(&contrlock);
3975+ if (p->i->controller > 0) {
3976+ capi_controllers[p->i->controller]->nfreebchannels++;
3977+ }
3978+ ast_mutex_unlock(&contrlock);
3979+ break;
3980+ case CAPI_DISCONNECT:
3981+// ast_log(LOG_NOTICE,"DISCONNECT_IND\n");
3982+ DISCONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber , 0);
3983+ DISCONNECT_RESP_PLCI(&CMSG2) = PLCI;
3984+/* if (p->i->controller > 0) {
3985+ capi_controllers[p->i->controller]->nfreebchannels++;
3986+ } */
3987+
3988+ if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
3989+ ast_log(LOG_NOTICE, "error sending DISCONNECT_RESP PLCI=%#x\n",PLCI);
3990+ } else {
3991+ if (option_verbose > 5) {
3992+ if (capidebug)
3993+ ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_RESP PLCI=%#x\n",PLCI);
3994+ }
3995+ }
3996+ if (p->c) {
3997+ p->c->hangupcause = DISCONNECT_IND_REASON(CMSG) - 0x3480;
3998+ }
3999+
4000+ if (PLCI == p->i->onholdPLCI) {
4001+ // the caller onhold hung up (or ECTed away)
4002+ p->i->onholdPLCI = 0;
4003+ remove_pipe(PLCI);
4004+ return 0;
4005+ }
4006+
4007+ if (p->i->state == CAPI_STATE_DID) {
4008+ if ((p->c) != NULL) {
4009+ ast_hangup(p->c);
4010+ } else {
4011+ ast_log(LOG_WARNING, "unable to hangup channel on DID. Channel is NULL.\n");
4012+ }
4013+ return 0;
4014+ }
4015+
4016+ p->i->state = CAPI_STATE_DISCONNECTED;
4017+
4018+ fr.frametype = AST_FRAME_CONTROL;
4019+ if (DISCONNECT_IND_REASON(CMSG) == 0x34a2) {
4020+ fr.subclass = AST_CONTROL_BUSY;
4021+ } else {
4022+ fr.frametype = AST_FRAME_NULL;
4023+ }
4024+ fr.datalen = 0;
4025+ if (pipe_frame(p,(struct ast_frame *)&fr) == -1) {
4026+ // printf("STATE = %#x\n",p->i->state);
4027+ // in this case * did not read our hangup control frame
4028+ // so we must hangup the channel!
4029+ if ( (p->i->state != CAPI_STATE_DISCONNECTED) && (ast_check_hangup(p->c) == 0)) {
4030+ if (option_verbose > 1) {
4031+ ast_verbose(VERBOSE_PREFIX_3 "soft hangup by capi\n");
4032+ }
4033+ ast_softhangup(p->c,AST_SOFTHANGUP_DEV);
4034+ } else {
4035+ // dont ever hangup while hanging up!
4036+// ast_log(LOG_NOTICE,"no soft hangup by capi\n");
4037+ }
4038+ return -1;
4039+ } else {
4040+ return 0;
4041+ }
4042+
4043+/* fr.frametype = AST_FRAME_NULL;
4044+ fr.datalen = 0;
4045+ pipe_frame(p,(struct ast_frame *)&fr); */
4046+ break;
4047+ case CAPI_DATA_B3:
4048+
4049+ memcpy(&b3buf[AST_FRIENDLY_OFFSET],(char *)DATA_B3_IND_DATA(CMSG),DATA_B3_IND_DATALENGTH(CMSG));
4050+ b3len = DATA_B3_IND_DATALENGTH(CMSG);
4051+
4052+ // send a DATA_B3_RESP very quickly to free the buffer in capi
4053+ DATA_B3_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber,0);
4054+ DATA_B3_RESP_NCCI(&CMSG2) = DATA_B3_IND_NCCI(CMSG);
4055+ DATA_B3_RESP_DATAHANDLE(&CMSG2) = DATA_B3_IND_DATAHANDLE(CMSG);
4056+ if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4057+ ast_log(LOG_ERROR,"error sending DATA_B3_RESP (error=%#x)\n",error);
4058+ } else {
4059+ if (option_verbose > 6) {
4060+ if (capidebug)
4061+ ast_verbose(VERBOSE_PREFIX_4 "sent DATA_B3_RESP (NCCI=%#x)\n",(int)DATA_B3_IND_NCCI(CMSG));
4062+ }
4063+ }
4064+#ifdef CAPI_SYNC
4065+ ast_mutex_lock(&p->i->lockB3in);
4066+ p->i->B3in++;
4067+ if (p->i->B3in > AST_CAPI_MAX_B3_BLOCKS) p->i->B3in = AST_CAPI_MAX_B3_BLOCKS;
4068+ ast_mutex_unlock(&p->i->lockB3in);
4069+#endif
4070+#ifdef CAPI_ES
4071+ if ((p->i->doES == 1)) {
4072+ for (j=0;j<b3len;j++) {
4073+ b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]];
4074+ rxavg += abs(capiXLAW2INT( reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]));
4075+ }
4076+ rxavg = rxavg/j;
4077+ for(j=0;j<ECHO_EFFECTIVE_TX_COUNT;j++) {
4078+ txavg += p->i->txavg[j];
4079+ }
4080+ txavg = txavg/j;
4081+
4082+ if( (txavg/ECHO_TXRX_RATIO) > rxavg) {
4083+#ifdef CAPI_ULAW
4084+ memset(&b3buf[AST_FRIENDLY_OFFSET],255,b3len);
4085+#else
4086+ memset(&b3buf[AST_FRIENDLY_OFFSET],84,b3len);
4087+#endif
4088+ if (capidebug) {
4089+ ast_log(LOG_NOTICE,"SUPPRESSING ECHOrx=%d, tx=%d\n",rxavg,txavg);
4090+ }
4091+ }
4092+ } else {
4093+#ifdef CAPI_GAIN
4094+ for (j=0;j<b3len;j++) {
4095+ b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[p->i->g.rxgains[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]];
4096+ }
4097+#else
4098+ for (j=0;j<b3len;j++) {
4099+ b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]];
4100+ }
4101+#endif
4102+ }
4103+#else
4104+
4105+#ifdef CAPI_GAIN
4106+ for (j=0;j<b3len;j++) {
4107+ b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[p->i->g.rxgains[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]];
4108+ }
4109+#else
4110+ for (j=0;j<b3len;j++) {
4111+ b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]];
4112+ }
4113+#endif
4114+
4115+#endif
4116+ // just being paranoid ...
4117+ /* if (p->c->_state != AST_STATE_UP) {
4118+ ast_setstate(p->c,AST_STATE_UP);
4119+ } */
4120+
4121+ fr.frametype = AST_FRAME_VOICE;
4122+ fr.subclass = capi_capability;
4123+ fr.data = (char *)&b3buf[AST_FRIENDLY_OFFSET];
4124+ fr.datalen = b3len;
4125+ fr.samples = b3len;
4126+ fr.offset = AST_FRIENDLY_OFFSET;
4127+ fr.mallocd = 0;
4128+ fr.delivery.tv_sec = 0;
4129+ fr.delivery.tv_usec = 0;
4130+ fr.src = NULL;
4131+ // ast_verbose(VERBOSE_PREFIX_3 "DATA_B3_IND (len=%d) fr.datalen=%d fr.subclass=%d\n",(int)DATA_B3_IND_DATALENGTH(CMSG),fr.datalen,fr.subclass);
4132+ return pipe_frame(p,(struct ast_frame *)&fr);
4133+ break;
4134+ case CAPI_FACILITY:
4135+ if (FACILITY_IND_FACILITYSELECTOR(CMSG) == 0x0001) {
4136+ // DTMF received
4137+ if (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[0] != (0xff)) {
4138+ dtmflen = FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[0];
4139+ FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG) += 1;
4140+ } else {
4141+ dtmflen = ((__u16 *) (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG) + 1))[0];
4142+ FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG) += 3;
4143+ }
4144+ if (dtmflen == 1) {
4145+ dtmf = (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG))[0];
4146+ fr.frametype = AST_FRAME_DTMF;
4147+ fr.subclass = dtmf;
4148+ if (option_verbose > 1) {
4149+ if (capidebug)
4150+ ast_verbose(VERBOSE_PREFIX_3 "c_dtmf = %c\n",dtmf);
4151+ }
4152+ pipe_frame(p,(struct ast_frame *)&fr);
4153+ }
4154+ }
4155+ if (FACILITY_IND_FACILITYSELECTOR(CMSG) == 0x0003) {
4156+ // sservices
4157+ /* ast_log(LOG_NOTICE,"FACILITY_IND PLCI = %#x\n",(int)FACILITY_IND_PLCI(CMSG));
4158+ ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[0]);
4159+ ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[1]);
4160+ ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[2]);
4161+ ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[3]);
4162+ ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4]);
4163+ ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5]); */
4164+ // RETRIEVE
4165+ if ( (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[1] == 0x3) && (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[3] == 0x2)) {
4166+ p->i->state = CAPI_STATE_CONNECTED;
4167+ p->i->PLCI = p->i->onholdPLCI;
4168+ p->i->onholdPLCI = 0;
4169+ }
4170+ if ( (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[1] == 0x2) && (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[3] == 0x2)) {
4171+ if ((FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5] != 0) && (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4] != 0)) {
4172+ // reason != 0x0000 == problem
4173+ p->i->onholdPLCI = 0;
4174+ p->i->state = CAPI_STATE_ONHOLD;
4175+ ast_log(LOG_WARNING, "unable to put PLCI=%#x onhold, REASON = %#x%#x, maybe you need to subscribe for this...\n",(int)FACILITY_IND_PLCI(CMSG),FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5],FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4]);
4176+ } else {
4177+ // reason = 0x0000 == call on hold
4178+ p->i->state = CAPI_STATE_ONHOLD;
4179+ if (capidebug)
4180+ ast_log(LOG_NOTICE, "PLCI=%#x put onhold\n",(int)FACILITY_IND_PLCI(CMSG));
4181+ }
4182+ }
4183+ }
4184+
4185+ error = FACILITY_RESP(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber,FACILITY_IND_PLCI(CMSG),FACILITY_IND_FACILITYSELECTOR(CMSG),FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG));
4186+
4187+ if (error != 0) {
4188+ ast_log(LOG_ERROR,"error sending FACILITY_RESP (error=%#x)\n",error);
4189+ } else {
4190+ if (option_verbose > 5) {
4191+ if (capidebug)
4192+ ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_RESP (PLCI=%#x)\n",(int)FACILITY_IND_PLCI(CMSG));
4193+ }
4194+ }
4195+ break;
4196+ case CAPI_INFO:
4197+ // ast_log(LOG_ERROR,"INFO_IND PLCI=%#x INFO# = %#x\n",PLCI,INFO_IND_INFONUMBER(CMSG));
4198+
4199+ memset(&CMSG2,0,sizeof(_cmsg));
4200+ error = INFO_RESP(&CMSG2,ast_capi_ApplID,CMSG->Messagenumber,PLCI);
4201+ if (error != 0) {
4202+ ast_log(LOG_ERROR,"error sending INFO_RESP (error=%#x)\n",error);
4203+ return -1;
4204+ } else {
4205+ if (option_verbose > 5) {
4206+ if (capidebug)
4207+ ast_verbose(VERBOSE_PREFIX_4 "sent INFO_RESP (PLCI=%#x)\n",PLCI);
4208+ }
4209+ }
4210+/* if ((INFO_IND_INFONUMBER(CMSG) >> 8) == 0x00) {
4211+ ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[0]);
4212+ ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[1]);
4213+ ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[2]);
4214+ ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[3]);
4215+ } */
4216+#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
4217+ if ((INFO_IND_INFONUMBER(CMSG) == 0x001e) && (p->i->doB3 != AST_CAPI_B3_DONT) && (p->i->earlyB3 == -1) && (p->i->state != CAPI_STATE_BCONNECTED)){
4218+ // ETSI 300 102-1 Progress Indicator
4219+ // we do early B3 Connect
4220+ if(INFO_IND_INFOELEMENT(CMSG)[0] >= 2) {
4221+ if(INFO_IND_INFOELEMENT(CMSG)[2] & 0x2) {
4222+ p->i->calledPartyIsISDN = 0;
4223+ // ast_log(LOG_NOTICE,"A N A L O G \n");
4224+ } else {
4225+ p->i->calledPartyIsISDN = 1;
4226+ // ast_log(LOG_NOTICE,"I S D N\n");
4227+ }
4228+ if(INFO_IND_INFOELEMENT(CMSG)[2] & 0x88) {
4229+ // in-band info available
4230+ p->i->earlyB3 = 1;
4231+ memset(&CMSG2,0,sizeof(_cmsg));
4232+ CONNECT_B3_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++,0);
4233+ CONNECT_B3_REQ_PLCI(&CMSG2) = PLCI;
4234+ if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4235+ ast_log(LOG_ERROR,"error sending early CONNECT_B3_REQ (error=%#x)\n",error);
4236+ return -1;
4237+ } else {
4238+ if (option_verbose > 1) {
4239+ if (capidebug)
4240+ ast_verbose(VERBOSE_PREFIX_4 "sent early CONNECT_B3_REQ (PLCI=%#x)\n",PLCI);
4241+ }
4242+ }
4243+ }
4244+ }
4245+ }
4246+ // DISCONNECT
4247+ if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (PLCI == p->i->onholdPLCI)) {
4248+ // the caller onhold hung up (or ECTed away)
4249+ // send a disconnect_req , we cannot hangup the channel here!!!
4250+ memset(&CMSG2,0,sizeof(_cmsg));
4251+ DISCONNECT_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
4252+ DISCONNECT_REQ_PLCI(&CMSG2) = p->i->onholdPLCI;
4253+
4254+ if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4255+ ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",PLCI);
4256+ } else {
4257+ if (option_verbose > 1) {
4258+ if (capidebug)
4259+ ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_REQ for onholdPLCI=%#x\n",PLCI);
4260+ }
4261+ }
4262+ return 0;
4263+ }
4264+
4265+ // case 1: B3 on success or no B3 at all
4266+ if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->doB3 != AST_CAPI_B3_ALWAYS) && (p->i->outgoing == 1)) {
4267+ p->i->earlyB3 = 0; // !!!
4268+ fr.frametype = AST_FRAME_NULL;
4269+ fr.datalen = 0;
4270+ return pipe_frame(p,(struct ast_frame *)&fr);
4271+ }
4272+ // case 2: we are doing B3, and receive the 0x8045 after a successful call
4273+ if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->doB3 != AST_CAPI_B3_DONT) && (p->i->earlyB3 == 0) && (p->i->outgoing == 1)) {
4274+ fr.frametype = AST_FRAME_NULL;
4275+ fr.datalen = 0;
4276+ return pipe_frame(p,(struct ast_frame *)&fr);
4277+ }
4278+ // case 3: this channel is an incoming channel! the user hung up!
4279+ // it is much better to hangup now instead of waiting for a timeout and
4280+ // network caused DISCONNECT_IND!
4281+ if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->outgoing == 0)) {
4282+ // ast_log(LOG_NOTICE,"case 3\n");
4283+ fr.frametype = AST_FRAME_NULL;
4284+ fr.datalen = 0;
4285+ return pipe_frame(p,(struct ast_frame *)&fr);
4286+ }
4287+ // case 4 (a.k.a. the italian case): B3 always. call is unsuccessful
4288+ if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->doB3 == AST_CAPI_B3_ALWAYS) && (p->i->earlyB3 == -1) && (p->i->outgoing == 1)) {
4289+ // wait for the 0x001e (PROGRESS), play audio and wait for a timeout from the network
4290+ return 0;
4291+ }
4292+#endif
4293+ // Handle DID digits
4294+ if ((INFO_IND_INFONUMBER(CMSG) == 0x0070) && p->i->isdnmode && (p->c != NULL)) {
4295+ int search = -1;
4296+ char name[AST_CHANNEL_NAME] = "";
4297+ char *did;
4298+
4299+ did = capi_number((char *)INFO_IND_INFOELEMENT(CMSG),1);
4300+ if (strcasecmp(p->i->dnid, did)) {
4301+ strncat(p->i->dnid, did, sizeof(p->i->dnid)-1);
4302+ }
4303+
4304+ snprintf(name,sizeof(name),"CAPI/contr%d/%s/-%d",p->i->controller,p->i->dnid,capi_counter++);
4305+ ast_change_name(p->c, name);
4306+
4307+ search = search_did(p->c);
4308+ if (search != -1) {
4309+ if (!search) {
4310+ ast_setstate(p->c, AST_STATE_RING);
4311+ // we are alerting (phones ringing)
4312+ capi_alert(p->c); // Do this here after pbx_start the Channel can be destroyed
4313+ if (ast_pbx_start(p->c)) {
4314+ ast_log(LOG_ERROR,"Unable to start pbx on channel!\n");
4315+ ast_hangup(p->c);
4316+ } else {
4317+ if (option_verbose > 2) {
4318+ if (capidebug)
4319+ ast_verbose(VERBOSE_PREFIX_3 "started pbx on channel!\n");
4320+ }
4321+ }
4322+ }
4323+ } else {
4324+ ast_log(LOG_ERROR,"did not find device for msn = %s\n",p->i->dnid);
4325+ CONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4326+ CONNECT_RESP_PLCI(&CMSG2) = PLCI;
4327+ CONNECT_RESP_REJECT(&CMSG2) = 1; // ignore
4328+ if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4329+ ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4330+ } else {
4331+ if (option_verbose > 5) {
4332+ if (capidebug)
4333+ ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4334+ }
4335+ }
4336+
4337+ return 0;
4338+ }
4339+ }
4340+ if (INFO_IND_INFONUMBER(CMSG) == 0x8001) {
4341+ fr.frametype = AST_FRAME_CONTROL;
4342+ fr.subclass = AST_CONTROL_RINGING;
4343+ return pipe_frame(p,(struct ast_frame *)&fr);
4344+ }
4345+ if (INFO_IND_INFONUMBER(CMSG) == 0x800d) {
4346+ fr.frametype = AST_FRAME_CONTROL;
4347+ fr.subclass = AST_CONTROL_PROGRESS;
4348+ return pipe_frame(p,(struct ast_frame *)&fr);
4349+ }
4350+ if (INFO_IND_INFONUMBER(CMSG) == 0x74) {
4351+ strncpy(p->i->owner->exten,capi_number((char *)INFO_IND_INFOELEMENT(CMSG),3),sizeof(p->i->owner->exten)-1);
4352+ ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(CMSG));
4353+ }
4354+ if (INFO_IND_INFONUMBER(CMSG) == 0x28) {
4355+ // ast_sendtext(p->i->owner,capi_number(INFO_IND_INFOELEMENT(CMSG),0));
4356+ // struct ast_frame ft = { AST_FRAME_TEXT, capi_number(INFO_IND_INFOELEMENT(CMSG),0), };
4357+ // ast_queue_frame(p->i->owner, &ft);
4358+ // ast_log(LOG_NOTICE,"%s\n",capi_number(INFO_IND_INFOELEMENT(CMSG),0));
4359+ }
4360+ break;
4361+ case CAPI_CONNECT_ACTIVE:
4362+// ast_log(LOG_NOTICE,"CONNECT_ACTIVE_IND PLCI=%#x\n",(int)CONNECT_ACTIVE_IND_PLCI(CMSG));
4363+ CONNECT_ACTIVE_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber,0);
4364+ CONNECT_ACTIVE_RESP_PLCI(&CMSG2) = PLCI;
4365+ if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4366+ ast_log(LOG_ERROR,"error sending CONNECT_ACTIVE_RESP (error=%#x)\n",error);
4367+ return -1;
4368+ } else {
4369+ if (option_verbose > 5) {
4370+ if (capidebug)
4371+ ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_ACTIVE_RESP (PLCI=%#x)\n",PLCI);
4372+ }
4373+ }
4374+ // normal processing
4375+ if (p->i->earlyB3 != 1) {
4376+ p->i->state = CAPI_STATE_CONNECTED;
4377+
4378+ // send a CONNECT_B3_REQ
4379+ if (p->i->outgoing == 1) {
4380+ // outgoing call
4381+ memset(&CMSG2,0,sizeof(_cmsg));
4382+ CONNECT_B3_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++,0);
4383+ CONNECT_B3_REQ_PLCI(&CMSG2) = PLCI;
4384+ if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4385+ ast_log(LOG_ERROR,"error sending CONNECT_B3_REQ (error=%#x)\n",error);
4386+ return -1;
4387+ } else {
4388+ if (option_verbose > 1) {
4389+ if (capidebug)
4390+ ast_verbose(VERBOSE_PREFIX_3 "sent CONNECT_B3_REQ (PLCI=%#x)\n",PLCI);
4391+ }
4392+ }
4393+ } else {
4394+ // incoming call
4395+ // RESP already sent ... wait for CONNECT_B3_IND
4396+// ast_log(LOG_NOTICE,"waiting for CONNECT_B3_IND\n");
4397+ }
4398+ } else {
4399+ // special treatment for early B3 connects
4400+ p->i->state = CAPI_STATE_BCONNECTED;
4401+ if (p->c->_state != AST_STATE_UP) {
4402+ ast_setstate(p->c,AST_STATE_UP);
4403+ }
4404+ p->i->earlyB3 = 0; // not early anymore
4405+ fr.frametype = AST_FRAME_CONTROL;
4406+ fr.subclass = AST_CONTROL_ANSWER;
4407+ fr.datalen = 0;
4408+ return pipe_frame(p,(struct ast_frame *)&fr);
4409+
4410+ }
4411+ break;
4412+ case CAPI_CONNECT_B3:
4413+ // then send a CONNECT_B3_RESP
4414+ memset(&CMSG2,0,sizeof(_cmsg));
4415+ CONNECT_B3_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4416+ CONNECT_B3_RESP_NCCI(&CMSG2) = CONNECT_B3_IND_NCCI(CMSG);
4417+ p->NCCI = CONNECT_B3_IND_NCCI(CMSG);
4418+ p->i->NCCI = p->NCCI;
4419+ CONNECT_B3_RESP_REJECT(&CMSG2) = 0;
4420+
4421+ if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4422+ ast_log(LOG_ERROR,"error sending CONNECT_B3_RESP (error=%#x)\n",error);
4423+ return -1;
4424+ } else {
4425+ if (option_verbose > 5) {
4426+ if (capidebug)
4427+ ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_B3_RESP (NCCI=%#x)\n",p->i->NCCI);
4428+ }
4429+ }
4430+ /* if (p->i->controller > 0) {
4431+ capi_controllers[p->i->controller]->nfreebchannels--;
4432+ } */
4433+ break;
4434+ case CAPI_CONNECT_B3_ACTIVE:
4435+// ast_log(LOG_NOTICE,"CONNECT_B3_ACTIVE_IND NCCI=%#x\n",p->i->NCCI);
4436+ // then send a CONNECT_B3__ACTIVERESP
4437+
4438+ CONNECT_B3_ACTIVE_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4439+ CONNECT_B3_ACTIVE_RESP_NCCI(&CMSG2) = p->i->NCCI;
4440+
4441+ if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4442+ ast_log(LOG_ERROR,"error sending CONNECT_B3_ACTIVE_RESP (error=%#x)\n",error);
4443+ return -1;
4444+ } else {
4445+ if (option_verbose > 5) {
4446+ if (capidebug)
4447+ ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_B3_ACTIVE_RESP (NCCI=%#x)\n",p->i->NCCI);
4448+ }
4449+ }
4450+
4451+ ast_mutex_lock(&contrlock);
4452+ if (p->i->controller > 0) {
4453+ capi_controllers[p->i->controller]->nfreebchannels--;
4454+ }
4455+ ast_mutex_unlock(&contrlock);
4456+
4457+ p->i->state = CAPI_STATE_BCONNECTED;
4458+ capi_echo_canceller(p->c,EC_FUNCTION_ENABLE);
4459+ capi_detect_dtmf(p->c,1);
4460+
4461+ if (p->i->earlyB3 != 1) {
4462+ ast_setstate(p->c,AST_STATE_UP);
4463+ fr.frametype = AST_FRAME_CONTROL;
4464+ fr.subclass = AST_CONTROL_ANSWER;
4465+ fr.datalen = 0;
4466+ return pipe_frame(p,(struct ast_frame *)&fr);
4467+ }
4468+ return 0;
4469+ break;
4470+ }
4471+ break;
4472+
4473+ case CAPI_CONF:
4474+ switch (CMSG->Command) {
4475+ case CAPI_FACILITY:
4476+ if (FACILITY_CONF_FACILITYSELECTOR(CMSG) == 0x3) {
4477+ if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[1] == 0x2) && (FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[2] == 0x0)) {
4478+ if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[4] == 0x0) && (FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[5] == 0x0)) {
4479+ } else {
4480+ p->i->state = CAPI_STATE_BCONNECTED;
4481+ if (capidebug)
4482+ ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(CMSG));
4483+ }
4484+ }
4485+ }
4486+ break;
4487+ case CAPI_DATA_B3:
4488+// ast_log(LOG_NOTICE,"DATA_B3_CONF (NCCI %#x) for DATAHANDLE %#x\n",DATA_B3_CONF_NCCI(CMSG),DATA_B3_CONF_DATAHANDLE(CMSG));
4489+ break;
4490+ case CAPI_ALERT:
4491+// ast_log(LOG_NOTICE,"ALERT_CONF (PLCI=%#x)\n",(int)ALERT_CONF_PLCI(CMSG));
4492+ p->i->state = CAPI_STATE_ALERTING;
4493+ if (p->c->_state == AST_STATE_RING) {
4494+ p->c->rings = 1;
4495+ }
4496+ break;
4497+ case CAPI_CONNECT:
4498+ if (option_verbose > 1) {
4499+ if (capidebug)
4500+ ast_verbose(VERBOSE_PREFIX_2 "received CONNECT_CONF PLCI = %#x INFO = %#x\n",(int)CONNECT_CONF_PLCI(CMSG),CONNECT_CONF_INFO(CMSG));
4501+ }
4502+ if (CONNECT_CONF_INFO(CMSG) == 0) {
4503+ p->i->PLCI = CONNECT_CONF_PLCI(CMSG);
4504+ p->PLCI = p->i->PLCI;
4505+ ast_setstate(p->c,AST_STATE_DIALING);
4506+ } else {
4507+ // here, something has to be done -->
4508+ fr.frametype = AST_FRAME_CONTROL;
4509+ fr.subclass = AST_CONTROL_BUSY;
4510+ fr.datalen = 0;
4511+ return pipe_frame(p,(struct ast_frame *)&fr);
4512+ }
4513+ break;
4514+ case CAPI_CONNECT_B3:
4515+// ast_log(LOG_NOTICE,"received CONNECT_B3_CONF NCCI = %#x INFO = %#x\n",(int)CONNECT_B3_CONF_NCCI(CMSG),CONNECT_B3_CONF_INFO(CMSG));
4516+ if (CONNECT_B3_CONF_INFO(CMSG) == 0) {
4517+ p->i->NCCI = CONNECT_B3_CONF_NCCI(CMSG);
4518+ } else {
4519+ p->i->earlyB3 = -1;
4520+ p->i->doB3 = AST_CAPI_B3_DONT;
4521+ }
4522+ break;
4523+ }
4524+ break;
4525+ }
4526+ }
4527+// ast_log(LOG_NOTICE,"returning\n");
4528+ return 0;
4529+}
4530+
4531+static void capi_handle_msg(_cmsg *CMSG) {
4532+ struct ast_capi_pvt *i;
4533+ char *DNID;
4534+ char *CID;
4535+ char *msn;
4536+ _cmsg CMSG2;
4537+ MESSAGE_EXCHANGE_ERROR error;
4538+ int PLCI=0,NCCI;
4539+ int NPLAN=0;
4540+ int fds[2];
4541+ int controller=0;
4542+ char buffer[AST_MAX_EXTENSION];
4543+ struct capi_pipe *p;
4544+ char *magicmsn = "*\0";
4545+ char *emptyid = "\0";
4546+ char *emptydnid = "s\0";
4547+ long flags;
4548+#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
4549+ int deflect=0;
4550+#endif
4551+
4552+ switch (CMSG->Subcommand) {
4553+ // indication msgs
4554+ case CAPI_IND:
4555+
4556+ switch (CMSG->Command) {
4557+ case CAPI_CONNECT: // only connect_ind are global (not channel specific)
4558+ if (capidebug)
4559+ ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(CMSG));
4560+ DNID = capi_number((char *)CONNECT_IND_CALLEDPARTYNUMBER(CMSG),1);
4561+ if ((DNID && *DNID == 0) || !DNID) {
4562+ DNID = emptydnid;
4563+ }
4564+ NPLAN = (CONNECT_IND_CALLINGPARTYNUMBER(CMSG)[1] & 0x70);
4565+ CID = capi_number((char *)CONNECT_IND_CALLINGPARTYNUMBER(CMSG),2);
4566+ PLCI = CONNECT_IND_PLCI(CMSG);
4567+ controller = PLCI & 0xff;
4568+ if (option_verbose > 1) {
4569+ if (capidebug)
4570+ ast_verbose(VERBOSE_PREFIX_2 "CONNECT_IND (PLCI=%#x,DID=%s,CID=%s,CIP=%#x,CONTROLLER=%#x)\n",PLCI,DNID,CID,CONNECT_IND_CIPVALUE(CMSG),controller);
4571+ }
4572+ if(CONNECT_IND_BCHANNELINFORMATION(CMSG))
4573+ if ((CONNECT_IND_BCHANNELINFORMATION(CMSG)[1] == 0x02) && (!capi_controllers[controller]->isdnmode)) {
4574+ // this is a call waiting CONNECT_IND with BChannelinformation[1] == 0x02
4575+ // meaning "no B or D channel for this call", since we can't do anything with call waiting now
4576+ // just reject it with "user busy"
4577+ // however...if we are a p2p BRI then the telco switch will allow us to choose the b channel
4578+ // so it will look like a callwaiting connect_ind to us
4579+
4580+ ast_log(LOG_ERROR,"received a call waiting CONNECT_IND\n");
4581+#ifndef CAPI_DEFLECT_ON_CIRCUITBUSY
4582+ CONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4583+ CONNECT_RESP_PLCI(&CMSG2) = CONNECT_IND_PLCI(CMSG);
4584+ CONNECT_RESP_REJECT(&CMSG2) = 3; // user is busy
4585+ if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4586+ ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4587+ } else {
4588+ if (option_verbose > 5) {
4589+ if (capidebug)
4590+ ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4591+ }
4592+ }
4593+ // no need to pipe this
4594+ PLCI = 0;
4595+ break;
4596+#else
4597+ deflect = 1;
4598+#endif
4599+ }
4600+ // well...somebody is calling us. let's set up a channel
4601+ ast_mutex_lock(&iflock);
4602+ i = iflist;
4603+ while(i) {
4604+ //XXX test this!
4605+ // has no owner
4606+ if ((!i->owner) && (i->incomingmsn != NULL)){
4607+ strncpy(buffer,i->incomingmsn,sizeof(buffer)-1);
4608+ msn = strtok(buffer,",");
4609+ while (msn != NULL) {
4610+// ast_log(LOG_NOTICE,"msn=%s\n",msn);
4611+ if (DNID && ((!strcasecmp(msn,DNID)) ||
4612+ (i->isdnmode && (strlen(msn)<strlen(DNID)) && !strncasecmp(msn, DNID, strlen(msn))) || (!strncasecmp(msn,magicmsn,strlen(msn)))) &&
4613+ (i->controllers & (1 << controller))) {
4614+ if (CID != NULL) {
4615+ if(NPLAN == CAPI_ETSI_NPLAN_NATIONAL)
4616+ snprintf(i->cid, (sizeof(i->cid)-1), "%s%s%s", i->prefix, capi_national_prefix, CID);
4617+ else if(NPLAN == CAPI_ETSI_NPLAN_INTERNAT)
4618+ snprintf(i->cid, (sizeof(i->cid)-1), "%s%s%s", i->prefix, capi_international_prefix, CID);
4619+ else
4620+ snprintf(i->cid, (sizeof(i->cid)-1), "%s%s", i->prefix, CID);
4621+ } else
4622+ strncpy(i->cid,emptyid,sizeof(i->cid)-1);
4623+
4624+ if (DNID != NULL)
4625+ strncpy(i->dnid,DNID,sizeof(i->dnid)-1);
4626+ else
4627+ strncpy(i->dnid,emptydnid,sizeof(i->dnid)-1);
4628+
4629+ i->controller=controller;
4630+ i->PLCI = PLCI;
4631+ i->MessageNumber = CMSG->Messagenumber;
4632+ if (pipe(fds) == 0) {
4633+ if (option_verbose > 4) {
4634+ ast_verbose(VERBOSE_PREFIX_3 "creating pipe for PLCI=%#x msn = %s\n",PLCI,msn);
4635+ }
4636+ i->fd = fds[0];
4637+ flags = fcntl(i->fd,F_GETFL);
4638+ fcntl(i->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
4639+// ast_log(LOG_NOTICE,"i->fd = %d\n",i->fd);
4640+ p = malloc(sizeof(struct capi_pipe));
4641+ memset(p, 0, sizeof(struct capi_pipe));
4642+ p->fd = fds[1];
4643+ flags = fcntl(i->fd,F_GETFL);
4644+ fcntl(p->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
4645+// ast_log(LOG_NOTICE,"p->fd = %d\n",p->fd);
4646+ p->PLCI = PLCI;
4647+ p->i = i;
4648+ ast_mutex_init(&(p->lock));
4649+ i->mypipe = p;
4650+ if (i->isdnmode) {
4651+ p->c = capi_new(i,AST_STATE_DOWN);
4652+ i->state = CAPI_STATE_DID;
4653+ } else {
4654+ p->c = capi_new(i,AST_STATE_RING);
4655+ }
4656+ p->next = pipelist;
4657+ pipelist = p;
4658+ // hmmm....
4659+ ast_mutex_unlock(&iflock);
4660+#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
4661+ if ((deflect == 1) && (i->deflect2)) {
4662+ capi_deflect(p->c,i->deflect2);
4663+ }
4664+#endif
4665+ return;
4666+ } else {
4667+ ast_log(LOG_ERROR,"creating pipe for PLCI=%#x failed\n",PLCI);
4668+ }
4669+ break;
4670+ } // if strcasecmp
4671+ msn = strtok(NULL,",");
4672+ } // while strtok
4673+ } // if
4674+ i = i->next;
4675+ } // while interface list
4676+ ast_mutex_unlock(&iflock); // obviously we are not called...so tell capi to ignore this call
4677+ if (capidebug) {
4678+ ast_log(LOG_ERROR,"did not find device for msn = %s\n",DNID);
4679+ }
4680+ CONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4681+ CONNECT_RESP_PLCI(&CMSG2) = CONNECT_IND_PLCI(CMSG);
4682+ CONNECT_RESP_REJECT(&CMSG2) = 1; // ignore
4683+ if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4684+ ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4685+ } else {
4686+ if (option_verbose > 5) {
4687+ if (capidebug)
4688+ ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4689+ }
4690+ }
4691+ ast_mutex_lock(&pipelock);
4692+ if (pipelist == NULL) {
4693+ capi_last_plci = PLCI;
4694+ }
4695+ ast_mutex_unlock(&pipelock);
4696+ // no need to pipe this
4697+ PLCI = 0;
4698+// ast_mutex_unlock(&iflock);
4699+// return;
4700+ break;
4701+ case CAPI_FACILITY:
4702+ PLCI = FACILITY_IND_PLCI(CMSG) & 0xffff; // this is for you eicon
4703+ if (option_verbose > 3) {
4704+ if (capidebug)
4705+ ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4706+ }
4707+// ast_log(LOG_ERROR,"FACILITY_IND PLCI=%#x\n",PLCI);
4708+ break;
4709+ case CAPI_INFO:
4710+ PLCI = INFO_IND_PLCI(CMSG);
4711+ if (option_verbose > 3) {
4712+ if (capidebug)
4713+ ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4714+ }
4715+// ast_log(LOG_ERROR,"INFO_IND PLCI=%#x INFO# = %#x\n",PLCI,INFO_IND_INFONUMBER(CMSG));
4716+ break;
4717+ case CAPI_CONNECT_ACTIVE:
4718+ PLCI = CONNECT_ACTIVE_IND_PLCI(CMSG);
4719+ if (option_verbose > 3) {
4720+ if (capidebug)
4721+ ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4722+ }
4723+// ast_log(LOG_ERROR,"CONNECT_ACTIVE_IND PLCI=%#x\n",PLCI);
4724+ break;
4725+ case CAPI_CONNECT_B3:
4726+ NCCI = CONNECT_B3_IND_NCCI(CMSG);
4727+ PLCI = (NCCI << 16) >> 16;
4728+ if (option_verbose > 3) {
4729+ if (capidebug)
4730+ ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4731+ }
4732+// ast_log(LOG_ERROR,"CONNECT_B3_IND NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
4733+ break;
4734+ case CAPI_CONNECT_B3_ACTIVE:
4735+ NCCI = CONNECT_B3_IND_NCCI(CMSG);
4736+ PLCI = (NCCI << 16) >> 16;
4737+ if (option_verbose > 3) {
4738+ if (capidebug)
4739+ ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4740+ }
4741+// ast_log(LOG_ERROR,"CONNECT_B3_ACTIVE_IND NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
4742+ break;
4743+ case CAPI_DATA_B3:
4744+ NCCI = DATA_B3_IND_NCCI(CMSG);
4745+ PLCI = (NCCI << 16) >> 16;
4746+// ast_log(LOG_ERROR,"DATA_B3_IND NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
4747+ break;
4748+ case CAPI_DISCONNECT_B3:
4749+ NCCI = DISCONNECT_B3_IND_NCCI(CMSG);
4750+ PLCI = (NCCI << 16) >> 16;
4751+ if (option_verbose > 1) {
4752+ if (capidebug)
4753+ ast_verbose(VERBOSE_PREFIX_2 "DISCONNECT_B3_IND NCCI=%#x\n",NCCI);
4754+ }
4755+ break;
4756+ case CAPI_DISCONNECT:
4757+ PLCI = DISCONNECT_IND_PLCI(CMSG);
4758+ if (option_verbose > 1) {
4759+ if (capidebug)
4760+ ast_verbose(VERBOSE_PREFIX_2 "DISCONNECT_IND PLCI=%#x REASON=%#x\n",PLCI,DISCONNECT_IND_REASON(CMSG));
4761+ }
4762+ break;
4763+ default:
4764+ ast_log(LOG_ERROR,"Command.Subcommand = %#x.%#x\n",CMSG->Command,CMSG->Subcommand);
4765+ }
4766+ break;
4767+ // confirmation msgs
4768+ case CAPI_CONF:
4769+ switch (CMSG->Command) {
4770+ case CAPI_FACILITY:
4771+ NCCI = FACILITY_CONF_NCCI(CMSG);
4772+ PLCI = (NCCI << 16) >> 16;
4773+ if (option_verbose > 2) {
4774+ if (FACILITY_CONF_FACILITYSELECTOR(CMSG) == 6) {
4775+ if (FACILITY_CONF_INFO(CMSG))
4776+ ast_verbose (VERBOSE_PREFIX_3 "Error setting up echo canceller (PLCI=%#x, Info=%#04x)\n", PLCI, FACILITY_CONF_INFO(CMSG));
4777+ else
4778+ ast_verbose (VERBOSE_PREFIX_3 "Echo canceller successfully set up (PLCI=%#x)\n",PLCI);
4779+ }
4780+ }
4781+ if (option_verbose > 3) {
4782+ if (capidebug)
4783+ ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4784+ }
4785+// ast_log(LOG_ERROR,"FACILITY_CONF NCCI=%#x INFO=%#x\n",(int)FACILITY_CONF_NCCI(CMSG),FACILITY_CONF_INFO(CMSG));
4786+ break;
4787+ case CAPI_INFO:
4788+ PLCI = INFO_CONF_PLCI(CMSG);
4789+// ast_log(LOG_ERROR,"INFO_CONF PLCI=%#x INFO=%#x\n",PLCI,INFO_CONF_INFO(CMSG));
4790+ break;
4791+ case CAPI_CONNECT:
4792+ PLCI = CONNECT_CONF_PLCI(CMSG);
4793+ if (option_verbose > 3) {
4794+ if (capidebug)
4795+ ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4796+ }
4797+// ast_log(LOG_ERROR,"CONNECT_CONF PLCI=%#x INFO=%#x MN=%#x\n",PLCI,CONNECT_CONF_INFO(CMSG),CMSG->Messagenumber);
4798+ break;
4799+ case CAPI_DISCONNECT:
4800+ PLCI = DISCONNECT_CONF_PLCI(CMSG);
4801+ if (option_verbose > 3) {
4802+ if (capidebug)
4803+ ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4804+ }
4805+// ast_log(LOG_ERROR,"DISCONNECT_CONF PLCI=%#x INFO=%#x MN=%#x\n",PLCI,DISCONNECT_CONF_INFO(CMSG),CMSG->Messagenumber);
4806+ break;
4807+ case CAPI_DISCONNECT_B3:
4808+ NCCI = DISCONNECT_B3_CONF_NCCI(CMSG);
4809+ PLCI = (NCCI << 16) >> 16;
4810+ if (option_verbose > 3) {
4811+ if (capidebug)
4812+ ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4813+ }
4814+// ast_log(LOG_ERROR,"DISCONNECT_B3_CONF NCCI=%#x INFO=%#x MN=%#x\n",NCCI,DISCONNECT_B3_CONF_INFO(CMSG),CMSG->Messagenumber);
4815+ break;
4816+ case CAPI_CONNECT_B3:
4817+ NCCI = CONNECT_B3_CONF_NCCI(CMSG);
4818+ PLCI = (NCCI << 16) >> 16;
4819+ if (option_verbose > 3) {
4820+ if (capidebug)
4821+ ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4822+ }
4823+// ast_log(LOG_ERROR,"CONNECT_B3_CONF PLCI=%#x INFO=%#x MN=%#x\n",PLCI,CONNECT_B3_CONF_INFO(CMSG),CMSG->Messagenumber);
4824+ break;
4825+ case CAPI_ALERT:
4826+ PLCI = ALERT_CONF_PLCI(CMSG);
4827+ if (option_verbose > 3) {
4828+ if (capidebug)
4829+ ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4830+ }
4831+// ast_log(LOG_ERROR,"ALERT_CONF PLCI=%#x\n",PLCI);
4832+ break;
4833+ case CAPI_DATA_B3:
4834+ NCCI = DATA_B3_CONF_NCCI(CMSG);
4835+ PLCI = (NCCI << 16) >> 16;
4836+ if (option_verbose > 5) {
4837+ if (capidebug)
4838+ ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4839+ }
4840+// ast_log(LOG_ERROR,"DATA_B3_CONF NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
4841+ break;
4842+ default:
4843+ ast_log(LOG_ERROR,"Command.Subcommand = %#x.%#x\n",CMSG->Command,CMSG->Subcommand);
4844+ }
4845+ break;
4846+ }
4847+ if (PLCI > 0) {
4848+ pipe_msg(PLCI,CMSG);
4849+ }
4850+
4851+}
4852+
4853+// module stuff, monitor...
4854+
4855+static void *do_monitor(void *data) {
4856+ unsigned int Info;
4857+ _cmsg *monCMSG;
4858+ for (;;) {
4859+/*
4860+ if (ast_mutex_lock(&monlock)) {
4861+ ast_log(LOG_ERROR,"Unable to get monitor lock!\n");
4862+ return NULL;
4863+ }
4864+ // do some nifty stuff
4865+ ast_mutex_unlock(&monlock);
4866+*/
4867+ monCMSG = malloc(sizeof(_cmsg));
4868+ memset(monCMSG,0,sizeof(_cmsg));
4869+ switch(Info = check_wait_get_cmsg(monCMSG)) {
4870+ case 0x0000:
4871+ if (option_verbose > 8) {
4872+ if (capidebug)
4873+ ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(monCMSG));
4874+ }
4875+ capi_handle_msg(monCMSG);
4876+ break;
4877+ case 0x1104:
4878+ // CAPI queue is empty
4879+ break;
4880+ default:
4881+ // something is wrong!
4882+ break;
4883+ } //switch
4884+ free(monCMSG);
4885+ } // for
4886+ // never reached
4887+ return NULL;
4888+}
4889+
4890+#ifdef CAPI_GAIN
4891+static void capi_gains(struct ast_capi_gains *g,float rxgain,float txgain) {
4892+ int i=0;
4893+ int x=0;
4894+ if (rxgain != 1.0) {
4895+ for (i=0;i<256;i++) {
4896+ x = (int)(((float)capiXLAW2INT(i)) * rxgain);
4897+ if (x > 32767) x = 32767;
4898+ if (x < -32767) x = -32767;
4899+ g->rxgains[i] = capiINT2XLAW(x);
4900+ }
4901+ } else {
4902+ for (i=0;i<256;i++) {
4903+ g->rxgains[i] = i;
4904+ }
4905+ }
4906+ if (txgain != 1.0) {
4907+ for (i=0;i<256;i++) {
4908+ x = (int)(((float)capiXLAW2INT(i)) * txgain);
4909+ if (x > 32767) x = 32767;
4910+ if (x < -32767) x = -32767;
4911+ g->txgains[i] = capiINT2XLAW(x);
4912+ }
4913+ } else {
4914+ for (i=0;i<256;i++) {
4915+ g->txgains[i] = i;
4916+ }
4917+ }
4918+
4919+}
4920+#endif
4921+#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
4922+int mkif(char *incomingmsn,char *context,char *controllerstr,int devices,int softdtmf,int echocancel,int ecoption,int ectail, char *prefix, int isdnmode, int es,float rxgain,float txgain, char *deflect2, char *accountcode, unsigned int callgroup, unsigned int group) {
4923+#else
4924+int mkif(char *incomingmsn,char *context,char *controllerstr,int devices,int softdtmf,int echocancel,int ecoption,int ectail, char *prefix, int isdnmode, int es,float rxgain,float txgain, char *accountcode, unsigned int callgroup, unsigned int group) {
4925+#endif
4926+ struct ast_capi_pvt *tmp;
4927+ int i=0;
4928+ char buffer[100];
4929+ char *contr;
4930+ unsigned long contrmap=0;
4931+
4932+ for (i=0;i<devices;i++) {
4933+ tmp = malloc(sizeof(struct ast_capi_pvt));
4934+ memset(tmp, 0, sizeof(struct ast_capi_pvt));
4935+ if (tmp) {
4936+ ast_mutex_init(&(tmp->lock));
4937+ strncpy(tmp->context, context, sizeof(tmp->context)-1);
4938+ strncpy(tmp->incomingmsn, incomingmsn, sizeof(tmp->incomingmsn)-1);
4939+ strncpy(tmp->prefix, prefix, sizeof(tmp->prefix)-1);
4940+ strncpy(tmp->accountcode, accountcode, sizeof(tmp->accountcode)-1);
4941+
4942+ strncpy(buffer,controllerstr,sizeof(buffer)-1);
4943+ contr = strtok(buffer,",");
4944+ while (contr != NULL) {
4945+ contrmap |= (1 << atoi(contr));
4946+ if (capi_controllers[atoi(contr)]) {
4947+ capi_controllers[atoi(contr)]->isdnmode = isdnmode;
4948+ // ast_log(LOG_NOTICE, "contr %d isdnmode %d\n",atoi(contr),isdnmode);
4949+ }
4950+ contr = strtok(NULL,",");
4951+ }
4952+ tmp->controllers = contrmap;
4953+ capi_used_controllers |= contrmap;
4954+ tmp->controller = 0;
4955+ tmp->CLIR = 0;
4956+ tmp->earlyB3 = -1;
4957+ tmp->onholdPLCI = 0;
4958+ tmp->doEC = echocancel;
4959+ tmp->ecOption = ecoption;
4960+ tmp->ecTail = ectail;
4961+ tmp->isdnmode = isdnmode;
4962+ tmp->doES = es;
4963+ tmp->callgroup = callgroup;
4964+ tmp->group = group;
4965+#ifdef CAPI_ES
4966+#endif
4967+#ifdef CAPI_GAIN
4968+ tmp->rxgain = rxgain;
4969+ tmp->txgain = txgain;
4970+ capi_gains(&tmp->g,rxgain,txgain);
4971+#endif
4972+#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
4973+ strncpy(tmp->deflect2, deflect2, sizeof(tmp->deflect2)-1);
4974+#endif
4975+#ifndef CAPI_FORCE_SOFTWARE_DTMF
4976+ if (softdtmf == 1) {
4977+#endif
4978+ tmp->doDTMF = 1;
4979+#ifndef CAPI_FORCE_SOFTWARE_DTMF
4980+ } else {
4981+ tmp->doDTMF = 0;
4982+ }
4983+#endif
4984+ tmp->next = iflist; // prepend
4985+ iflist = tmp;
4986+ // ast_log(LOG_NOTICE, "ast_capi_pvt(%s,%s,%#x,%d) (%d,%d,%d) (%d)(%f/%f) %d\n",tmp->incomingmsn,tmp->context,(int)tmp->controllers,devices,tmp->doEC,tmp->ecOption,tmp->ecTail,tmp->doES,tmp->rxgain,tmp->txgain,callgroup);
4987+ if (option_verbose > 2) {
4988+ ast_verbose(VERBOSE_PREFIX_2 "ast_capi_pvt(%s,%s,%d,%d) (%d,%d,%d)\n",tmp->incomingmsn,tmp->context,tmp->controller,devices,tmp->doEC,tmp->ecOption,tmp->ecTail);
4989+ }
4990+
4991+ } else {
4992+ return -1;
4993+ }
4994+ }
4995+ return 0;
4996+}
4997+
4998+void supported_sservices(struct ast_capi_controller *cp) {
4999+ MESSAGE_EXCHANGE_ERROR error;
5000+ _cmsg CMSG,CMSG2;
5001+ struct timeval tv;
5002+ char fac[20];
5003+
5004+ FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
5005+ FACILITY_REQ_CONTROLLER(&CMSG) = cp->controller;
5006+ FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 0x0003; // sservices
5007+ fac[0] = 3;
5008+ fac[1] = 0;
5009+ fac[2] = 0;
5010+ fac[3] = 0;
5011+ FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = (unsigned char *)&fac;
5012+ if ((error= _capi_put_cmsg(&CMSG)) != 0) {
5013+ ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
5014+ } else {
5015+ if (option_verbose > 5) {
5016+ ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_REQ (CONTROLLER=%#x)\n",cp->controller);
5017+ }
5018+ }
5019+
5020+ tv.tv_sec = 1;
5021+ tv.tv_usec = 0;
5022+ for (;;){
5023+ error = capi20_waitformessage(ast_capi_ApplID,&tv);
5024+ error = capi_get_cmsg(&CMSG2,ast_capi_ApplID);
5025+// error = check_wait_get_cmsg(&CMSG2);
5026+ if (error == 0) {
5027+ if (IS_FACILITY_CONF(&CMSG2)) {
5028+ if (option_verbose > 5) {
5029+ ast_verbose(VERBOSE_PREFIX_4 "FACILITY_CONF INFO = %#x\n",FACILITY_CONF_INFO(&CMSG2));
5030+ }
5031+ break;
5032+ }
5033+ }
5034+ }
5035+ // parse supported sservices
5036+ if (FACILITY_CONF_FACILITYSELECTOR(&CMSG2) == 0x0003) {
5037+ // success
5038+ if (FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[4] == 0) {
5039+ if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 1) == 1) {
5040+ cp->holdretrieve = 1;
5041+ if (option_verbose > 3)
5042+ ast_verbose(VERBOSE_PREFIX_4 "HOLD/RETRIEVE\n");
5043+ } else {
5044+ cp->holdretrieve = 0;
5045+ }
5046+ if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 2) >> 1) == 1) {
5047+ cp->terminalportability = 1;
5048+ if (option_verbose > 3)
5049+ ast_verbose(VERBOSE_PREFIX_4 "TERMINAL PORTABILITY\n");
5050+ } else {
5051+ cp->terminalportability = 0;
5052+ }
5053+ if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 4) >> 2) == 1) {
5054+ cp->ECT = 1;
5055+ if (option_verbose > 3)
5056+ ast_verbose(VERBOSE_PREFIX_4 "ECT\n");
5057+ } else {
5058+ cp->ECT = 0;
5059+ }
5060+ if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 8) >> 3) == 1) {
5061+ cp->threePTY = 1;
5062+ if (option_verbose > 3)
5063+ ast_verbose(VERBOSE_PREFIX_4 "3PTY\n");
5064+ } else {
5065+ cp->threePTY = 0;
5066+ }
5067+ if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 16) >> 4) == 1) {
5068+ cp->CF = 1;
5069+ if (option_verbose > 3)
5070+ ast_verbose(VERBOSE_PREFIX_4 "CF\n");
5071+ } else {
5072+ cp->CF = 0;
5073+ }
5074+ if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 32) >> 5) == 1) {
5075+ cp->CD = 1;
5076+ if (option_verbose > 3)
5077+ ast_verbose(VERBOSE_PREFIX_4 "CD\n");
5078+ } else {
5079+ cp->CD = 0;
5080+ }
5081+ if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 64) >> 6) == 1) {
5082+ cp->MCID = 1;
5083+ if (option_verbose > 3)
5084+ ast_verbose(VERBOSE_PREFIX_4 "MCID\n");
5085+ } else {
5086+ cp->MCID = 0;
5087+ }
5088+ if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 128) >> 7) == 1) {
5089+ cp->CCBS = 1;
5090+ if (option_verbose > 3)
5091+ ast_verbose(VERBOSE_PREFIX_4 "CCBS\n");
5092+ } else {
5093+ cp->CCBS = 0;
5094+ }
5095+ if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[7] & 1) == 1) {
5096+ cp->MWI = 1;
5097+ if (option_verbose > 3)
5098+ ast_verbose(VERBOSE_PREFIX_4 "MWI\n");
5099+ } else {
5100+ cp->MWI = 0;
5101+ }
5102+ if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[7] & 2) >> 1) == 1) {
5103+ cp->CCNR = 1;
5104+ if (option_verbose > 3)
5105+ ast_verbose(VERBOSE_PREFIX_4 "CCNR\n");
5106+ } else {
5107+ cp->CCNR = 0;
5108+ }
5109+ if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[7] & 4) >> 2) == 1) {
5110+ cp->CONF = 1;
5111+ if (option_verbose > 3)
5112+ ast_verbose(VERBOSE_PREFIX_4 "CONF\n");
5113+ } else {
5114+ cp->CONF = 0;
5115+ }
5116+ } else {
5117+ ast_log(LOG_NOTICE,"supplementary services info = %#x\n",(short)FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[1]);
5118+ }
5119+ } else {
5120+ ast_log(LOG_NOTICE,"unexpected FACILITY_SELECTOR = %#x\n",FACILITY_CONF_FACILITYSELECTOR(&CMSG2));
5121+ }
5122+}
5123+
5124+static int capi_info(int fd, int argc, char *argv[])
5125+{
5126+ int i=0;
5127+ if (argc != 2)
5128+ return RESULT_SHOWUSAGE;
5129+ for (i=1;i<=capi_num_controllers;i++) {
5130+ ast_mutex_lock(&contrlock);
5131+ if (capi_controllers[i] != NULL) {
5132+ ast_cli(fd,"Contr%d: %d B channels total, %d B channels free.\n",i,capi_controllers[i]->nbchannels,capi_controllers[i]->nfreebchannels);
5133+ }
5134+ ast_mutex_unlock(&contrlock);
5135+ }
5136+ return RESULT_SUCCESS;
5137+}
5138+
5139+static int capi_do_debug(int fd, int argc, char *argv[])
5140+{
5141+ if (argc != 2)
5142+ return RESULT_SHOWUSAGE;
5143+ capidebug = 1;
5144+ ast_cli(fd, "CAPI Debugging Enabled\n");
5145+ return RESULT_SUCCESS;
5146+}
5147+
5148+static int capi_no_debug(int fd, int argc, char *argv[])
5149+{
5150+ if (argc != 3)
5151+ return RESULT_SHOWUSAGE;
5152+ capidebug = 0;
5153+ ast_cli(fd, "CAPI Debugging Disabled\n");
5154+ return RESULT_SUCCESS;
5155+}
5156+
5157+static char info_usage[] =
5158+"Usage: capi info\n"
5159+" Show info about B channels.\n";
5160+
5161+static char debug_usage[] =
5162+"Usage: capi debug\n"
5163+" Enables dumping of CAPI packets for debugging purposes\n";
5164+
5165+static char no_debug_usage[] =
5166+"Usage: capi no debug\n"
5167+" Disables dumping of CAPI packets for debugging purposes\n";
5168+
5169+static struct ast_cli_entry cli_info =
5170+ { { "capi", "info", NULL }, capi_info, "Show CAPI info", info_usage };
5171+static struct ast_cli_entry cli_debug =
5172+ { { "capi", "debug", NULL }, capi_do_debug, "Enable CAPI debugging", debug_usage };
5173+static struct ast_cli_entry cli_no_debug =
5174+ { { "capi", "no", "debug", NULL }, capi_no_debug, "Disable CAPI debugging", no_debug_usage };
5175+
5176+static const struct ast_channel_tech capi_tech = {
5177+ .type = type,
5178+ .description = tdesc,
5179+#ifdef CAPI_ULAW
5180+ .capabilities = AST_FORMAT_ULAW,
5181+#else
5182+ .capabilities = AST_FORMAT_ALAW,
5183+#endif
5184+ .requester = capi_request,
5185+ .send_digit = capi_send_digit,
5186+ .send_text = NULL,
5187+ .call = capi_call,
5188+ .hangup = capi_hangup,
5189+ .answer = capi_answer,
5190+ .read = capi_read,
5191+ .write = capi_write,
5192+ .bridge = NULL,
5193+ .exception = NULL,
5194+ .indicate = capi_indicate,
5195+ .fixup = capi_fixup,
5196+ .setoption = NULL,
5197+};
5198+
5199+int load_module(void)
5200+{
5201+ struct ast_config *cfg;
5202+ struct ast_variable *v;
5203+ char *config = "capi.conf";
5204+ char incomingmsn[AST_MAX_EXTENSION]="";
5205+ char context[AST_MAX_EXTENSION]="";
5206+ char prefix[AST_MAX_EXTENSION]="";
5207+ char accountcode[20]="";
5208+ char *empty = "\0";
5209+ char deflect2[AST_MAX_EXTENSION]="";
5210+ char controllerstr[AST_MAX_EXTENSION]="";
5211+ int res = 0;
5212+ int controller=0;
5213+ int softdtmf=0;
5214+ int echocancel=1;
5215+ int ecoption=EC_OPTION_DISABLE_G165;
5216+ int ectail=EC_DEFAULT_TAIL;
5217+ int es=0;
5218+ float rxgain = 1.0;
5219+ float txgain = 1.0;
5220+ int isdnmode = 0;
5221+ unsigned int callgroup=0;
5222+ unsigned int group=0;
5223+ struct ast_capi_controller *cp;
5224+
5225+ cfg = ast_config_load(config);
5226+
5227+ /* We *must* have a config file otherwise stop immediately, well no... */
5228+ if (!cfg) {
5229+ ast_log(LOG_ERROR, "Unable to load config %s, CAPI disabled\n", config);
5230+ return 0;
5231+ }
5232+ if (ast_mutex_lock(&iflock)) {
5233+ ast_log(LOG_ERROR, "Unable to lock interface list???\n");
5234+ return -1;
5235+ }
5236+
5237+ strncpy(capi_national_prefix, AST_CAPI_NATIONAL_PREF, sizeof(capi_national_prefix)-1);
5238+ strncpy(capi_international_prefix, AST_CAPI_NATIONAL_PREF, sizeof(capi_national_prefix)-1);
5239+ v = ast_variable_browse(cfg, "general");
5240+ while(v) {
5241+ if (!strcasecmp(v->name, "nationalprefix")) {
5242+ strncpy(capi_national_prefix, v->value, sizeof(capi_national_prefix)-1);
5243+ } else if (!strcasecmp(v->name, "internationalprefix")) {
5244+ strncpy(capi_international_prefix, v->value, sizeof(capi_international_prefix)-1);
5245+ } else if (!strcasecmp(v->name, "rxgain")) {
5246+ if (sscanf(v->value,"%f",&rxgain) != 1) {
5247+ ast_log(LOG_ERROR,"invalid rxgain\n");
5248+ }
5249+ } else if (!strcasecmp(v->name, "txgain")) {
5250+ if (sscanf(v->value,"%f",&txgain) != 1) {
5251+ ast_log(LOG_ERROR,"invalid txgain\n");
5252+ }
5253+ }
5254+ v = v->next;
5255+ }
5256+
5257+
5258+
5259+
5260+ if (capi20_isinstalled() != 0) {
5261+ ast_log(LOG_WARNING,"CAPI not installed, CAPI disabled!\n");
5262+ return 0;
5263+ }
5264+
5265+ if (capi20_register(AST_CAPI_BCHANS,AST_CAPI_MAX_B3_BLOCKS,AST_CAPI_MAX_B3_BLOCK_SIZE,&ast_capi_ApplID) != 0) {
5266+ ast_log(LOG_NOTICE,"unable to register application at CAPI!\n");
5267+ return -1;
5268+ }
5269+
5270+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5271+ if (capi20_get_profile(0,&profile) != 0) {
5272+#else
5273+ if (capi20_get_profile(0,(unsigned char *)&profile) != 0) {
5274+#endif
5275+ ast_log(LOG_NOTICE,"unable to get CAPI profile!\n");
5276+ return -1;
5277+ } else {
5278+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5279+ capi_num_controllers = profile.wCtlr;
5280+#else
5281+ capi_num_controllers = profile.ncontrollers;
5282+#endif
5283+ if (option_verbose > 3)
5284+ ast_verbose(VERBOSE_PREFIX_3 "This box has %d capi controller(s).\n",capi_num_controllers);
5285+ for (controller=1;controller<=capi_num_controllers;controller++) {
5286+
5287+ memset(&profile,0,sizeof(profile));
5288+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5289+ capi20_get_profile(controller,&profile);
5290+#else
5291+ capi20_get_profile(controller,(unsigned char *)&profile);
5292+#endif
5293+ cp = malloc(sizeof(struct ast_capi_controller));
5294+ cp->controller = controller;
5295+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5296+ cp->nbchannels = profile.wNumBChannels;
5297+ cp->nfreebchannels = profile.wNumBChannels;
5298+ if (profile.dwGlobalOptions & CAPI_PROFILE_DTMF_SUPPORT) {
5299+#else
5300+ cp->nbchannels = profile.nbchannels;
5301+ cp->nfreebchannels = profile.nbchannels;
5302+ if ((profile.globaloptions & 8) >> 3 == 1) {
5303+#endif
5304+ if (option_verbose > 3)
5305+ ast_verbose(VERBOSE_PREFIX_3 "CAPI/contr%d supports DTMF\n",controller);
5306+ cp->dtmf = 1;
5307+ } else {
5308+ cp->dtmf = 0;
5309+ }
5310+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5311+ if (profile.dwGlobalOptions & CAPI_PROFILE_ECHO_CANCELLATION) {
5312+#else
5313+ if (profile.globaloptions2 & 1) {
5314+#endif
5315+ if (option_verbose > 3)
5316+ ast_verbose(VERBOSE_PREFIX_3 "CAPI/contr%d supports echo cancellation\n",controller);
5317+ cp->echocancel = 1;
5318+ } else {
5319+ cp->echocancel = 0;
5320+ }
5321+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5322+ if (profile.dwGlobalOptions & CAPI_PROFILE_SUPPLEMENTARY_SERVICES) {
5323+#else
5324+ if ((profile.globaloptions & 16) >> 4 == 1) {
5325+#endif
5326+ cp->sservices = 1;
5327+ } else {
5328+ cp->sservices = 0;
5329+ }
5330+ capi_controllers[controller] = cp;
5331+ if (cp->sservices == 1) {
5332+ if (option_verbose > 3)
5333+ ast_verbose(VERBOSE_PREFIX_3 "CAPI/contr%d supports supplementary services\n",controller);
5334+ supported_sservices(cp);
5335+ }
5336+ }
5337+ }
5338+
5339+ v = ast_variable_browse(cfg, "interfaces");
5340+ while(v) {
5341+ /* Create the interface list */
5342+ if (!strcasecmp(v->name, "devices")) {
5343+#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
5344+ if (mkif(incomingmsn,context,controllerstr,atoi(v->value),softdtmf,echocancel,ecoption,ectail, prefix, isdnmode, es,rxgain,txgain,deflect2,accountcode,callgroup, group)) {
5345+#else
5346+ if (mkif(incomingmsn,context,controllerstr,atoi(v->value),softdtmf,echocancel,ecoption,ectail, prefix, isdnmode, es,rxgain,txgain,accountcode,callgroup, group)) {
5347+#endif
5348+ ast_log(LOG_ERROR,"Error creating interface list\n");
5349+ return -1;
5350+ }
5351+ es=0;
5352+ strncpy(deflect2, empty, sizeof(deflect2)-1);
5353+ } else if (!strcasecmp(v->name, "context")) {
5354+ strncpy(context, v->value, sizeof(context)-1);
5355+ } else if (!strcasecmp(v->name, "incomingmsn")) {
5356+ strncpy(incomingmsn, v->value, sizeof(incomingmsn)-1);
5357+ } else if (!strcasecmp(v->name, "controller")) {
5358+ strncpy(controllerstr, v->value, sizeof(controllerstr)-1);
5359+ } else if (!strcasecmp(v->name, "softdtmf")) {
5360+ softdtmf = atoi(v->value);
5361+ } else if (!strcasecmp(v->name, "echosquelch")) {
5362+ es = atoi(v->value);
5363+ } else if (!strcasecmp(v->name, "callgroup")) {
5364+ callgroup = ast_get_group(v->value);
5365+ } else if (!strcasecmp(v->name, "group")) {
5366+ group = ast_get_group(v->value);
5367+ } else if (!strcasecmp(v->name, "deflect")) {
5368+ strncpy(deflect2, v->value, sizeof(deflect2)-1);
5369+ } else if (!strcasecmp(v->name, "rxgain")) {
5370+ if (sscanf(v->value,"%f",&rxgain) != 1) {
5371+ ast_log(LOG_ERROR,"invalid rxgain\n");
5372+ }
5373+ } else if (!strcasecmp(v->name, "txgain")) {
5374+ if (sscanf(v->value,"%f",&txgain) != 1) {
5375+ ast_log(LOG_ERROR,"invalid txgain\n");
5376+ }
5377+ } else if (!strcasecmp(v->name, "echocancel")) {
5378+ if (!strcasecmp(v->value, "yes") || !strcasecmp(v->value, "1") || !strcasecmp(v->value, "on")) {
5379+ echocancel=1;
5380+ ecoption=EC_OPTION_DISABLE_G165;
5381+ }
5382+ else if (!strcasecmp(v->value, "no") || !strcasecmp(v->value, "0") || !strcasecmp(v->value, "off")) {
5383+ echocancel=0;
5384+ ecoption=0;
5385+ }
5386+ else if (!strcasecmp(v->value, "g165") || !strcasecmp(v->value, "g.165")) {
5387+ echocancel=1;
5388+ ecoption=EC_OPTION_DISABLE_G165;
5389+ }
5390+ else if (!strcasecmp(v->value, "g164") || !strcasecmp(v->value, "g.164")) {
5391+ echocancel=1;
5392+ ecoption=EC_OPTION_DISABLE_G164_OR_G165;
5393+ }
5394+ else if (!strcasecmp(v->value, "force")) {
5395+ echocancel=1;
5396+ ecoption=EC_OPTION_DISABLE_NEVER;
5397+ }
5398+ else {
5399+ ast_log(LOG_ERROR,"Unknown echocancel parameter \"%s\" -- ignoring\n",v->value);
5400+ }
5401+ } else if (!strcasecmp(v->name, "echotail")) {
5402+ ectail = atoi(v->value);
5403+ if (ectail > 255)
5404+ ectail = 255;
5405+ } else if (!strcasecmp(v->name, "prefix")) {
5406+ strncpy(prefix, v->value, sizeof(prefix)-1);
5407+ } else if (!strcasecmp(v->name, "accountcode")) {
5408+ strncpy(accountcode, v->value, sizeof(accountcode)-1);
5409+ } else if (!strcasecmp(v->name, "isdnmode")) {
5410+ if (!strcasecmp(v->value, "ptp") || !strcasecmp(v->value, "1"))
5411+ isdnmode = 1;
5412+ else if (!strcasecmp(v->value, "ptm") || !strcasecmp(v->value, "0") || !strcasecmp(v->value, "ptmp"))
5413+ isdnmode = 0;
5414+ else
5415+ ast_log(LOG_ERROR,"Unknown isdnmode parameter \"%s\" -- ignoring\n",v->value);
5416+
5417+ }
5418+
5419+ v = v->next;
5420+ }
5421+ ast_config_destroy(cfg);
5422+
5423+ for (controller=1;controller<=capi_num_controllers;controller++) {
5424+ if (capi_used_controllers & (1 << controller)) {
5425+ if (ListenOnController(ALL_SERVICES,controller) != 0) {
5426+ ast_log(LOG_ERROR,"Unable to listen on contr%d\n",controller);
5427+ } else {
5428+ if (option_verbose > 2)
5429+ ast_verbose(VERBOSE_PREFIX_3 "listening on contr%d CIPmask = %#x\n",controller,ALL_SERVICES);
5430+ }
5431+ } else {
5432+ ast_log(LOG_WARNING,"Unused contr%d\n",controller);
5433+ }
5434+ }
5435+
5436+
5437+ ast_mutex_unlock(&iflock);
5438+
5439+ if (ast_channel_register(&capi_tech)) {
5440+ ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
5441+ unload_module();
5442+ return -1;
5443+ }
5444+
5445+ ast_cli_register(&cli_info);
5446+ ast_cli_register(&cli_debug);
5447+ ast_cli_register(&cli_no_debug);
5448+
5449+ if (ast_mutex_lock(&monlock)) {
5450+ ast_log(LOG_WARNING,"Unable to get monitor lock!\n");
5451+ return -1;
5452+ }
5453+ if (monitor_thread == pthread_self()) {
5454+ ast_mutex_unlock(&monlock);
5455+ ast_log(LOG_WARNING,"Unable to kill myself!\n");
5456+ return -1;
5457+ }
5458+
5459+ if (ast_pthread_create(&monitor_thread,NULL,do_monitor,NULL) < 0) {
5460+ ast_mutex_unlock(&monlock);
5461+ ast_log(LOG_ERROR,"Unable to start monitor thread!\n");
5462+ return -1;
5463+ }
5464+
5465+ return res;
5466+}
5467+
5468+
5469+int unload_module()
5470+{
5471+ if (capi20_release(ast_capi_ApplID) != 0)
5472+ ast_log(LOG_WARNING,"Unable to unregister from CAPI!\n");
5473+ ast_channel_unregister(&capi_tech);
5474+ return 0;
5475+}
5476+
5477+int usecount()
5478+{
5479+ int res;
5480+ ast_mutex_lock(&usecnt_lock);
5481+ res = usecnt;
5482+ ast_mutex_unlock(&usecnt_lock);
5483+ return res;
5484+}
5485+
5486+char *description()
5487+{
5488+ return desc;
5489+}
5490+
5491+
5492+char *key()
5493+{
5494+ return ASTERISK_GPL_KEY;
5495+}
b684b13b
MT
5496diff -urN asterisk-1.2.9.1.orig/channels/chan_features.c asterisk-1.2.9.1/channels/chan_features.c
5497--- asterisk-1.2.9.1.orig/channels/chan_features.c 2006-01-25 19:39:44.000000000 +0100
5498+++ asterisk-1.2.9.1/channels/chan_features.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
5499@@ -438,7 +438,7 @@
5500 }
5501 ast_mutex_unlock(&featurelock);
5502 if (!tmp) {
5503- chan = ast_request(tech, format, dest, &status);
5504+ chan = ast_request(tech, format, dest, &status, NULL);
5505 if (!chan) {
5506 ast_log(LOG_NOTICE, "Unable to allocate subchannel '%s/%s'\n", tech, dest);
5507 return NULL;
b684b13b
MT
5508diff -urN asterisk-1.2.9.1.orig/channels/chan_iax2.c asterisk-1.2.9.1/channels/chan_iax2.c
5509--- asterisk-1.2.9.1.orig/channels/chan_iax2.c 2006-06-06 17:48:00.000000000 +0200
5510+++ asterisk-1.2.9.1/channels/chan_iax2.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
5511@@ -11,6 +11,9 @@
5512 * the project provides a web site, mailing lists and IRC
5513 * channels for your use.
5514 *
5515+ * Hangup cause signalling implementation by
5516+ * Levent Guendogdu <levon@feature-it.com>
5517+ *
5518 * This program is free software, distributed under the terms of
5519 * the GNU General Public License Version 2. See the LICENSE file
5520 * at the top of the source tree.
b684b13b 5521@@ -3068,7 +3071,7 @@
5e69ef1a
MT
5522 memset(&ied, 0, sizeof(ied));
5523 ast_mutex_lock(&iaxsl[callno]);
5524 if (callno && iaxs[callno]) {
5525- ast_log(LOG_DEBUG, "We're hanging up %s now...\n", c->name);
5526+ ast_log(LOG_DEBUG, "We're hanging up %s with cause %i now...\n", c->name, c->hangupcause);
5527 alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
5528 /* Send the hangup unless we have had a transmission error or are already gone */
5529 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
b684b13b 5530@@ -3120,7 +3123,8 @@
5e69ef1a
MT
5531 static struct ast_frame *iax2_read(struct ast_channel *c)
5532 {
5533 static struct ast_frame f = { AST_FRAME_NULL, };
5534- ast_log(LOG_NOTICE, "I should never be called!\n");
5535+ if (option_verbose > 3)
5536+ ast_log(LOG_NOTICE, "I should never be called!\n");
5537 return &f;
5538 }
5539
b684b13b
MT
5540diff -urN asterisk-1.2.9.1.orig/channels/chan_sip.c asterisk-1.2.9.1/channels/chan_sip.c
5541--- asterisk-1.2.9.1.orig/channels/chan_sip.c 2006-05-25 19:18:01.000000000 +0200
5542+++ asterisk-1.2.9.1/channels/chan_sip.c 2006-06-09 10:25:04.000000000 +0200
5543@@ -603,6 +603,7 @@
5e69ef1a
MT
5544 unsigned int flags; /*!< SIP_ flags */
5545 int timer_t1; /*!< SIP timer T1, ms rtt */
5546 unsigned int sipoptions; /*!< Supported SIP sipoptions on the other end */
5547+ int dialog_established; /*!< SIP dialog established */
5548 int capability; /*!< Special capability (codec) */
5549 int jointcapability; /*!< Supported capability at both ends (codecs ) */
5550 int peercapability; /*!< Supported peer capability */
b684b13b 5551@@ -626,6 +627,7 @@
5e69ef1a
MT
5552 char refer_to[AST_MAX_EXTENSION]; /*!< Place to store REFER-TO extension */
5553 char referred_by[AST_MAX_EXTENSION]; /*!< Place to store REFERRED-BY extension */
b684b13b 5554 char refer_contact[SIP_LEN_CONTACT]; /*!< Place to store Contact info from a REFER extension */
5e69ef1a
MT
5555+ char refer_replaces[AST_MAX_EXTENSION]; /*!< Place to store Replaces header of REFER-TO header */
5556 struct sip_pvt *refer_call; /*!< Call we are referring */
5557 struct sip_route *route; /*!< Head of linked list of routing steps (fm Record-Route) */
5558 int route_persistant; /*!< Is this the "real" route? */
b684b13b 5559@@ -645,6 +647,7 @@
5e69ef1a
MT
5560 char peername[256]; /*!< [peer] name, not set if [user] */
5561 char authname[256]; /*!< Who we use for authentication */
5562 char uri[256]; /*!< Original requested URI */
b684b13b
MT
5563+ char origuri[SIP_LEN_CONTACT]; /*!< REAL! Original requested URI */
5564 char okcontacturi[SIP_LEN_CONTACT]; /*!< URI from the 200 OK on INVITE */
5e69ef1a
MT
5565 char peersecret[256]; /*!< Password */
5566 char peermd5secret[256];
b684b13b
MT
5567@@ -768,6 +771,9 @@
5568 int callingpres; /*!< Calling id presentation */
5569 int inUse; /*!< Number of calls in use */
5570 int call_limit; /*!< Limit of concurrent calls */
5571+ int max_regs; /*!< Limit of concurrent registrations */
5572+ int subpeer; /*!< Peer entry used for multiple registrations */
5573+ char reg_callid[80]; /*!< Call-ID used for registration */
5574 char vmexten[AST_MAX_EXTENSION]; /*!< Dialplan extension for MWI notify message*/
5575 char mailbox[AST_MAX_EXTENSION]; /*!< Mailbox setting for MWI checks */
5576 char language[MAX_LANGUAGE]; /*!< Default language for prompts */
5577@@ -928,7 +934,7 @@
5e69ef1a
MT
5578 static int determine_firstline_parts(struct sip_request *req);
5579 static void sip_dump_history(struct sip_pvt *dialog); /* Dump history to LOG_DEBUG at end of dialog, before destroying data */
5580 static const struct cfsubscription_types *find_subscription_type(enum subscriptiontype subtype);
5581-static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate);
5582+static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate, char *cid_num, char *cid_name);
5583 static char *gettag(struct sip_request *req, char *header, char *tagbuf, int tagbufsize);
5584
5585 /*! \brief Definition of this channel for PBX channel registration */
b684b13b 5586@@ -1311,7 +1317,7 @@
5e69ef1a
MT
5587 /* If this is a subscription, tell the phone that we got a timeout */
5588 if (p->subscribed) {
5589 p->subscribed = TIMEOUT;
5590- transmit_state_notify(p, AST_EXTENSION_DEACTIVATED, 1, 1); /* Send first notification */
5591+ transmit_state_notify(p, AST_EXTENSION_DEACTIVATED, 1, 1, NULL, NULL); /* Send first notification */
5592 p->subscribed = NONE;
5593 append_history(p, "Subscribestatus", "timeout");
5594 return 10000; /* Reschedule this destruction so that we know that it's gone */
b684b13b 5595@@ -3150,16 +3156,30 @@
5e69ef1a
MT
5596
5597 /*! \brief find_call: Connect incoming SIP message to current dialog or create new dialog structure */
5598 /* Called by handle_request, sipsock_read */
5599-static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *sin, const int intended_method)
5600+static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *sin, const int intended_method, const int replaces_callid)
5601 {
5602 struct sip_pvt *p;
5603 char *callid;
5604 char *tag = "";
5605+ char *replaces;
5606 char totag[128];
5607 char fromtag[128];
5608+ char *c;
5609
5610 callid = get_header(req, "Call-ID");
5611
5612+ if (replaces_callid) {
5613+ replaces = get_header(req, "Replaces");
5614+ c = strchr(replaces, ';');
5615+ if (c)
5616+ *c = '\0';
5617+ if (!ast_strlen_zero(replaces)) {
5618+ callid = replaces;
5619+ } else {
5620+ return NULL;
5621+ }
5622+ }
5623+
5624 if (pedanticsipchecking) {
5625 /* In principle Call-ID's uniquely identify a call, but with a forking SIP proxy
5626 we need more to identify a branch - so we have to check branch, from
b684b13b 5627@@ -4141,6 +4161,7 @@
5e69ef1a
MT
5628 if (sipmethod == SIP_CANCEL) {
5629 c = p->initreq.rlPart2; /* Use original URI */
5630 } else if (sipmethod == SIP_ACK) {
5631+// XXX+ } else if (!strcasecmp(msg, "ACK") && !p->dialog_established) {
5632 /* Use URI from Contact: in 200 OK (if INVITE)
5633 (we only have the contacturi on INVITEs) */
5634 if (!ast_strlen_zero(p->okcontacturi))
b684b13b 5635@@ -4907,13 +4928,15 @@
5e69ef1a
MT
5636 ast_build_string(&invite, &invite_max, ";%s", p->options->uri_options);
5637
5638 ast_copy_string(p->uri, invite_buf, sizeof(p->uri));
5639+ ast_copy_string(p->origuri, invite, sizeof(p->origuri));
5640
5f892677
MT
5641 if (sipmethod == SIP_NOTIFY && !ast_strlen_zero(p->theirtag)) {
5642 /* If this is a NOTIFY, use the From: tag in the subscribe (RFC 3265) */
5643 snprintf(to, sizeof(to), "<sip:%s>;tag=%s", p->uri, p->theirtag);
5644 } else if (p->options && p->options->vxml_url) {
5645 /* If there is a VXML URL append it to the SIP URL */
5e69ef1a
MT
5646- snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url);
5647+// snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url);
5648+ snprintf(to, sizeof(to), "<%s;%s>", p->uri, p->options->vxml_url);
5649 } else {
5650 snprintf(to, sizeof(to), "<%s>", p->uri);
5651 }
b684b13b 5652@@ -4970,6 +4993,11 @@
5e69ef1a
MT
5653 if (!ast_strlen_zero(p->referred_by))
5654 add_header(&req, "Referred-By", p->referred_by);
5655 }
5656+ if (sipmethod == SIP_INVITE) {
5657+ if (!ast_strlen_zero(p->refer_replaces)) {
5658+ add_header(&req, "Replaces", p->refer_replaces);
5659+ }
5660+ }
5661 #ifdef OSP_SUPPORT
5662 if ((req.method != SIP_OPTIONS) && p->options && !ast_strlen_zero(p->options->osptoken)) {
5663 ast_log(LOG_DEBUG,"Adding OSP Token: %s\n", p->options->osptoken);
b684b13b 5664@@ -5044,8 +5072,7 @@
5e69ef1a
MT
5665 }
5666
5667 /*! \brief transmit_state_notify: Used in the SUBSCRIBE notification subsystem ----*/
5668-static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate)
5669-{
5670+static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate, char *cid_num, char *cid_name) {
5671 char tmp[4000], from[256], to[256];
5672 char *t = tmp, *c, *a, *mfrom, *mto;
5673 size_t maxbytes = sizeof(tmp);
b684b13b 5674@@ -5189,10 +5216,19 @@
5e69ef1a
MT
5675 case DIALOG_INFO_XML: /* SNOM subscribes in this format */
5676 ast_build_string(&t, &maxbytes, "<?xml version=\"1.0\"?>\n");
5677 ast_build_string(&t, &maxbytes, "<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" version=\"%d\" state=\"%s\" entity=\"%s\">\n", p->dialogver++, full ? "full":"partial", mto);
5678- if ((state & AST_EXTENSION_RINGING) && global_notifyringing)
5679- ast_build_string(&t, &maxbytes, "<dialog id=\"%s\" direction=\"recipient\">\n", p->exten);
5680- else
5681+ if ((state & AST_EXTENSION_RINGING) && global_notifyringing) {
5682+ ast_build_string(&t, &maxbytes, "<dialog id=\"%s\" direction=\"recipient\">\n", p->exten);
5683+ if (cid_num) {
5684+ ast_build_string(&t, &maxbytes, "<local><identity display=\"%s\">%s</identity><target uri=\"%s\"/></local>\n", p->exten, p->exten, mfrom);
5685+ if (cid_name && !ast_strlen_zero(cid_name)) {
5686+ ast_build_string(&t, &maxbytes, "<remote><identity display=\"%s\">sip:%s@%s</identity><target uri=\"sip:%s%s@%s\"/></remote>\n", cid_name, cid_num, p->fromdomain, ast_pickup_ext(), p->exten, p->fromdomain);
5687+ } else {
5688+ ast_build_string(&t, &maxbytes, "<remote><identity display=\"%s\">sip:%s@%s</identity><target uri=\"sip:%s%s@%s\"/></remote>\n", cid_num, cid_num, p->fromdomain, ast_pickup_ext(), p->exten, p->fromdomain);
5689+ }
5690+ }
5691+ } else {
5692 ast_build_string(&t, &maxbytes, "<dialog id=\"%s\">\n", p->exten);
5693+ }
5694 ast_build_string(&t, &maxbytes, "<state>%s</state>\n", statestring);
5695 ast_build_string(&t, &maxbytes, "</dialog>\n</dialog-info>\n");
5696 break;
b684b13b
MT
5697@@ -6019,8 +6055,10 @@
5698 p->expire = -1;
5699 pvt->expiry = expiry;
5700 snprintf(data, sizeof(data), "%s:%d:%d:%s:%s", ast_inet_ntoa(iabuf, sizeof(iabuf), p->addr.sin_addr), ntohs(p->addr.sin_port), expiry, p->username, p->fullcontact);
5701- if (!ast_test_flag((&p->flags_page2), SIP_PAGE2_RT_FROMCONTACT))
5702+ if (!ast_test_flag((&p->flags_page2), SIP_PAGE2_RT_FROMCONTACT)) {
5703+ // ast_log(LOG_NOTICE, "updating SIP/Registry for peer %s with data %s\n", p->name, data);
5704 ast_db_put("SIP/Registry", p->name, data);
5705+ }
5706 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Registered\r\n", p->name);
5707 if (inaddrcmp(&p->addr, &oldsin)) {
5708 sip_poke_peer(p);
5709@@ -6411,7 +6449,7 @@
5e69ef1a
MT
5710 /*! \brief cb_extensionstate: Callback for the devicestate notification (SUBSCRIBE) support subsystem ---*/
5711 /* If you add an "hint" priority to the extension in the dial plan,
5712 you will get notifications on device state changes */
5713-static int cb_extensionstate(char *context, char* exten, int state, void *data)
5714+static int cb_extensionstate(char *context, char* exten, int state, void *data, char *cid_num, char *cid_name)
5715 {
5716 struct sip_pvt *p = data;
5717
b684b13b 5718@@ -6430,7 +6468,7 @@
5e69ef1a
MT
5719 p->laststate = state;
5720 break;
5721 }
5722- transmit_state_notify(p, state, 1, 1);
5723+ transmit_state_notify(p, state, 1, 1, cid_num, cid_name);
5724
5725 if (option_debug > 1)
5726 ast_verbose(VERBOSE_PREFIX_1 "Extension Changed %s new state %s for Notify User %s\n", exten, ast_extension_state2str(state), p->username);
b684b13b
MT
5727@@ -6456,7 +6494,13 @@
5728 char *name, *c;
5729 char *t;
5730 char *domain;
5731-
5732+ char *callid;
5733+ struct sip_peer *clone;
5734+ char clone_name[256];
5735+ int found = 0;
5736+ struct sip_peer *recycle_peer = NULL;
5737+ char peer_name[256];
5738+
5739 /* Terminate URI */
5740 t = uri;
5741 while(*t && (*t > 32) && (*t != ';'))
5742@@ -6505,9 +6549,68 @@
5743 if (!ast_test_flag(&peer->flags_page2, SIP_PAGE2_DYNAMIC)) {
5744 ast_log(LOG_ERROR, "Peer '%s' is trying to register, but not configured as host=dynamic\n", peer->name);
5745 } else {
5746+ callid = get_header(req, "Call-ID");
5747+ ast_copy_string(peer_name, peer->name, sizeof(peer_name));
5748+ if (peer->max_regs > 1) {
5749+ int i = 0;
5750+ /* check if peer matches callid */
5751+ if ((peer->expire > -1) && (!strncmp(peer->reg_callid, callid, strlen(callid)))) {
5752+ // ast_log(LOG_NOTICE, "peer->reg_callid %s, req->callid %s found in peer\n", peer->reg_callid, callid);
5753+ found++;
5754+ } else {
5755+ /* otherwise check subpeers for callid */
5756+ for (i=0; i<peer->max_regs - 1; i++) {
5757+ snprintf(clone_name, sizeof(clone_name), "%s@%d", peer->name, i);
5758+ // ast_log(LOG_NOTICE, "checking subpeer %s\n", clone_name);
5759+ clone = find_peer(clone_name, NULL, 1);
5760+ if (clone && (clone->expire > -1)) {
5761+ if (!strncmp(clone->reg_callid, callid, strlen(callid))) {
5762+ // ast_log(LOG_NOTICE, "clone->reg_callid %s, req->callid %s found in subpeer\n", clone->reg_callid, callid);
5763+ found++;
5764+ peer = clone;
5765+ break;
5766+ }
5767+ }
5768+ }
5769+ }
5770+ if (!found) {
5771+ // ast_log(LOG_NOTICE, "did not find callid in peer or subpeer\n");
5772+ /* choose the next best peer or subpeer (that means: find the peer with the smalles expiry time */
5773+ if (peer->expire == -1) {
5774+ recycle_peer = peer;
5775+ // ast_log(LOG_NOTICE, "peer %s expiry %d\n", peer->name, peer->expire);
5776+ } else {
5777+ for (i=0; i<peer->max_regs - 1; i++) {
5778+ snprintf(clone_name, sizeof(clone_name), "%s@%d", peer->name, i);
5779+ clone = find_peer(clone_name, NULL, 1);
5780+ if (clone) {
5781+ if (clone->expire == -1) {
5782+ recycle_peer = clone;
5783+ break;
5784+ }
5785+ // ast_log(LOG_NOTICE, "clone %s expiry %d\n", clone->name, clone->expire);
5786+ }
5787+ }
5788+ }
5789+ if (recycle_peer) {
5790+ peer = recycle_peer;
5791+ ast_copy_string(peer_name, peer->name, sizeof(peer_name));
5792+ // ast_log(LOG_NOTICE, "recycling peer %s\n", peer->name);
5793+ if (peer->subpeer) {
5794+ i = strchr(peer_name, '@') - peer_name;
5795+ if (i < sizeof(peer_name))
5796+ peer_name[i] = '\0';
5797+ // ast_log(LOG_NOTICE, "i = %d\n", i);
5798+ }
5799+ } else {
5800+ /* deny registration */
5801+ peer_name[0] = '\0';
5802+ }
5803+ }
5804+ }
5805 ast_copy_flags(p, peer, SIP_NAT);
5806 transmit_response(p, "100 Trying", req);
5807- if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), peer->name, peer->secret, peer->md5secret, SIP_REGISTER, uri, 0, ignore))) {
5808+ if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), peer_name, peer->secret, peer->md5secret, SIP_REGISTER, uri, 0, ignore))) {
5809 sip_cancel_destroy(p);
5810 switch (parse_register_contact(p, peer, req)) {
5811 case PARSE_REGISTER_FAILED:
5812@@ -6527,6 +6630,7 @@
5813 transmit_response_with_date(p, "200 OK", req);
5814 peer->lastmsgssent = -1;
5815 res = 0;
5816+ ast_copy_string(peer->reg_callid, callid, sizeof(peer->reg_callid));
5817 break;
5818 }
5819 }
5820@@ -6872,6 +6976,11 @@
5821 /* XXX The refer_to could contain a call on an entirely different machine, requiring an
5822 INVITE with a replaces header -anthm XXX */
5823 /* The only way to find out is to use the dialplan - oej */
5824+ ast_copy_string(sip_pvt->refer_to, refer_to, sizeof(sip_pvt->refer_to));
5825+ ast_copy_string(sip_pvt->referred_by, referred_by, sizeof(sip_pvt->referred_by));
5826+ ast_copy_string(sip_pvt->refer_contact, h_contact, sizeof(sip_pvt->refer_contact));
5827+ ast_copy_string(sip_pvt->refer_replaces, replace_callid, sizeof(sip_pvt->referred_by));
5828+ return 2;
5829 }
5830 } else if (ast_exists_extension(NULL, transfercontext, refer_to, 1, NULL) || !strcmp(refer_to, ast_parking_ext())) {
5831 /* This is an unsupervised transfer (blind transfer) */
5832@@ -7592,6 +7701,8 @@
5833 int peers_offline = 0;
5834 char *id;
5835 char idtext[256] = "";
5836+ char *tmp;
5837+ int i = 0;
5838
5839 if (s) { /* Manager - get ActionID */
5840 id = astman_get_header(m,"ActionID");
5841@@ -7634,6 +7745,7 @@
5842 else
5843 ast_copy_string(name, iterator->name, sizeof(name));
5844
5845+ if ((iterator->expire != -1) || (iterator->subpeer != 1)) {
5846 pstatus = peer_status(iterator, status, sizeof(status));
5847 if (pstatus)
5848 peers_online++;
5849@@ -7650,14 +7762,24 @@
5850 }
5851 }
5852
5853- snprintf(srch, sizeof(srch), FORMAT, name,
5854+ }
5855+ /* multiple registration, peer used ? */
5856+ if ((iterator->expire != -1) || (iterator->subpeer != 1)) {
5857+ snprintf(srch, sizeof(srch), FORMAT, name,
5858 iterator->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), iterator->addr.sin_addr) : "(Unspecified)",
5859 ast_test_flag(&iterator->flags_page2, SIP_PAGE2_DYNAMIC) ? " D " : " ", /* Dynamic or not? */
5860 (ast_test_flag(iterator, SIP_NAT) & SIP_NAT_ROUTE) ? " N " : " ", /* NAT=yes? */
5861 iterator->ha ? " A " : " ", /* permit/deny */
5862 ntohs(iterator->addr.sin_port), status);
5863+ }
5864
5865 if (!s) {/* Normal CLI list */
5866+ if ((iterator->expire != -1) || (iterator->subpeer != 1)) {
5867+ if (iterator->subpeer == 1) {
5868+ tmp = strchr(name, '@');
5869+ i = tmp - name;
5870+ name[i] = '\0';
5871+ }
5872 ast_cli(fd, FORMAT, name,
5873 iterator->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), iterator->addr.sin_addr) : "(Unspecified)",
5874 ast_test_flag(&iterator->flags_page2, SIP_PAGE2_DYNAMIC) ? " D " : " ", /* Dynamic or not? */
5875@@ -7665,6 +7787,7 @@
5876 iterator->ha ? " A " : " ", /* permit/deny */
5877
5878 ntohs(iterator->addr.sin_port), status);
5879+ }
5880 } else { /* Manager format */
5881 /* The names here need to be the same as other channels */
5882 ast_cli(fd,
5883@@ -7690,7 +7813,9 @@
5884
5885 ASTOBJ_UNLOCK(iterator);
5886
5887- total_peers++;
5888+ if ((iterator->expire != -1) || (iterator->subpeer != 1)) {
5889+ total_peers++;
5890+ }
5891 } while(0) );
5892
5893 if (!s) {
5894@@ -8725,6 +8850,7 @@
5e69ef1a
MT
5895 char buf[1024];
5896 unsigned int event;
5897 char *c;
5898+ struct ast_call_feature *feature;
5899
5900 /* Need to check the media/type */
5901 if (!strcasecmp(get_header(req, "Content-Type"), "application/dtmf-relay") ||
b684b13b 5902@@ -8788,6 +8914,19 @@
5e69ef1a
MT
5903 ast_queue_control(p->owner, AST_CONTROL_VIDUPDATE);
5904 transmit_response(p, "200 OK", req);
5905 return;
5906+ } else if ((c = get_header(req, "Record"))) {
5907+ feature = ast_find_builtin_feature("automon");
5908+ if (feature && (!ast_strlen_zero(feature->exten))) {
5909+ int i = 0;
5910+// ast_log(LOG_NOTICE, "feature exten %s\n", feature->exten);
5911+ for (i=0; i<strlen(feature->exten); i++) {
5912+ struct ast_frame f = { AST_FRAME_DTMF, feature->exten[i] };
5913+ ast_queue_frame(p->owner, &f);
5914+ }
5915+ } else {
5916+ ast_log(LOG_NOTICE, "Feature \"One Touch Monitor\" not configured in features.conf.\n");
5917+ }
5918+ return;
5919 } else if ((c = get_header(req, "X-ClientCode"))) {
5920 /* Client code (from SNOM phone) */
5921 if (ast_test_flag(p, SIP_USECLIENTCODE)) {
b684b13b 5922@@ -8887,12 +9026,63 @@
5e69ef1a
MT
5923 return RESULT_SUCCESS;
5924 }
5925
5926+
5927+/*! \brief sip_notify: Send SIP notify to peer */
5928+static int sip_send_notify(int fd, char *notify_type, char *peer)
5929+{
5930+ struct ast_variable *varlist;
5931+ struct sip_pvt *p;
5932+ struct sip_request req;
5933+ struct ast_variable *var;
5934+
5935+ varlist = ast_variable_browse(notify_types, notify_type);
5936+
5937+ if (!varlist) {
5938+ if (fd > 0)
5939+ ast_cli(fd, "Unable to find notify type '%s'\n", notify_type);
5940+ return RESULT_FAILURE;
5941+ }
5942+
5943+ p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY);
5944+ if (!p) {
5945+ ast_log(LOG_WARNING, "Unable to build sip pvt data for notify\n");
5946+ return RESULT_FAILURE;
5947+ }
5948+
5949+ if (create_addr(p, peer)) {
5950+ /* Maybe they're not registered, etc. */
5951+ sip_destroy(p);
5952+ if (fd > 0)
5953+ ast_cli(fd, "Could not create address for '%s'\n", peer);
5954+ return RESULT_FAILURE;
5955+ }
5956+
5957+ initreqprep(&req, p, SIP_NOTIFY);
5958+
5959+ for (var = varlist; var; var = var->next)
5960+ add_header(&req, var->name, var->value);
5961+
5962+ add_blank_header(&req);
5963+ /* Recalculate our side, and recalculate Call ID */
5964+ if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
5965+ memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
5966+ build_via(p, p->via, sizeof(p->via));
5967+ build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
5968+ if (fd > 0)
5969+ ast_cli(fd, "Sending NOTIFY of type '%s' to '%s'\n", notify_type, peer);
5970+ transmit_sip_request(p, &req);
5971+ sip_scheddestroy(p, 15000);
5972+
5973+ return RESULT_SUCCESS;
5974+}
5975+
5976 /*! \brief sip_notify: Send SIP notify to peer */
5977 static int sip_notify(int fd, int argc, char *argv[])
5978 {
5979 struct ast_variable *varlist;
5980 int i;
5981-
5982+ int res = RESULT_SUCCESS;
5983+
5984 if (argc < 4)
5985 return RESULT_SHOWUSAGE;
5986
b684b13b 5987@@ -8909,41 +9099,13 @@
5e69ef1a
MT
5988 }
5989
5990 for (i = 3; i < argc; i++) {
5991- struct sip_pvt *p;
5992- struct sip_request req;
5993- struct ast_variable *var;
5994-
5995- p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY);
5996- if (!p) {
5997- ast_log(LOG_WARNING, "Unable to build sip pvt data for notify\n");
5998- return RESULT_FAILURE;
5999- }
6000-
6001- if (create_addr(p, argv[i])) {
6002- /* Maybe they're not registered, etc. */
6003- sip_destroy(p);
6004- ast_cli(fd, "Could not create address for '%s'\n", argv[i]);
6005- continue;
6006- }
6007-
6008- initreqprep(&req, p, SIP_NOTIFY);
6009-
6010- for (var = varlist; var; var = var->next)
6011- add_header(&req, var->name, var->value);
6012+ if (sip_send_notify(fd, argv[2], argv[i]) == RESULT_FAILURE)
6013+ res = RESULT_FAILURE;
6014+ }
6015+ return res;
6016+}
6017
6018- add_blank_header(&req);
6019- /* Recalculate our side, and recalculate Call ID */
6020- if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
6021- memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
6022- build_via(p, p->via, sizeof(p->via));
6023- build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
6024- ast_cli(fd, "Sending NOTIFY of type '%s' to '%s'\n", argv[2], argv[i]);
6025- transmit_sip_request(p, &req);
6026- sip_scheddestroy(p, 15000);
6027- }
6028
6029- return RESULT_SUCCESS;
6030-}
6031 /*! \brief sip_do_history: Enable SIP History logging (CLI) ---*/
6032 static int sip_do_history(int fd, int argc, char *argv[])
6033 {
b684b13b
MT
6034@@ -9597,12 +9759,13 @@
6035 check_pendings(p);
6036 ast_set_flag(p, SIP_CAN_BYE);
5f892677
MT
6037 break;
6038+ case 183:
6039 case 180: /* 180 Ringing */
6040 sip_cancel_destroy(p);
5e69ef1a
MT
6041 if (!ignore && p->owner) {
6042 ast_queue_control(p->owner, AST_CONTROL_RINGING);
6043 if (p->owner->_state != AST_STATE_UP)
6044- ast_setstate(p->owner, AST_STATE_RINGING);
6045+ ast_setstate_and_cid(p->owner, AST_STATE_RINGING, p->owner->cid.cid_num, p->owner->cid.cid_name);
6046 }
b684b13b 6047 if (find_sdp(req)) {
5e69ef1a 6048 process_sdp(p, req);
b684b13b
MT
6049@@ -9616,21 +9779,6 @@
6050 check_pendings(p);
6051 ast_set_flag(p, SIP_CAN_BYE);
5f892677
MT
6052 break;
6053- case 183: /* Session progress */
b684b13b 6054- sip_cancel_destroy(p);
5f892677 6055- /* Ignore 183 Session progress without SDP */
b684b13b
MT
6056- if (find_sdp(req)) {
6057- process_sdp(p, req);
6058- if (!ignore && p->owner) {
5f892677 6059- /* Queue a progress frame */
b684b13b
MT
6060- ast_queue_control(p->owner, AST_CONTROL_PROGRESS);
6061- }
6062- }
6063- /* must call check_pendings before setting CAN_BYE, so that
6064- if PENDINGBYE is set it will know to send CANCEL instead */
6065- check_pendings(p);
6066- ast_set_flag(p, SIP_CAN_BYE);
5f892677 6067- break;
5f892677
MT
6068 case 200: /* 200 OK on invite - someone's answering our call */
6069 sip_cancel_destroy(p);
6070 p->authtries = 0;
b684b13b 6071@@ -10424,9 +10572,18 @@
5f892677
MT
6072 /* This is a call to ourself. Send ourselves an error code and stop
6073 processing immediately, as SIP really has no good mechanism for
6074 being able to call yourself */
b684b13b
MT
6075- transmit_response(p, "482 Loop Detected", req);
6076- /* We do NOT destroy p here, so that our response will be accepted */
6077- return 0;
6078+/* char tmp[256] = "", *uri;
6079+ if (req->rlPart2)
6080+ ast_copy_string(tmp, req->rlPart2, sizeof(tmp));
6081+ uri = get_in_brackets(tmp);
6082+ if (strcmp(p->uri, uri)) {
6083+ ast_log(LOG_NOTICE, "SPIRAL DETECTED p->uri: %s uri: %s\n", p->uri, uri);
6084+ } else {
6085+ ast_log(LOG_NOTICE, "LOOP DETECTED p->uri: %s uri: %s\n", p->uri, uri);*/
6086+ transmit_response(p, "482 Loop Detected", req);
6087+ /* We do NOT destroy p here, so that our response will be accepted */
6088+ return 0;
6089+/* }*/
6090 }
6091 if (!ignore) {
6092 /* Use this as the basis */
6093@@ -10658,6 +10815,7 @@
6094 struct ast_channel *c=NULL;
6095 int res;
6096 struct ast_channel *transfer_to;
6097+ struct sip_pvt *rp; /* replace call */
6098
6099 if (option_debug > 2)
6100 ast_log(LOG_DEBUG, "SIP call transfer received for call %s (REFER)!\n", p->callid);
6101@@ -10666,9 +10824,74 @@
6102 res = get_refer_info(p, req);
6103 if (res < 0)
6104 transmit_response_with_allow(p, "404 Not Found", req, 1);
6105- else if (res > 0)
6106+ else if (res == 1)
6107 transmit_response_with_allow(p, "484 Address Incomplete", req, 1);
6108- else {
6109+ else if (res == 2) {
6110+ transmit_response(p, "202 Accepted", req);
6111+ rp = sip_alloc(NULL, NULL, 0, SIP_INVITE);
6112+ if (!rp) {
6113+ return -1;
6114+ }
6115+ rp->capability = global_capability;
6116+
6117+ build_route(rp, req, 0);
6118+ if (option_verbose > 3)
6119+ ast_log(LOG_NOTICE, "got REFER for callid %s TO %s CONTACT %s replacing callid %s (tohost %s, p->route %s, rp->route %s)\n", p->callid, p->refer_to, p->refer_contact, p->refer_replaces, p->tohost, p->route->hop, rp->route->hop);
6120+ if (create_addr(rp, p->tohost)) {
6121+ sip_destroy(rp);
6122+ return -1;
6123+ }
6124+
6125+ if (ast_sip_ouraddrfor(&rp->sa.sin_addr,&rp->ourip)) {
6126+ memcpy(&rp->ourip, &__ourip, sizeof(rp->ourip));
6127+ }
6128+ build_via(rp, rp->via, sizeof(rp->via));
6129+ build_callid(rp->callid, sizeof(rp->callid) - 1, rp->ourip, rp->fromdomain);
6130+
6131+ ast_log(LOG_NOTICE, "1\n");
6132+ rp->prefcodec = p->prefcodec;
6133+ rp->jointcapability = rp->capability;
6134+ rp->rtp = p->rtp;
6135+ p->rtp = NULL;
6136+ if (!ast_strlen_zero(p->refer_to)) {
6137+ ast_copy_string(rp->username, p->refer_to, sizeof(rp->username));
6138+ rp->fullcontact[0] = '\0';
6139+ }
6140+ if (!ast_strlen_zero(p->refer_replaces)) {
6141+ ast_copy_string(rp->refer_replaces, p->refer_replaces, sizeof(rp->refer_replaces));
6142+ }
6143+ ast_log(LOG_NOTICE, "2\n");
6144+ ast_set_flag(rp, SIP_OUTGOING);
6145+
6146+ ast_log(LOG_NOTICE, "3\n");
6147+
6148+ if (p->owner) {
6149+ c = p->owner;
6150+// ast_copy_string(rp->cid_num, c->cid.cid_num, sizeof(rp->cid_num));
6151+// ast_copy_string(rp->cid_name, c->cid.cid_name, sizeof(rp->cid_name));
6152+ ast_log(LOG_NOTICE, "4\n");
6153+ c->tech_pvt = rp;
6154+ rp->owner = c;
6155+ ast_log(LOG_NOTICE, "5\n");
6156+ ast_mutex_unlock(&c->lock);
6157+ }
6158+ p->owner = NULL;
6159+ ast_log(LOG_NOTICE, "6\n");
6160+
6161+ transmit_invite(rp, SIP_INVITE, 1, 2);
6162+ if (rp->maxtime) {
6163+ /* Initialize auto-congest time */
6164+ rp->initid = ast_sched_add(sched, rp->maxtime * 4, auto_congest, rp);
6165+ }
6166+
6167+ transmit_notify_with_sipfrag(p, seqno);
6168+
6169+ /* Always increment on a BYE */
6170+ transmit_request_with_auth(p, SIP_BYE, 0, 1, 1);
6171+ ast_set_flag(p, SIP_ALREADYGONE);
6172+ return 0;
6173+
6174+ } else { /* res == 0 */
6175 int nobye = 0;
6176 if (!ignore) {
6177 if (p->refer_call) {
6178@@ -10993,7 +11216,7 @@
5e69ef1a
MT
6179 struct sip_pvt *p_old;
6180
6181 transmit_response(p, "200 OK", req);
6182- transmit_state_notify(p, firststate, 1, 1); /* Send first notification */
6183+ transmit_state_notify(p, firststate, 1, 1, NULL, NULL); /* Send first notification */
6184 append_history(p, "Subscribestatus", ast_extension_state2str(firststate));
6185
6186 /* remove any old subscription from this peer for the same exten/context,
b684b13b
MT
6187@@ -11187,6 +11410,8 @@
6188 res = handle_request_options(p, req, debug);
6189 break;
6190 case SIP_INVITE:
6191+ /* XXX quick fix for xfers */
6192+ ast_copy_string(p->tohost, ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), sizeof(p->tohost));
6193 res = handle_request_invite(p, req, debug, ignore, seqno, sin, recount, e);
6194 break;
6195 case SIP_REFER:
6196@@ -11307,7 +11532,7 @@
5e69ef1a
MT
6197 /* Process request, with netlock held */
6198 retrylock:
6199 ast_mutex_lock(&netlock);
6200- p = find_call(&req, &sin, req.method);
6201+ p = find_call(&req, &sin, req.method, 0);
6202 if (p) {
6203 /* Go ahead and lock the owner if it has one -- we may need it */
6204 if (p->owner && ast_mutex_trylock(&p->owner->lock)) {
b684b13b 6205@@ -11634,6 +11859,52 @@
5e69ef1a
MT
6206 return 0;
6207 }
6208
6209+static char mandescr_sip_notify[] =
6210+"Description: Send a NOTIFY message to one or more SIP peers.\n"
6211+"Variables: \n"
6212+" Peer: <name> The peer name you want to send a NOTIFY to.\n"
6213+" Type: <name> The notify type (see sip_notify.conf).\n"
6214+" ActionID: <id> Optional action ID for this AMI transaction.\n";
6215+
6216+/*! \brief manager_sip_notify: Send a notify (see sip_notify.conf) to a peer ---*/
6217+static int manager_sip_notify(struct mansession *s, struct message *m)
6218+{
6219+ char *id = astman_get_header(m,"ActionID");
6220+ char *peer;
6221+ char *notify_type;
6222+ int res = 0;
6223+
6224+ peer = astman_get_header(m,"Peer");
6225+ if (ast_strlen_zero(peer)) {
6226+ astman_send_error(s, m, "Peer: <name> missing.\n");
6227+ return 0;
6228+ }
6229+ notify_type = astman_get_header(m,"Type");
6230+ if (ast_strlen_zero(notify_type)) {
6231+ astman_send_error(s, m, "Type: <name> missing.\n");
6232+ return 0;
6233+ }
6234+
6235+ res = sip_send_notify(-1, notify_type, peer);
6236+ if (res != RESULT_SUCCESS) {
6237+ ast_cli(s->fd, "Response: SIPNotify Failure\r\n"
6238+ "Peer: %s\r\n"
6239+ "Type: %s\r\n"
6240+ "ActionID: %s\r\n"
6241+ "\r\n",
6242+ peer, notify_type, id);
6243+ } else {
6244+ ast_cli(s->fd, "Response: SIPNotify Success\r\n"
6245+ "Peer: %s\r\n"
6246+ "Type: %s\r\n"
6247+ "ActionID: %s\r\n"
6248+ "\r\n",
6249+ peer, notify_type, id);
6250+ }
6251+ return res;
6252+}
6253+
6254+
6255 /*! \brief sip_devicestate: Part of PBX channel interface ---*/
6256
6257 /* Return values:---
b684b13b
MT
6258@@ -12171,6 +12442,7 @@
6259
6260 peer->expire = -1;
6261 peer->pokeexpire = -1;
6262+ peer->max_regs = 1;
6263 ast_copy_string(peer->name, name, sizeof(peer->name));
6264 ast_copy_flags(peer, &global_flags, SIP_FLAGS_TO_COPY);
6265 strcpy(peer->context, default_context);
6266@@ -12216,7 +12488,9 @@
6267
6268 if (peer) {
6269 /* Already in the list, remove it and it will be added back (or FREE'd) */
6270- found++;
6271+ if (peer->max_regs == 1) {
6272+ found++;
6273+ }
6274 } else {
6275 peer = malloc(sizeof(*peer));
6276 if (peer) {
6277@@ -12228,6 +12502,7 @@
6278 ASTOBJ_INIT(peer);
6279 peer->expire = -1;
6280 peer->pokeexpire = -1;
6281+ peer->max_regs = 1;
6282 } else {
6283 ast_log(LOG_WARNING, "Can't allocate SIP peer memory\n");
6284 }
6285@@ -12373,6 +12648,10 @@
6286 peer->call_limit = atoi(v->value);
6287 if (peer->call_limit < 0)
6288 peer->call_limit = 0;
6289+ } else if (!strcasecmp(v->name, "registrations")) {
6290+ peer->max_regs = atoi(v->value);
6291+ if (peer->max_regs < 0)
6292+ peer->max_regs = 0;
6293 } else if (!strcasecmp(v->name, "amaflags")) {
6294 format = ast_cdr_amaflags2int(v->value);
6295 if (format < 0) {
6296@@ -12768,8 +13047,24 @@
6297 if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) {
6298 peer = build_peer(cat, ast_variable_browse(cfg, cat), 0);
6299 if (peer) {
6300- ASTOBJ_CONTAINER_LINK(&peerl,peer);
6301- ASTOBJ_UNREF(peer, sip_destroy_peer);
6302+ if (peer->max_regs > 1) {
6303+ int i = 0;
6304+ int clones = peer->max_regs - 1;
6305+ struct sip_peer *clone = NULL;
6306+ char clone_name[sizeof(clone->name)];
6307+ /* clone clone clone */
6308+ for (i=0;i<clones;i++) {
6309+ snprintf(clone_name, sizeof(clone_name), "%s@%d", cat, i);
6310+ clone = build_peer(clone_name, ast_variable_browse(cfg, cat), 0);
6311+ if (clone) {
6312+ clone->subpeer = 1;
6313+ ASTOBJ_CONTAINER_LINK(&peerl,clone);
6314+ ASTOBJ_UNREF(clone, sip_destroy_peer);
6315+ }
6316+ }
6317+ }
6318+ ASTOBJ_CONTAINER_LINK(&peerl,peer);
6319+ ASTOBJ_UNREF(peer, sip_destroy_peer);
6320 }
6321 } else if (strcasecmp(utype, "user")) {
6322 ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, "sip.conf");
6323@@ -13359,6 +13654,8 @@
5e69ef1a
MT
6324 "List SIP peers (text format)", mandescr_show_peers);
6325 ast_manager_register2("SIPshowpeer", EVENT_FLAG_SYSTEM, manager_sip_show_peer,
6326 "Show SIP peer (text format)", mandescr_show_peer);
6327+ ast_manager_register2("SIPNotify", EVENT_FLAG_SYSTEM, manager_sip_notify,
6328+ "Send NOTIFY to peer", mandescr_sip_notify);
6329
6330 sip_poke_all_peers();
6331 sip_send_all_registers();
b684b13b 6332@@ -13389,6 +13686,7 @@
5e69ef1a
MT
6333
6334 ast_rtp_proto_unregister(&sip_rtp);
6335
6336+ ast_manager_unregister("SIPNotify");
6337 ast_manager_unregister("SIPpeers");
6338 ast_manager_unregister("SIPshowpeer");
6339
b684b13b
MT
6340diff -urN asterisk-1.2.9.1.orig/channels/chan_zap.c asterisk-1.2.9.1/channels/chan_zap.c
6341--- asterisk-1.2.9.1.orig/channels/chan_zap.c 2006-05-31 22:26:17.000000000 +0200
6342+++ asterisk-1.2.9.1/channels/chan_zap.c 2006-06-15 16:09:02.000000000 +0200
5e69ef1a
MT
6343@@ -11,6 +11,10 @@
6344 * the project provides a web site, mailing lists and IRC
6345 * channels for your use.
6346 *
5f892677 6347+ * Copyright (C) 2003-2006 Junghanns.NET GmbH
5e69ef1a
MT
6348+ * Klaus-Peter Junghanns <kpj@junghanns.net>
6349+ *
6350+ *
6351 * This program is free software, distributed under the terms of
6352 * the GNU General Public License Version 2. See the LICENSE file
6353 * at the top of the source tree.
5f892677
MT
6354@@ -65,6 +69,9 @@
6355 #ifdef ZAPATA_R2
6356 #include <libmfcr2.h>
6357 #endif
6358+#ifdef ZAPATA_GSM
6359+#include <libgsmat.h>
6360+#endif
6361
6362 #include "asterisk.h"
6363
6364@@ -96,6 +103,7 @@
5e69ef1a
MT
6365 #include "asterisk/term.h"
6366 #include "asterisk/utils.h"
6367 #include "asterisk/transcap.h"
6368+#include "asterisk/devicestate.h"
6369
6370 #ifndef ZT_SIG_EM_E1
6371 #error "Your zaptel is too old. please cvs update"
5f892677
MT
6372@@ -173,6 +181,7 @@
6373 #define SIG_FXOGS ZT_SIG_FXOGS
6374 #define SIG_FXOKS ZT_SIG_FXOKS
6375 #define SIG_PRI ZT_SIG_CLEAR
6376+#define SIG_GSM (0x100000 | ZT_SIG_CLEAR)
6377 #define SIG_R2 ZT_SIG_CAS
6378 #define SIG_SF ZT_SIG_SF
6379 #define SIG_SFWINK (0x0100000 | ZT_SIG_SF)
6380@@ -183,7 +192,7 @@
5e69ef1a
MT
6381 #define SIG_GR303FXOKS (0x0100000 | ZT_SIG_FXOKS)
6382 #define SIG_GR303FXSKS (0x0100000 | ZT_SIG_FXSKS)
6383
6384-#define NUM_SPANS 32
6385+#define NUM_SPANS 128 /*!<"32 spans", muahahaha, us alaws like to have some more... */
6386 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
6387 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
6388
5f892677 6389@@ -201,6 +210,11 @@
5e69ef1a
MT
6390 static char defaultcic[64] = "";
6391 static char defaultozz[64] = "";
6392
6393+static char nocid[256] = "No CID available";
6394+static char withheldcid[256] = "CID withheld";
5f892677
MT
6395+static char gsm_modem_pin[20];
6396+static char gsm_modem_exten[AST_MAX_EXTENSION];
5e69ef1a
MT
6397+
6398 static char language[MAX_LANGUAGE] = "";
6399 static char musicclass[MAX_MUSICCLASS] = "";
6400 static char progzone[10]= "";
5f892677 6401@@ -287,6 +301,7 @@
5e69ef1a
MT
6402 static int cur_priexclusive = 0;
6403
6404 static int priindication_oob = 0;
6405+static int pritransfer = 0;
6406
6407 #ifdef ZAPATA_PRI
6408 static int minunused = 2;
5f892677 6409@@ -294,6 +309,7 @@
5e69ef1a
MT
6410 static char idleext[AST_MAX_EXTENSION];
6411 static char idledial[AST_MAX_EXTENSION];
6412 static int overlapdial = 0;
6413+static int usercid = 0;
6414 static int facilityenable = 0;
6415 static char internationalprefix[10] = "";
6416 static char nationalprefix[10] = "";
5f892677 6417@@ -305,8 +321,6 @@
5e69ef1a
MT
6418 #ifdef PRI_GETSET_TIMERS
6419 static int pritimers[PRI_MAX_TIMERS];
6420 #endif
6421-static int pridebugfd = -1;
6422-static char pridebugfilename[1024]="";
6423 #endif
6424
6425 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
5f892677 6426@@ -327,10 +341,6 @@
5e69ef1a
MT
6427
6428 static int ifcount = 0;
6429
6430-#ifdef ZAPATA_PRI
6431-AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
6432-#endif
6433-
6434 /*! \brief Whether we answer on a Polarity Switch event */
6435 static int answeronpolarityswitch = 0;
6436
5f892677
MT
6437@@ -389,6 +399,18 @@
6438
6439 struct zt_pvt;
6440
6441+#ifdef ZAPATA_GSM
6442+struct zt_gsm {
6443+ pthread_t master;
6444+ ast_mutex_t lock; /* Mutex */
6445+ int fd;
6446+ int span;
6447+ struct gsm_modul *modul;
6448+ char pin[256];
6449+ char exten[AST_MAX_EXTENSION]; /* Where to idle extra calls */
6450+ struct zt_pvt *pvt;
6451+};
6452+#endif
6453
6454 #ifdef ZAPATA_R2
6455 static int r2prot = -1;
6456@@ -403,6 +425,28 @@
5e69ef1a
MT
6457 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
6458 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
6459
6460+struct zt_suspended_call {
6461+ ast_mutex_t lock; /* Mutex */
6462+ char msn[AST_MAX_EXTENSION]; /* the MSN to which this parked call belongs */
6463+ char callid[10]; /* the callID provided by the user */
6464+ int parked_at; /* extension in the call parking context */
6465+ struct zt_suspended_call *next;
6466+};
6467+
6468+struct zt_holded_call {
6469+ ast_mutex_t lock; /* Mutex */
6470+ char msn[AST_MAX_EXTENSION]; /* the MSN to which this parked call belongs */
6471+ char uniqueid[AST_MAX_EXTENSION]; /* unique id of the onhold channel */
6472+ int tei;
6473+ int cref;
6474+ int alreadyhungup;
6475+ struct ast_channel *channel;
6476+ struct ast_channel *bridge;
6477+ q931_call *call; /* this also covers tei mumbojumbo */
6478+ struct zt_holded_call *next;
6479+};
5f892677 6480+
5e69ef1a
MT
6481+
6482 struct zt_pri {
6483 pthread_t master; /*!< Thread of master */
6484 ast_mutex_t lock; /*!< Mutex */
5f892677 6485@@ -416,6 +460,8 @@
5e69ef1a
MT
6486 int nsf; /*!< Network-Specific Facilities */
6487 int dialplan; /*!< Dialing plan */
6488 int localdialplan; /*!< Local dialing plan */
6489+ char nocid[256];
6490+ char withheldcid[256];
6491 char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
6492 char nationalprefix[10]; /*!< area access code ('0' for european dialplans) */
6493 char localprefix[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
5f892677 6494@@ -435,6 +481,7 @@
5e69ef1a
MT
6495 int fds[NUM_DCHANS]; /*!< FD's for d-channels */
6496 int offset;
6497 int span;
6498+ int usercid; /* trust user provided callerid (callerani) ?? */
6499 int resetting;
6500 int resetpos;
6501 time_t lastreset; /*!< time when unused channels were last reset */
5f892677 6502@@ -442,6 +489,9 @@
5e69ef1a
MT
6503 struct zt_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
6504 struct zt_pvt *crvs; /*!< Member CRV structs */
6505 struct zt_pvt *crvend; /*!< Pointer to end of CRV structs */
6506+ struct zt_suspended_call *suspended_calls; /* Calls parked with SUSPEND messages */
6507+ struct zt_holded_call *holded_calls; /* Calls on hold */
6508+ int debugfd;
6509 };
6510
6511
5f892677 6512@@ -561,6 +611,8 @@
5e69ef1a
MT
6513 unsigned int echocanbridged:1;
6514 unsigned int echocanon:1;
6515 unsigned int faxhandled:1; /*!< Has a fax tone already been handled? */
6516+ /*!< KPJ: i will abuse this flag to implement a zapata option for dialing out
6517+ on a zap channel with EC to be off no matter what happens. */
6518 unsigned int firstradio:1;
6519 unsigned int hanguponpolarityswitch:1;
6520 unsigned int hardwaredtmf:1;
5f892677 6521@@ -573,7 +625,8 @@
5e69ef1a
MT
6522 unsigned int overlapdial:1;
6523 unsigned int permcallwaiting:1;
6524 unsigned int permhidecallerid:1; /*!< Whether to hide our outgoing caller ID or not */
6525- unsigned int priindication_oob:1;
6526+ unsigned int priindication_oob:2;
6527+ unsigned int pritransfer:2;
6528 unsigned int priexclusive:1;
6529 unsigned int pulse:1;
6530 unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */
5f892677 6531@@ -612,6 +665,7 @@
5e69ef1a
MT
6532 #endif
6533 char cid_num[AST_MAX_EXTENSION];
6534 int cid_ton; /*!< Type Of Number (TON) */
6535+ int cid_pres; /*!< Calling Presentation */
6536 char cid_name[AST_MAX_EXTENSION];
6537 char lastcid_num[AST_MAX_EXTENSION];
6538 char lastcid_name[AST_MAX_EXTENSION];
5f892677
MT
6539@@ -672,10 +726,15 @@
6540 int polarityonanswerdelay;
6541 struct timeval polaritydelaytv;
6542 int sendcalleridafter;
6543+#ifdef ZAPATA_GSM
6544+ struct zt_gsm gsm;
6545+#endif
6546 #ifdef ZAPATA_PRI
5e69ef1a
MT
6547 struct zt_pri *pri;
6548 struct zt_pvt *bearer;
6549 struct zt_pvt *realcall;
6550+ int tei; /* channel in use by this tei */
6551+ q931_call *holdedcall;
6552 q931_call *call;
6553 int prioffset;
6554 int logicalspan;
5f892677 6555@@ -701,11 +760,14 @@
5e69ef1a
MT
6556 static int zt_indicate(struct ast_channel *chan, int condition);
6557 static int zt_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
6558 static int zt_setoption(struct ast_channel *chan, int option, void *data, int datalen);
6559+static int zt_devicestate(void *data);
6560+static void disable_dtmf_detect(struct zt_pvt *p);
6561+static void enable_dtmf_detect(struct zt_pvt *p);
6562
6563 static const struct ast_channel_tech zap_tech = {
6564 .type = type,
6565 .description = tdesc,
6566- .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW,
6567+ .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
6568 .requester = zt_request,
6569 .send_digit = zt_digit,
6570 .send_text = zt_sendtext,
5f892677 6571@@ -719,6 +781,7 @@
5e69ef1a
MT
6572 .indicate = zt_indicate,
6573 .fixup = zt_fixup,
6574 .setoption = zt_setoption,
6575+ .devicestate = zt_devicestate
6576 };
6577
6578 #ifdef ZAPATA_PRI
5f892677 6579@@ -730,6 +793,13 @@
5e69ef1a
MT
6580 struct zt_pvt *round_robin[32];
6581
6582 #ifdef ZAPATA_PRI
6583+struct app_tmp {
6584+ char app[256];
6585+ char data[256];
6586+ struct ast_channel *chan;
6587+ pthread_t t;
6588+};
6589+
6590 static inline int pri_grab(struct zt_pvt *pvt, struct zt_pri *pri)
6591 {
6592 int res;
5f892677 6593@@ -779,6 +849,112 @@
5e69ef1a
MT
6594 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
6595 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
6596
6597+static int zt_devicestate(void *data)
6598+{
6599+ int groupmatch = 0;
6600+ int channelmatch = 0;
6601+ struct zt_pvt *p;
6602+ char *dest=NULL;
6603+ int x,d;
6604+ char *s;
6605+ char opt=0;
6606+ int res, y=0;
6607+ struct zt_pvt *exit, *start, *end;
6608+ ast_mutex_t *lock;
6609+
6610+// ast_log(LOG_NOTICE, "data = %s\n", (char *)data);
6611+ return AST_DEVICE_UNKNOWN;
6612+
6613+ /* Assume we're locking the iflock */
6614+ lock = &iflock;
6615+ start = iflist;
6616+ end = ifend;
6617+
6618+ if (data) {
6619+ dest = ast_strdupa((char *)data);
6620+ } else {
6621+ ast_log(LOG_WARNING, "Channel requested with no data\n");
6622+ return AST_DEVICE_INVALID;
6623+ }
6624+ if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
6625+ /* Retrieve the group number */
6626+ char *stringp=NULL;
6627+ stringp=dest + 1;
6628+ s = strsep(&stringp, "/");
6629+ if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
6630+ ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
6631+ return AST_DEVICE_INVALID;
6632+ }
6633+ groupmatch = 1 << x;
6634+ } else {
6635+ char *stringp=NULL;
6636+ stringp=dest;
6637+ s = strsep(&stringp, "/");
6638+ p = iflist;
6639+ if (!strcasecmp(s, "pseudo")) {
6640+ /* Special case for pseudo */
6641+ x = CHAN_PSEUDO;
6642+ channelmatch = x;
6643+ /* bail out */
6644+ return AST_DEVICE_INVALID;
6645+ }
6646+
6647+ else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
6648+ ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
6649+ return AST_DEVICE_INVALID;
6650+ } else {
6651+ channelmatch = x;
6652+ ast_log(LOG_NOTICE, "channelmatch = %d\n", channelmatch);
6653+ }
6654+ }
6655+ /* Search for an unowned channel */
6656+ if (ast_mutex_lock(lock)) {
6657+ ast_log(LOG_ERROR, "Unable to lock interface list???\n");
6658+ return AST_DEVICE_INVALID;
6659+ }
6660+ p = iflist;
6661+ exit = iflist;
6662+ res = AST_DEVICE_INVALID; /* start pessimistic */
6663+ while(p) {
6664+ if (p) {
6665+ ast_mutex_lock(&p->lock);
6666+ if ((groupmatch && ((p->group & groupmatch) != 0)) || (channelmatch && (p->channel == channelmatch))) {
6667+#ifdef ZAPATA_PRI
6668+ if (p->pri) {
6669+ for(d=0;d<NUM_DCHANS;d++) {
6670+ if (p->pri->dchanavail[d] & DCHAN_UP) {
6671+ res = AST_DEVICE_UNKNOWN;
6672+ }
6673+ }
6674+ }
6675+#endif
6676+ if ((!ast_strlen_zero(p->cid_num) && (strncasecmp(p->cid_num, dest, strlen(p->cid_num)))) || (!ast_strlen_zero(p->dnid) && (strncasecmp(p->dnid, dest, strlen(p->dnid))))) {
6677+ res = AST_DEVICE_UNKNOWN;
6678+ if (p->owner) {
6679+ if ((p->owner->_state == AST_STATE_RINGING) && (p->outgoing)) {
6680+ res = AST_DEVICE_RINGING;
6681+ }
6682+ if (((p->owner->_state == AST_STATE_RINGING) && (!p->outgoing)) || (p->owner->_state == AST_STATE_UP) || (p->owner->_state == AST_STATE_DIALING) || (p->owner->_state == AST_STATE_RESERVED) || (p->owner->_state == AST_STATE_RING)){
6683+ res = AST_DEVICE_INUSE;
6684+ }
6685+ }
6686+ if ((res == AST_DEVICE_INUSE) || (res == AST_DEVICE_RINGING)) {
6687+ /* stop searching now, one non-idle channel is sufficient */
6688+ ast_mutex_unlock(&p->lock);
6689+ break;
6690+ }
6691+ }
6692+ }
6693+ ast_mutex_unlock(&p->lock);
6694+ }
6695+ p = p->next;
6696+ }
6697+ ast_mutex_unlock(lock);
6698+
6699+ return res;
6700+
6701+}
6702+
6703 static int zt_get_index(struct ast_channel *ast, struct zt_pvt *p, int nullok)
6704 {
6705 int res;
5f892677
MT
6706@@ -1181,6 +1357,8 @@
6707 return "GR-303 Signalling with FXOKS";
6708 case SIG_GR303FXSKS:
6709 return "GR-303 Signalling with FXSKS";
6710+ case SIG_GSM:
6711+ return "GSM Signalling";
6712 case 0:
6713 return "Pseudo Signalling";
6714 default:
6715@@ -1381,12 +1559,16 @@
5e69ef1a
MT
6716 int res;
6717 if (!p)
6718 return;
6719+ if (p->faxhandled) {
6720+ ast_log(LOG_DEBUG, "Not enabling echo cancellation on a fax/modem call\n");
6721+ return;
6722+ }
6723 if (p->echocanon) {
6724 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
6725 return;
6726 }
6727 if (p->digital) {
6728- ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
6729+ ast_log(LOG_DEBUG, "Echo cancellation does not make any sense on digital connections!\n");
6730 return;
6731 }
6732 if (p->echocancel) {
5f892677 6733@@ -1412,7 +1594,7 @@
5e69ef1a
MT
6734 {
6735 int x;
6736 int res;
6737- if (p && p->echocancel && p->echotraining) {
6738+ if (p && p->echocancel && p->echotraining && (!p->digital) && (!p->faxhandled)) {
6739 x = p->echotraining;
6740 res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOTRAIN, &x);
6741 if (res)
5f892677
MT
6742@@ -1592,7 +1774,7 @@
6743 {
6744 int x, y, res;
6745 x = muted;
6746- if (p->sig == SIG_PRI) {
6747+ if ((p->sig == SIG_PRI) || (p->sig == SIG_GSM)) {
6748 y = 1;
6749 res = ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &y);
6750 if (res)
6751@@ -1774,7 +1956,12 @@
5e69ef1a
MT
6752 ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", p->channel);
6753 p->outgoing = 1;
6754
6755- set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
6756+ if (IS_DIGITAL(ast->transfercapability)) {
6757+ set_actual_gain(p->subs[SUB_REAL].zfd, 0, 0, 0, p->law);
6758+ } else {
6759+ set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
6760+ }
6761+
5e69ef1a
MT
6762
6763 switch(p->sig) {
6764 case SIG_FXOLS:
5f892677
MT
6765@@ -1998,6 +2185,26 @@
6766 case SIG_PRI:
6767 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
6768 p->dialdest[0] = '\0';
6769+ disable_dtmf_detect(p);
6770+ break;
6771+ case SIG_GSM:
6772+#ifdef ZAPATA_GSM
6773+ if (p->gsm.modul) {
6774+ c = strchr(dest, '/');
6775+ if (c)
6776+ c++;
6777+ else
6778+ c = dest;
6779+ ast_mutex_lock(&p->gsm.lock);
b684b13b 6780+ if (gsm_dial(p->gsm.modul, p->use_callingpres ? ast->cid.cid_pres : 0, c)) {
5f892677
MT
6781+ ast_log(LOG_WARNING, "dialing failed on channel %d\n", p->channel);
6782+ ast_mutex_unlock(&p->gsm.lock);
6783+ ast_mutex_unlock(&p->lock);
6784+ return -1;
6785+ }
6786+ ast_mutex_unlock(&p->gsm.lock);
6787+ }
6788+#endif
6789 break;
6790 default:
6791 ast_log(LOG_DEBUG, "not yet implemented\n");
6792@@ -2016,6 +2223,12 @@
5e69ef1a
MT
6793 int ldp_strip;
6794 int exclusive;
6795
6796+ if ((p->pri->nodetype == BRI_NETWORK_PTMP) || (p->pri->nodetype == BRI_NETWORK)) {
6797+ // pass NO audio when ringing an isdn phone
6798+ p->dialing = 1;
6799+ // maybe we could allow passing audio when calling a p2p PBX, but well... ;-)
6800+ }
6801+
6802 c = strchr(dest, '/');
6803 if (c)
6804 c++;
5f892677 6805@@ -2033,6 +2246,7 @@
5e69ef1a
MT
6806 ast_mutex_unlock(&p->lock);
6807 return -1;
6808 }
6809+ strncpy(p->dnid, (c + p->stripmsd), sizeof(p->dnid)-1);
6810 if (p->sig != SIG_FXSKS) {
6811 p->dop.op = ZT_DIAL_OP_REPLACE;
6812 s = strchr(c + p->stripmsd, 'w');
5f892677 6813@@ -2056,6 +2270,8 @@
5e69ef1a
MT
6814 pri_rel(p->pri);
6815 ast_mutex_unlock(&p->lock);
6816 return -1;
6817+ } else {
6818+ // ast_log(LOG_NOTICE, "call %d\n", p->call);
6819 }
6820 if (!(sr = pri_sr_new())) {
6821 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
5f892677
MT
6822@@ -2085,7 +2301,7 @@
6823 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
6824 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
6825 (p->digital ? -1 :
6826- ((p->law == ZT_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
6827+ ((p->law == ZT_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)), ast->lowlayercompat);
6828 if (p->pri->facilityenable)
6829 pri_facility_enable(p->pri->pri);
6830
b684b13b 6831@@ -2286,8 +2502,10 @@
5e69ef1a
MT
6832 }
6833 if (newslot < 0) {
6834 newslot = 0;
6835- ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
6836+ if (pri->nodetype != BRI_CPE_PTMP) {
6837+ ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
6838 pri->dchannels[newslot]);
6839+ }
6840 }
6841 if (old && (oldslot != newslot))
6842 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
b684b13b 6843@@ -2343,8 +2561,7 @@
5e69ef1a
MT
6844
6845 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
6846 p->channel, index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
6847- p->ignoredtmf = 0;
6848-
6849+
6850 if (index > -1) {
6851 /* Real channel, do some fixup */
6852 p->subs[index].owner = NULL;
b684b13b 6853@@ -2441,6 +2658,7 @@
5e69ef1a
MT
6854
6855
6856 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
6857+ int outgoing = p->outgoing;
6858 p->owner = NULL;
6859 p->ringt = 0;
6860 p->distinctivering = 0;
b684b13b 6861@@ -2477,19 +2695,61 @@
5f892677
MT
6862 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
6863 if (!pri_grab(p, p->pri)) {
6864 if (p->alreadyhungup) {
6865+/* char *aoc = pbx_builtin_getvar_helper(ast,"AOCEUNITS");
6866+ int iaoc = aoc ? atoi(aoc) : -1;
6867+ char *aocpm = pbx_builtin_getvar_helper(ast,"AOCEUNITSPERMIN");
6868+ int iaocpm = aocpm ? atoi(aocpm) : -1;
6869+
6870+ if (iaocpm > -1) {
6871+ if (ast->cdr) {
6872+ long bill_sec = ast->cdr->billsec;
6873+ long bill_min = 0;
6874+ if (bill_sec > 0) {
6875+ bill_min = bill_sec / 60;
6876+ if (bill_min < 1) bill_min = 1;
6877+ }
6878+ iaoc = bill_min * iaocpm;
6879+ } else {
6880+ ast_log(LOG_NOTICE, "no cdr \n");
6881+ }
6882+ } else {
6883+ ast_log(LOG_NOTICE, "iaocpm %d \n", iaocpm);
6884+ }
6885+*/
6886 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
6887
6888 #ifdef SUPPORT_USERUSER
6889 pri_call_set_useruser(p->call, useruser);
6890 #endif
6891
6892- pri_hangup(p->pri->pri, p->call, -1);
6893+ pri_hangup(p->pri->pri, p->call, -1, -1);
6894 p->call = NULL;
6895 if (p->bearer)
6896 p->bearer->call = NULL;
6897 } else {
6898 char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
6899 int icause = ast->hangupcause ? ast->hangupcause : -1;
6900+/* char *aoc = pbx_builtin_getvar_helper(ast,"AOCEUNITS");
6901+ int iaoc = aoc ? atoi(aoc) : -1;
6902+ char *aocpm = pbx_builtin_getvar_helper(ast,"AOCEUNITSPERMIN");
6903+ int iaocpm = aocpm ? atoi(aocpm) : -1;
6904+
6905+ if (iaocpm > -1) {
6906+ if (ast->cdr) {
6907+ long bill_sec = ast->cdr->billsec;
6908+ long bill_min = 0;
6909+ if (bill_sec > 0) {
6910+ bill_min = bill_sec / 60;
6911+ if (bill_min < 1) bill_min = 1;
6912+ }
6913+ iaoc = bill_min * iaocpm;
6914+ } else {
6915+ ast_log(LOG_NOTICE, "no cdr \n");
6916+ }
6917+ } else {
6918+ ast_log(LOG_NOTICE, "iaocpm %d \n", iaocpm);
6919+ }
6920+*/
6921 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
6922
6923 #ifdef SUPPORT_USERUSER
b684b13b 6924@@ -2503,7 +2763,28 @@
5f892677 6925 if (atoi(cause))
5e69ef1a
MT
6926 icause = atoi(cause);
6927 }
5f892677
MT
6928- pri_hangup(p->pri->pri, p->call, icause);
6929+
6930+ pri_hangup(p->pri->pri, p->call, icause, -1);
5e69ef1a
MT
6931+
6932+ /* if we send a release complete we wont ge no hangup event, so clear the call here */
6933+ if (icause == 34 || icause == 44 || icause == 82 || icause == 1 || icause == 81 || icause == 17) {
6934+ if ((ast->_state == AST_STATE_RING) || (ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING)) {
6935+ p->call = NULL;
6936+ } else {
6937+ ast_log(LOG_ERROR, "What is wrong with you? You cannot use cause %d number when in state %d!\n", icause, ast->_state);
5f892677 6938+ icause = 16; /* Note, in pri_hangup() libpri will already override the cause */
5e69ef1a
MT
6939+ }
6940+ }
6941+
6942+ if (p->pri->nodetype == BRI_NETWORK_PTMP) {
6943+ if ((icause == 16 || icause == -1) && (ast->_state != AST_STATE_UP)) {
6944+ if (outgoing) {
6945+ p->call = NULL;
6946+ }
6947+ }
6948+ }
6949+
6950+
6951 }
6952 if (res < 0)
6953 ast_log(LOG_WARNING, "pri_disconnect failed\n");
b684b13b 6954@@ -2531,7 +2812,13 @@
5f892677
MT
6955
6956 }
6957 #endif
6958- if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_R2))
6959+#ifdef ZAPATA_GSM
6960+ if (p->gsm.modul) {
6961+ if (!p->alreadyhungup)
6962+ gsm_hangup(p->gsm.modul);
6963+ }
6964+#endif
6965+ if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_R2) && (p->sig != SIG_GSM))
6966 res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_ONHOOK);
6967 if (res < 0) {
6968 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
b684b13b 6969@@ -2700,10 +2987,14 @@
5e69ef1a
MT
6970 p->proceeding = 1;
6971 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
6972 pri_rel(p->pri);
6973+ /* stop ignoring inband dtmf */
6974+ enable_dtmf_detect(p);
6975 } else {
6976 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
6977 res= -1;
6978 }
6979+ /* the audio path is complete now, train the echo canceler */
6980+ zt_train_ec(p);
6981 break;
6982 #endif
6983 #ifdef ZAPATA_R2
b684b13b 6984@@ -2713,6 +3004,13 @@
5f892677
MT
6985 ast_log(LOG_WARNING, "R2 Answer call failed :( on %s\n", ast->name);
6986 break;
6987 #endif
6988+#ifdef ZAPATA_GSM
6989+ case SIG_GSM:
6990+ if (p->gsm.modul) {
6991+ gsm_answer(p->gsm.modul);
6992+ }
6993+ break;
6994+#endif
6995 case 0:
6996 ast_mutex_unlock(&p->lock);
6997 return 0;
b684b13b 6998@@ -3273,6 +3571,15 @@
5e69ef1a
MT
6999 {
7000 struct zt_pvt *p = newchan->tech_pvt;
7001 int x;
7002+ if (newchan && newchan->tech_pvt) {
7003+ p = newchan->tech_pvt;
7004+ }
7005+ if (!p) {
7006+ if (newchan) {
7007+ ast_log(LOG_ERROR, "channel %s has no tech_pvt structure\n", newchan->name);
7008+ }
7009+ return 0;
7010+ }
7011 ast_mutex_lock(&p->lock);
7012 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
7013 if (p->owner == oldchan) {
b684b13b 7014@@ -3636,7 +3943,7 @@
5f892677
MT
7015 if (p->call) {
7016 if (p->pri && p->pri->pri) {
7017 if (!pri_grab(p, p->pri)) {
7018- pri_hangup(p->pri->pri, p->call, -1);
7019+ pri_hangup(p->pri->pri, p->call, -1, -1);
7020 pri_destroycall(p->pri->pri, p->call);
7021 p->call = NULL;
7022 pri_rel(p->pri);
b684b13b 7023@@ -4599,7 +4906,7 @@
5e69ef1a
MT
7024 p->subs[index].f.data = NULL;
7025 p->subs[index].f.datalen= 0;
7026 }
7027- if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
7028+ if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
7029 /* Perform busy detection. etc on the zap line */
7030 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
7031 if (f) {
b684b13b 7032@@ -4611,8 +4918,9 @@
5e69ef1a
MT
7033 }
7034 } else if (f->frametype == AST_FRAME_DTMF) {
7035 #ifdef ZAPATA_PRI
7036- if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
7037- /* Don't accept in-band DTMF when in overlap dial mode */
5f892677 7038+ if (p->sig==SIG_PRI && p->pri && p->pri->overlapdial && p->ignoredtmf) {
5e69ef1a
MT
7039+ /* Don't accept in-band DTMF when in overlap dial mode
7040+ or when in non-overlap overlapdialing mode ... */
7041 f->frametype = AST_FRAME_NULL;
7042 f->subclass = 0;
7043 }
b684b13b 7044@@ -4660,8 +4968,10 @@
5f892677
MT
7045 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
7046 if (ast_async_goto(ast, target_context, "fax", 1))
7047 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
7048- } else
7049- ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
7050+ } else {
7051+ if (option_verbose > 2)
7052+ ast_verbose(VERBOSE_PREFIX_3 "Fax detected, but no fax extension\n");
7053+ }
7054 } else
7055 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
7056 } else
b684b13b 7057@@ -4747,7 +5057,9 @@
5e69ef1a
MT
7058 #endif
7059 /* Write a frame of (presumably voice) data */
7060 if (frame->frametype != AST_FRAME_VOICE) {
7061- if (frame->frametype != AST_FRAME_IMAGE)
7062+ if (frame->frametype == AST_FRAME_TEXT) {
7063+ ast_log(LOG_NOTICE, "text\n");
7064+ } else if (frame->frametype != AST_FRAME_IMAGE)
7065 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
7066 return 0;
7067 }
b684b13b 7068@@ -4818,7 +5130,7 @@
5e69ef1a
MT
7069 switch(condition) {
7070 case AST_CONTROL_BUSY:
7071 #ifdef ZAPATA_PRI
7072- if (p->priindication_oob && p->sig == SIG_PRI) {
7073+ if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
7074 chan->hangupcause = AST_CAUSE_USER_BUSY;
7075 chan->_softhangup |= AST_SOFTHANGUP_DEV;
7076 res = 0;
b684b13b 7077@@ -4900,7 +5212,7 @@
5e69ef1a
MT
7078 case AST_CONTROL_CONGESTION:
7079 chan->hangupcause = AST_CAUSE_CONGESTION;
7080 #ifdef ZAPATA_PRI
7081- if (p->priindication_oob && p->sig == SIG_PRI) {
7082+ if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
7083 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
7084 chan->_softhangup |= AST_SOFTHANGUP_DEV;
7085 res = 0;
b684b13b 7086@@ -5085,8 +5397,12 @@
5e69ef1a
MT
7087 if (state == AST_STATE_RING)
7088 tmp->rings = 1;
7089 tmp->tech_pvt = i;
7090- if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
7091- /* Only FXO signalled stuff can be picked up */
7092+#ifdef ZAPATA_PRI
7093+ if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS) || (i->sig == SIG_PRI)) {
7094+#else
7095+ if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
7096+#endif
7097+ /* Only FXO signalled stuff can be picked up */ /* i dont think so, mr. ulaw! we alaws like to pick up BRIs/PRIs */
7098 tmp->callgroup = i->callgroup;
7099 tmp->pickupgroup = i->pickupgroup;
7100 }
b684b13b 7101@@ -5216,6 +5532,7 @@
5e69ef1a
MT
7102 int len = 0;
7103 int res;
7104 int index;
7105+ int network;
7106 if (option_verbose > 2)
7107 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
7108 index = zt_get_index(chan, p, 1);
b684b13b 7109@@ -5234,10 +5551,17 @@
5e69ef1a
MT
7110 len = strlen(exten);
7111 res = 0;
7112 while((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
7113- if (len && !ast_ignore_pattern(chan->context, exten))
7114+ if (len && !ast_ignore_pattern(chan->context, exten)) {
7115 tone_zone_play_tone(p->subs[index].zfd, -1);
7116- else
7117- tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
7118+ } else {
7119+ network = p->pri->nodetype == PRI_NETWORK || p->pri->nodetype == BRI_NETWORK || p->pri->nodetype == BRI_NETWORK_PTMP;
7120+ if (network) {
7121+ tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
7122+ } else {
7123+ /* cpe be quiet */
7124+ tone_zone_play_tone(p->subs[index].zfd, -1);
7125+ }
7126+ }
7127 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
7128 timeout = matchdigittimeout;
7129 else
b684b13b 7130@@ -6724,6 +7048,8 @@
5e69ef1a
MT
7131 } else {
7132 if (si->totalchans == 31) { /* if it's an E1 */
7133 pris[*span].dchannels[0] = 16 + offset;
7134+ } else if (si->totalchans == 3) { /* if it's an S0 ZAPBRI */
7135+ pris[*span].dchannels[0] = 3 + offset;
7136 } else {
7137 pris[*span].dchannels[0] = 24 + offset;
7138 }
b684b13b 7139@@ -6811,6 +7137,10 @@
5f892677
MT
7140
7141 #endif
7142
7143+#ifdef ZAPATA_GSM
7144+static void *gsm_dchannel(void *vgsm);
7145+#endif
7146+
7147 static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_pri *pri, int reloading)
7148 {
7149 /* Make a zt_pvt structure for this interface (or CRV if "pri" is specified) */
b684b13b 7150@@ -6969,6 +7299,11 @@
5e69ef1a
MT
7151 destroy_zt_pvt(&tmp);
7152 return NULL;
7153 }
7154+ if ((pris[span].localdialplan) && (pris[span].localdialplan != localdialplan)) {
7155+ ast_log(LOG_ERROR, "Span %d is already a %s local dialing plan\n", span + 1, dialplan2str(pris[span].localdialplan));
7156+ destroy_zt_pvt(&tmp);
7157+ return NULL;
7158+ }
7159 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, idledial)) {
7160 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, idledial);
7161 destroy_zt_pvt(&tmp);
b684b13b 7162@@ -6996,6 +7331,17 @@
5e69ef1a
MT
7163 return NULL;
7164 }
7165 pris[span].nodetype = pritype;
7166+// XXX
7167+ if (pritype == BRI_NETWORK_PTMP) {
7168+ pris[span].dchanavail[0] = DCHAN_AVAILABLE;
7169+ pri_find_dchan(&pris[span]);
7170+ }
7171+// XXX tuev
7172+
7173+ if ((pritype == BRI_CPE) || (pritype == BRI_CPE_PTMP)) {
7174+ pris[span].dchanavail[0] = DCHAN_AVAILABLE;
7175+ pri_find_dchan(&pris[span]);
7176+ }
7177 pris[span].switchtype = myswitchtype;
7178 pris[span].nsf = nsf;
7179 pris[span].dialplan = dialplan;
b684b13b 7180@@ -7004,9 +7350,14 @@
5e69ef1a
MT
7181 pris[span].minunused = minunused;
7182 pris[span].minidle = minidle;
7183 pris[span].overlapdial = overlapdial;
7184+ pris[span].usercid = usercid;
7185+ pris[span].suspended_calls = NULL;
7186+ pris[span].holded_calls = NULL;
7187 pris[span].facilityenable = facilityenable;
7188 ast_copy_string(pris[span].idledial, idledial, sizeof(pris[span].idledial));
7189 ast_copy_string(pris[span].idleext, idleext, sizeof(pris[span].idleext));
7190+ ast_copy_string(pris[span].nocid, nocid, sizeof(pris[span].nocid) - 1);
7191+ ast_copy_string(pris[span].withheldcid, withheldcid, sizeof(pris[span].withheldcid) - 1);
7192 ast_copy_string(pris[span].internationalprefix, internationalprefix, sizeof(pris[span].internationalprefix));
7193 ast_copy_string(pris[span].nationalprefix, nationalprefix, sizeof(pris[span].nationalprefix));
7194 ast_copy_string(pris[span].localprefix, localprefix, sizeof(pris[span].localprefix));
b684b13b 7195@@ -7027,6 +7378,36 @@
5f892677
MT
7196 tmp->prioffset = 0;
7197 }
7198 #endif
7199+#ifdef ZAPATA_GSM
7200+ if (signalling == SIG_GSM) {
7201+ struct zt_bufferinfo bi;
7202+ ast_mutex_init(&tmp->gsm.lock);
7203+ strncpy(tmp->gsm.pin, gsm_modem_pin, sizeof(tmp->gsm.pin) - 1);
7204+ strncpy(tmp->gsm.exten, gsm_modem_exten, sizeof(tmp->gsm.exten) - 1);
7205+ snprintf(fn, sizeof(fn), "%d", channel + 1);
7206+ /* Open non-blocking */
7207+ tmp->gsm.fd = zt_open(fn);
7208+ bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
7209+ bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
7210+ bi.numbufs = 16;
7211+ bi.bufsize = 1024;
7212+ if (ioctl(tmp->gsm.fd, ZT_SET_BUFINFO, &bi)) {
7213+ ast_log(LOG_ERROR, "Unable to set buffer info on channel '%s': %s\n", fn, strerror(errno));
7214+ return NULL;
7215+ }
7216+ tmp->gsm.pvt = tmp;
7217+ tmp->gsm.span = tmp->span;
7218+ tmp->gsm.modul = gsm_new(tmp->gsm.fd, 0, tmp->gsm.pin, tmp->span);
7219+ if (ioctl(tmp->subs[SUB_REAL].zfd, ZT_AUDIOMODE, tmp->channel)) {
7220+ ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d: %s\n", tmp->channel, strerror(errno));
7221+ destroy_zt_pvt(&tmp);
7222+ return NULL;
7223+ }
7224+ if (ast_pthread_create(&tmp->gsm.master, NULL, gsm_dchannel, &tmp->gsm)) {
7225+ zt_close(tmp->gsm.fd);
7226+ }
7227+ }
7228+#endif
7229 #ifdef ZAPATA_R2
7230 if (signalling == SIG_R2) {
7231 if (r2prot < 0) {
b684b13b 7232@@ -7160,6 +7541,7 @@
5e69ef1a
MT
7233 tmp->restrictcid = restrictcid;
7234 tmp->use_callingpres = use_callingpres;
7235 tmp->priindication_oob = priindication_oob;
7236+ tmp->pritransfer = pritransfer;
7237 tmp->priexclusive = cur_priexclusive;
7238 if (tmp->usedistinctiveringdetection) {
7239 if (!tmp->use_callerid) {
b684b13b 7240@@ -7433,7 +7815,7 @@
5e69ef1a
MT
7241 break;
7242 if (!backwards && (x >= pri->numchans))
7243 break;
7244- if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
7245+ if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner && !pri->pvts[x]->call) {
7246 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
7247 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
7248 return x;
b684b13b 7249@@ -7480,7 +7862,7 @@
5e69ef1a
MT
7250 end = ifend;
7251 /* We do signed linear */
7252 oldformat = format;
7253- format &= (AST_FORMAT_SLINEAR | AST_FORMAT_ULAW);
7254+ format &= (AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW);
7255 if (!format) {
7256 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
7257 return NULL;
b684b13b 7258@@ -7640,6 +8022,11 @@
5e69ef1a
MT
7259 p->digital = 1;
7260 if (tmp)
7261 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
7262+ } else if (opt == 'm') {
7263+ /* If this is a modem/fax call, pretend to have the fax handled and dont do EC */
7264+ p->faxhandled = 1;
7265+ if (tmp)
7266+ tmp->transfercapability = AST_TRANS_CAP_3_1K_AUDIO;
7267 } else {
7268 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
7269 }
b684b13b 7270@@ -7679,6 +8066,164 @@
5f892677
MT
7271 return tmp;
7272 }
7273
7274+#ifdef ZAPATA_GSM
7275+static void handle_gsm_event(struct zt_gsm *gsm, gsm_event *e)
7276+{
7277+ struct ast_channel *c = NULL;
7278+ int law = ZT_LAW_ALAW;
7279+ int res = 0;
7280+
7281+ switch(e->e) {
7282+ case GSM_EVENT_DCHAN_UP:
7283+ if (option_verbose > 2)
7284+ ast_verbose(VERBOSE_PREFIX_3 "GSM Span %d registered to network!\n", gsm->span);
7285+ break;
7286+ case GSM_EVENT_DCHAN_DOWN:
7287+ if (option_verbose > 2)
7288+ ast_verbose(VERBOSE_PREFIX_3 "GSM Span %d unregistered from network!\n", gsm->span);
7289+ break;
7290+ case GSM_EVENT_RING:
7291+ ast_mutex_lock(&gsm->pvt->lock);
7292+ if (!ast_strlen_zero(e->ring.callingnum)) {
7293+ strncpy(gsm->pvt->cid_num, e->ring.callingnum, sizeof(gsm->pvt->cid_num) - 1);
7294+ }
7295+ if (!ast_strlen_zero(gsm->exten)) {
7296+ strncpy(gsm->pvt->exten, gsm->exten, sizeof(gsm->pvt->exten) - 1);
7297+ } else {
7298+ gsm->pvt->exten[0] = 's';
7299+ gsm->pvt->exten[1] = '\0';
7300+ }
7301+ c = zt_new(gsm->pvt, AST_STATE_RING, 1, SUB_REAL, ZT_LAW_ALAW, AST_TRANS_CAP_SPEECH);
7302+ if (c) {
7303+ if (option_verbose > 2)
7304+ ast_verbose(VERBOSE_PREFIX_3 "Ring on channel %d (from %s to %s)\n", e->ring.channel, e->ring.callingnum, gsm->exten);
7305+ gsm->pvt->owner = c;
7306+ if (ioctl(gsm->pvt->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
7307+ ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", gsm->pvt->channel, law);
7308+ res = zt_setlaw(gsm->pvt->subs[SUB_REAL].zfd, law);
7309+ res = set_actual_gain(gsm->pvt->subs[SUB_REAL].zfd, 0, gsm->pvt->rxgain, gsm->pvt->txgain, law);
7310+ if (res < 0) {
7311+ ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", gsm->pvt->channel);
7312+// } else {
7313+// ast_log(LOG_NOTICE, "tx gain %f rx gain %f law %d pvt->law %d\n", gsm->pvt->txgain, gsm->pvt->rxgain, law, gsm->pvt->law);
7314+ }
7315+ }
7316+ ast_mutex_unlock(&gsm->pvt->lock);
7317+ break;
7318+ case GSM_EVENT_HANGUP:
7319+ ast_verbose(VERBOSE_PREFIX_3 "Got hang up on channel %d\n", e->hangup.channel);
7320+ ast_mutex_lock(&gsm->pvt->lock);
7321+ gsm->pvt->alreadyhungup = 1;
7322+ if (gsm->pvt->owner) {
7323+ gsm->pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7324+ }
7325+ ast_mutex_unlock(&gsm->pvt->lock);
7326+ break;
7327+ case GSM_EVENT_ALERTING:
7328+ ast_mutex_lock(&gsm->pvt->lock);
7329+ gsm->pvt->subs[SUB_REAL].needringing =1;
7330+ ast_mutex_unlock(&gsm->pvt->lock);
7331+ break;
7332+ case GSM_EVENT_ANSWER:
7333+ ast_mutex_lock(&gsm->pvt->lock);
7334+ gsm->pvt->dialing = 0;
7335+ gsm->pvt->subs[SUB_REAL].needanswer =1;
7336+ gsm->pvt->ignoredtmf = 0;
7337+ ast_mutex_unlock(&gsm->pvt->lock);
7338+ break;
7339+ case GSM_EVENT_PIN_REQUIRED:
7340+ gsm_send_pin(gsm->modul, gsm->pin);
7341+ break;
7342+ case GSM_EVENT_SM_RECEIVED:
7343+ ast_verbose(VERBOSE_PREFIX_3 "SMS received on span %d. PDU: %s\n", gsm->span, e->sm_received.pdu);
7344+ break;
7345+ default:
7346+ ast_log(LOG_WARNING,"!! Unknown GSM event %d !!\n", e->e);
7347+ }
7348+}
7349+
7350+static void *gsm_dchannel(void *vgsm)
7351+{
7352+ struct zt_gsm *gsm = vgsm;
7353+ gsm_event *e;
7354+ struct timeval tv = {0,0}, *next;
7355+ fd_set rfds, efds;
7356+ int res,x;
7357+
7358+ if (!gsm) return NULL;
7359+
7360+ if (!gsm->modul) {
7361+ fprintf(stderr, "No gsm_mod\n");
7362+ return NULL;
7363+ }
7364+ gsm_set_debug(gsm->modul, 1);
7365+ for (;;) {
7366+
7367+ /* Run the D-Channel */
7368+ FD_ZERO(&rfds);
7369+ FD_ZERO(&efds);
7370+ FD_SET(gsm->fd, &rfds);
7371+ FD_SET(gsm->fd, &efds);
7372+
7373+ if ((next = gsm_schedule_next(gsm->modul))) {
7374+ gettimeofday(&tv, NULL);
7375+ tv.tv_sec = next->tv_sec - tv.tv_sec;
7376+ tv.tv_usec = next->tv_usec - tv.tv_usec;
7377+ if (tv.tv_usec < 0) {
7378+ tv.tv_usec += 1000000;
7379+ tv.tv_sec -= 1;
7380+ }
7381+ if (tv.tv_sec < 0) {
7382+ tv.tv_sec = 0;
7383+ tv.tv_usec = 0;
7384+ }
7385+ }
7386+ res = select(gsm->fd + 1, &rfds, NULL, &efds, next ? &tv : NULL);
7387+ e = NULL;
7388+
7389+ ast_mutex_lock(&gsm->lock);
7390+ if (!res) {
7391+ e = gsm_schedule_run(gsm->modul);
7392+ } else if (res > 0) {
7393+ e = gsm_check_event(gsm->modul, 1);
7394+ } else if (errno == ELAST) {
7395+ res = ioctl(gsm->fd, ZT_GETEVENT, &x);
7396+ printf("Got Zaptel event: %d\n", x);
7397+ } else if (errno != EINTR)
7398+ fprintf(stderr, "Error (%d) on select: %s\n", ELAST, strerror(errno));
7399+
7400+ if (!e) {
7401+ e = gsm_check_event(gsm->modul, 0);
7402+ }
7403+
7404+ if (e) {
7405+ handle_gsm_event(gsm, e);
7406+ }
7407+ ast_mutex_unlock(&gsm->lock);
7408+
7409+ res = ioctl(gsm->fd, ZT_GETEVENT, &x);
7410+
7411+ if (!res && x) {
7412+ switch (x) {
7413+ case ZT_EVENT_NOALARM:
7414+ ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", gsm->span);
7415+ usleep(1000);
7416+ gsm_restart(gsm->modul);
7417+ break;
7418+ case ZT_EVENT_ALARM:
7419+ ast_log(LOG_NOTICE, "Alarm detected on span %d\n", gsm->span);
7420+ break;
7421+ default:
7422+ fprintf(stderr, "Got event on GSM interface: %d\n", x);
7423+ }
7424+ }
7425+
7426+
7427+ }
7428+ return NULL;
7429+}
7430+
7431+#endif
7432
7433 #ifdef ZAPATA_PRI
7434 static struct zt_pvt *pri_find_crv(struct zt_pri *pri, int crv)
b684b13b 7435@@ -7693,6 +8238,57 @@
5e69ef1a
MT
7436 return NULL;
7437 }
7438
7439+static int pri_find_tei(struct zt_pri *pri, q931_call *c, int tei)
7440+{
7441+ int x=0;
7442+ for (x=0;x<pri->numchans;x++) {
7443+ if (!pri->pvts[x]) continue;
7444+ if ((pri->pvts[x]->tei == tei) && (pri->pvts[x]-> call != c)) {
7445+ return x;
7446+ }
7447+ }
7448+ return -1;
7449+}
7450+
7451+static struct zt_holded_call *pri_get_callonhold(struct zt_pri *pri, int cref, int tei) {
7452+ struct zt_holded_call *zhc = pri->holded_calls;
7453+ struct zt_holded_call *zhctemp = NULL;
7454+
7455+ while (zhc) {
7456+ if ((zhc->tei == tei) && ((zhc->cref == cref) || (cref == -1))) {
7457+ return zhc;
7458+ }
7459+ zhctemp = zhc;
7460+ if (zhc) zhc = zhc->next;
7461+ }
7462+ return NULL;
7463+}
7464+
7465+static int pri_destroy_callonhold(struct zt_pri *pri, struct zt_holded_call *onhold) {
7466+ struct zt_holded_call *zhc = pri->holded_calls;
7467+ struct zt_holded_call *zhctemp = NULL;
7468+
7469+ while (zhc) {
7470+ if (zhc == onhold) {
7471+ if (zhctemp) {
7472+ zhctemp->next = zhc->next;
7473+ zhc = zhctemp;
7474+ } else {
7475+ pri->holded_calls = zhc->next;
7476+ zhc = pri->holded_calls;
7477+ zhctemp = NULL;
7478+ }
7479+ }
7480+ zhctemp = zhc;
7481+ if (zhc) zhc = zhc->next;
7482+ }
7483+ if (onhold) {
7484+ free(onhold);
7485+ onhold = NULL;
7486+ return 1;
7487+ }
7488+ return 0;
7489+}
7490
7491 static int pri_find_principle(struct zt_pri *pri, int channel)
7492 {
b684b13b 7493@@ -7725,7 +8321,9 @@
5e69ef1a
MT
7494 static int pri_fixup_principle(struct zt_pri *pri, int principle, q931_call *c)
7495 {
7496 int x;
7497+ int res = 0;
7498 struct zt_pvt *crv;
7499+ char tmpname[256];
7500 if (!c) {
7501 if (principle < 0)
7502 return -1;
b684b13b 7503@@ -7739,6 +8337,7 @@
5e69ef1a
MT
7504 /* First, check for other bearers */
7505 for (x=0;x<pri->numchans;x++) {
7506 if (!pri->pvts[x]) continue;
7507+// ast_log(LOG_NOTICE, "principle %d channel %d call %d channel[x]->call %d\n",principle, x, c, pri->pvts[x]->call);
7508 if (pri->pvts[x]->call == c) {
7509 /* Found our call */
7510 if (principle != x) {
b684b13b 7511@@ -7752,19 +8351,56 @@
5e69ef1a
MT
7512 }
7513 /* Fix it all up now */
7514 pri->pvts[principle]->owner = pri->pvts[x]->owner;
7515+ pri->pvts[principle]->outgoing = pri->pvts[x]->outgoing;
7516 if (pri->pvts[principle]->owner) {
7517 snprintf(pri->pvts[principle]->owner->name, sizeof(pri->pvts[principle]->owner->name),
7518 "Zap/%d:%d-%d", pri->trunkgroup, pri->pvts[principle]->channel, 1);
7519 pri->pvts[principle]->owner->tech_pvt = pri->pvts[principle];
7520 pri->pvts[principle]->owner->fds[0] = pri->pvts[principle]->subs[SUB_REAL].zfd;
7521 pri->pvts[principle]->subs[SUB_REAL].owner = pri->pvts[x]->subs[SUB_REAL].owner;
7522- } else
7523+ } else {
7524 ast_log(LOG_WARNING, "Whoa, there's no owner, and we're having to fix up channel %d to channel %d\n", pri->pvts[x]->channel, pri->pvts[principle]->channel);
7525+ }
7526 pri->pvts[principle]->call = pri->pvts[x]->call;
7527+ pri->pvts[principle]->dsp = pri->pvts[x]->dsp;
7528+ pri->pvts[principle]->alreadyhungup = pri->pvts[x]->alreadyhungup;
7529+ pri->pvts[principle]->digital = pri->pvts[x]->digital;
7530+ pri->pvts[principle]->faxhandled = pri->pvts[x]->faxhandled;
7531+
7532+ if ((pri->nodetype == BRI_CPE_PTMP) || (pri->nodetype == BRI_CPE)) {
7533+ /* this might also apply for other pri types! */
7534+ pri->pvts[principle]->law = pri->pvts[x]->law;
7535+ if (ioctl(pri->pvts[principle]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &pri->pvts[principle]->law) == -1)
7536+ ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", pri->pvts[principle]->channel, pri->pvts[principle]->law);
7537+ res = zt_setlaw(pri->pvts[principle]->subs[SUB_REAL].zfd, pri->pvts[principle]->law);
7538+ if (res < 0)
7539+ ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[principle]->channel);
7540+ if (!pri->pvts[principle]->digital) {
7541+ res = set_actual_gain(pri->pvts[principle]->subs[SUB_REAL].zfd, 0, pri->pvts[principle]->rxgain, pri->pvts[principle]->txgain, pri->pvts[principle]->law);
7542+ } else {
7543+ res = set_actual_gain(pri->pvts[principle]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[principle]->law);
7544+ }
7545+ if (res < 0)
7546+ ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[principle]->channel);
7547+ zt_confmute(pri->pvts[x], 0);
7548+ update_conf(pri->pvts[x]);
7549+ reset_conf(pri->pvts[x]);
7550+ restore_gains(pri->pvts[x]);
7551+ zt_disable_ec(pri->pvts[x]);
7552+ zt_setlinear(pri->pvts[x]->subs[SUB_REAL].zfd, 0);
7553+ }
7554+
7555+ if (pri->pvts[principle]->owner) {
7556+ snprintf(tmpname, sizeof(tmpname), "Zap/%d-1", pri->pvts[principle]->channel);
7557+ ast_change_name(pri->pvts[principle]->owner, tmpname);
7558+ }
7559+
7560+
7561 /* Free up the old channel, now not in use */
7562 pri->pvts[x]->subs[SUB_REAL].owner = NULL;
7563 pri->pvts[x]->owner = NULL;
7564 pri->pvts[x]->call = NULL;
7565+ pri->pvts[x]->dsp = NULL;
7566 }
7567 return principle;
7568 }
b684b13b 7569@@ -7793,7 +8429,9 @@
5e69ef1a
MT
7570 }
7571 crv = crv->next;
7572 }
7573- ast_log(LOG_WARNING, "Call specified, but not found?\n");
7574+ if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
7575+ ast_log(LOG_WARNING, "Call specified, but not found?\n");
7576+ }
7577 return -1;
7578 }
7579
b684b13b 7580@@ -7855,86 +8493,33 @@
5e69ef1a
MT
7581 #ifndef PRI_RESTART
7582 #error "Upgrade your libpri"
7583 #endif
7584-static void zt_pri_message(struct pri *pri, char *s)
7585+static void zt_pri_message(char *s, int span)
7586 {
7587- int x, y;
7588- int dchan = -1, span = -1;
7589- int dchancount = 0;
7590-
7591- if (pri) {
7592- for (x = 0; x < NUM_SPANS; x++) {
7593- for (y = 0; y < NUM_DCHANS; y++) {
7594- if (pris[x].dchans[y])
7595- dchancount++;
7596-
7597- if (pris[x].dchans[y] == pri)
7598- dchan = y;
7599- }
7600- if (dchan >= 0) {
7601- span = x;
7602- break;
7603- }
7604- dchancount = 0;
7605- }
7606- if ((dchan >= 0) && (span >= 0)) {
7607- if (dchancount > 1)
7608- ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
7609- else
7610- ast_verbose("%s", s);
7611- } else
7612- ast_verbose("PRI debug error: could not find pri associated it with debug message output\n");
7613- } else
7614- ast_verbose("%s", s);
7615-
7616- ast_mutex_lock(&pridebugfdlock);
7617-
7618- if (pridebugfd >= 0)
7619- write(pridebugfd, s, strlen(s));
7620-
7621- ast_mutex_unlock(&pridebugfdlock);
7622+ ast_verbose("%d %s", span, s);
7623 }
7624
7625-static void zt_pri_error(struct pri *pri, char *s)
7626+static void zt_pri_error(char *s, int span)
7627 {
7628- int x, y;
7629- int dchan = -1, span = -1;
7630- int dchancount = 0;
7631-
7632- if (pri) {
7633- for (x = 0; x < NUM_SPANS; x++) {
7634- for (y = 0; y < NUM_DCHANS; y++) {
7635- if (pris[x].dchans[y])
7636- dchancount++;
7637-
7638- if (pris[x].dchans[y] == pri)
7639- dchan = y;
7640- }
7641- if (dchan >= 0) {
7642- span = x;
7643- break;
7644- }
7645- dchancount = 0;
7646- }
7647- if ((dchan >= 0) && (span >= 0)) {
7648- if (dchancount > 1)
7649- ast_log(LOG_WARNING, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
7650- else
7651- ast_verbose("%s", s);
7652- } else
7653- ast_verbose("PRI debug error: could not find pri associated it with debug message output\n");
7654- } else
7655- ast_log(LOG_WARNING, "%s", s);
7656-
7657- ast_mutex_lock(&pridebugfdlock);
5f892677
MT
7658+ ast_log(LOG_WARNING, "%d %s", span, s);
7659+}
7660
5e69ef1a
MT
7661- if (pridebugfd >= 0)
7662- write(pridebugfd, s, strlen(s));
5f892677
MT
7663+#ifdef ZAPATA_GSM
7664+static void zt_gsm_message(char *s, int span)
7665+{
7666+// ast_verbose("%d %s", span, s);
7667+}
7668
5e69ef1a 7669- ast_mutex_unlock(&pridebugfdlock);
5f892677
MT
7670+static void zt_gsm_error(char *s, int span)
7671+{
7672+ ast_log(LOG_WARNING, "GSM: %d %s", span, s);
5e69ef1a 7673 }
5f892677 7674+#endif
5e69ef1a
MT
7675
7676 static int pri_check_restart(struct zt_pri *pri)
7677 {
b684b13b 7678+ if ((pri->nodetype != PRI_NETWORK) && (pri->nodetype != PRI_CPE)) {
5e69ef1a
MT
7679+ return 0;
7680+ }
7681 do {
7682 pri->resetpos++;
7683 } while((pri->resetpos < pri->numchans) &&
b684b13b 7684@@ -8017,6 +8602,32 @@
5e69ef1a
MT
7685 }
7686 }
7687
7688+static void pri_make_callerid(struct zt_pri *pri, char *callerid, int callerid_len, char *callingnum, int callingnum_len, int callingplan, int callingpres, int stripmsd) {
7689+ if (callingnum && (callingnum_len > stripmsd)) {
7690+ callingnum += stripmsd;
7691+ }
7692+ switch (callingplan) {
7693+ case PRI_INTERNATIONAL_ISDN:
7694+ snprintf(callerid, callerid_len, "%s%s", pri->internationalprefix, callingnum);
7695+ break;
7696+ case PRI_NATIONAL_ISDN:
7697+ snprintf(callerid, callerid_len, "%s%s", pri->nationalprefix, callingnum);
7698+ break;
7699+ case PRI_LOCAL_ISDN:
7700+ snprintf(callerid, callerid_len, "%s%s", pri->localprefix, callingnum);
7701+ break;
7702+ case PRI_PRIVATE:
7703+ snprintf(callerid, callerid_len, "%s%s", pri->privateprefix, callingnum);
7704+ break;
7705+ case PRI_UNKNOWN:
7706+ snprintf(callerid, callerid_len, "%s%s", pri->unknownprefix, callingnum);
7707+ break;
7708+ default:
7709+ snprintf(callerid, callerid_len, "%s", callingnum);
7710+ break;
7711+ }
7712+}
7713+
7714 static void *pri_dchannel(void *vpri)
7715 {
7716 struct zt_pri *pri = vpri;
b684b13b 7717@@ -8108,6 +8719,8 @@
5e69ef1a
MT
7718 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
7719 activeidles++;
7720 }
7721+ // ast_log(LOG_NOTICE, "name = %s condition = %d index = %d (%d) zfd = %d res = %d\n",chan->name, condition, index, SUB_REAL, p->subs[index].zfd, res);
7722+
7723 #if 0
7724 printf("nextidle: %d, haveidles: %d, minunsed: %d\n",
7725 nextidle, haveidles, minunused);
b684b13b 7726@@ -8209,9 +8822,36 @@
5e69ef1a
MT
7727 if (x == ZT_EVENT_ALARM) {
7728 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
7729 pri_find_dchan(pri);
7730+ if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
7731+ if (pri->pri) {
7732+ ast_log(LOG_NOTICE, "pri_shutdown\n");
7733+ for (i=0; i<pri->numchans; i++) {
7734+ struct zt_pvt *p = pri->pvts[i];
7735+ if (p) {
7736+ if (p->call) {
7737+ if (p->pri && p->pri->pri) {
7738+ pri_destroycall(p->pri->pri, p->call);
7739+ p->call = NULL;
7740+ p->tei = -1;
7741+ } else
7742+ ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
7743+ }
7744+ if (p->owner)
7745+ p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7746+ p->inalarm = 1;
7747+ }
7748+ }
7749+ pri_shutdown(pri->pri);
7750+ }
7751+ }
7752 } else if (x == ZT_EVENT_NOALARM) {
7753- pri->dchanavail[which] |= DCHAN_NOTINALARM;
7754- pri_restart(pri->dchans[which]);
7755+ if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
7756+ pri->dchanavail[which] |= DCHAN_NOTINALARM;
7757+ pri->dchanavail[which] |= DCHAN_UP;
7758+ } else {
7759+ pri->dchanavail[which] |= DCHAN_NOTINALARM;
7760+ pri_restart(pri->dchans[which]);
7761+ }
7762 }
7763
7764 if (option_debug)
b684b13b 7765@@ -8223,8 +8863,7 @@
5e69ef1a
MT
7766 break;
7767 }
7768 } else if (errno != EINTR)
7769- ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
7770-
7771+ ast_log(LOG_WARNING, "pri_event returned error %d (%s) on span %d\n", errno, strerror(errno), pri->span);
7772 if (e) {
7773 if (pri->debug)
7774 pri_dump_event(pri->dchans[which], e);
b684b13b 7775@@ -8232,32 +8871,102 @@
5e69ef1a
MT
7776 pri->dchanavail[which] |= DCHAN_UP;
7777 switch(e->e) {
7778 case PRI_EVENT_DCHAN_UP:
7779- if (option_verbose > 1)
7780- ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
7781- pri->dchanavail[which] |= DCHAN_UP;
7782- if (!pri->pri) pri_find_dchan(pri);
7783-
7784- /* Note presense of D-channel */
7785- time(&pri->lastreset);
7786-
7787- /* Restart in 5 seconds */
7788- if (pri->resetinterval > -1) {
7789- pri->lastreset -= pri->resetinterval;
7790- pri->lastreset += 5;
7791- }
7792- pri->resetting = 0;
7793- /* Take the channels from inalarm condition */
7794- for (i=0; i<pri->numchans; i++)
7795- if (pri->pvts[i]) {
7796- pri->pvts[i]->inalarm = 0;
7797- }
7798+ if (pri->nodetype == BRI_NETWORK_PTMP) {
7799+ if (option_verbose > 3)
7800+ ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
7801+ pri->dchanavail[which] |= (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP);
7802+ pri_find_dchan(pri);
7803+
7804+ /* Note presense of D-channel */
7805+ time(&pri->lastreset);
7806+
7807+ pri->resetting = 0;
7808+ /* Take the channels from inalarm condition */
7809+ for (i=0; i<pri->numchans; i++)
7810+ if (pri->pvts[i]) {
7811+ pri->pvts[i]->inalarm = 0;
7812+ }
7813+ } else {
7814+ if (pri->nodetype == BRI_CPE_PTMP) {
7815+ if (option_verbose > 3)
7816+ ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
7817+ } else {
7818+ if (option_verbose > 1)
7819+ ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
7820+ }
7821+ pri->dchanavail[which] |= (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP);
7822+ pri_find_dchan(pri);
7823+
7824+ /* Note presense of D-channel */
7825+ time(&pri->lastreset);
7826+
7827+ /* Restart in 5 seconds */
7828+ pri->lastreset -= pri->resetinterval;
7829+ pri->lastreset += 5;
7830+ pri->resetting = 0;
7831+ /* Take the channels from inalarm condition */
7832+ for (i=0; i<pri->numchans; i++) {
7833+ struct zt_pvt *p = pri->pvts[i];
7834+ if (p) {
7835+ p->inalarm = 0;
7836+ /* hang up calls that are not bridged yet, dont touch bridged calls */
7837+ if (p->call) {
7838+ if (p->pri && p->pri->pri) {
7839+ if (p->owner) {
7840+ if (p->owner->_state != AST_STATE_UP) {
7841+ p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7842+ pri_destroycall(p->pri->pri, p->call);
5f892677 7843+ p->call = NULL;
5e69ef1a
MT
7844+ }
7845+ } else {
7846+ pri_destroycall(p->pri->pri, p->call);
5f892677 7847+ p->call = NULL;
5e69ef1a 7848+ }
5e69ef1a
MT
7849+ }
7850+ }
7851+ }
7852+ }
7853+ }
7854 break;
7855 case PRI_EVENT_DCHAN_DOWN:
7856- if (option_verbose > 1)
7857- ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
7858- pri->dchanavail[which] &= ~DCHAN_UP;
7859- pri_find_dchan(pri);
7860- if (!pri_is_up(pri)) {
7861+ if (pri->nodetype == BRI_NETWORK_PTMP) {
7862+ if (option_verbose > 3)
7863+ ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
7864+ // PTMP BRIs have N dchans, handled by libpri
7865+ if (e->gen.tei == 0) break;
7866+ /* Hangup active channels */
7867+ for (i=0; i<pri->numchans; i++) {
7868+ struct zt_pvt *p = pri->pvts[i];
7869+ if (p) {
7870+ // ast_log(LOG_NOTICE, "chan %d tei %d\n",i,p->tei);
7871+ if (p->tei == e->gen.tei) {
7872+ if (p->call) {
7873+ if (p->pri && p->pri->pri) {
5f892677 7874+ // pri_hangup(p->pri->pri, p->call, -1);
5e69ef1a
MT
7875+ pri_destroycall(p->pri->pri, p->call);
7876+ p->tei = -1;
7877+ p->call = NULL;
7878+ } else
7879+ ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
7880+ }
7881+ if (p->owner)
7882+ p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7883+ p->inalarm = 1;
7884+ p->tei = -1;
7885+ }
7886+ }
7887+ }
7888+ } else {
7889+ if (pri->nodetype == BRI_CPE_PTMP) {
7890+ if (option_verbose > 3)
7891+ ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
7892+ } else {
7893+ if (option_verbose > 1)
7894+ ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
7895+ }
7896+ pri->dchanavail[which] &= ~DCHAN_UP;
7897+ pri_find_dchan(pri);
7898+ if (!pri_is_up(pri)) {
7899 pri->resetting = 0;
7900 /* Hangup active channels and put them in alarm mode */
7901 for (i=0; i<pri->numchans; i++) {
b684b13b 7902@@ -8265,19 +8974,29 @@
5e69ef1a
MT
7903 if (p) {
7904 if (p->call) {
7905 if (p->pri && p->pri->pri) {
7906- pri_hangup(p->pri->pri, p->call, -1);
5f892677
MT
7907- pri_destroycall(p->pri->pri, p->call);
7908- p->call = NULL;
7909+ if (p->owner) {
7910+ if (p->owner->_state != AST_STATE_UP) {
7911+ // pri_hangup(p->pri->pri, p->call, -1);
7912+ pri_destroycall(p->pri->pri, p->call);
7913+ p->call = NULL;
7914+ p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7915+ p->inalarm = 1;
7916+ }
7917+ } else {
7918+ pri_destroycall(p->pri->pri, p->call);
7919+ p->call = NULL;
7920+ p->inalarm = 1;
7921+ }
5e69ef1a 7922 } else
5f892677
MT
7923 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
7924 }
7925 if (p->realcall) {
7926- pri_hangup_all(p->realcall, pri);
7927- } else if (p->owner)
7928- p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7929- p->inalarm = 1;
7930+ pri_hangup_all(p->realcall, pri);
7931+ p->inalarm = 1;
7932+ }
5e69ef1a
MT
7933 }
7934 }
7935+ }
7936 }
7937 break;
7938 case PRI_EVENT_RESTART:
b684b13b 7939@@ -8312,8 +9031,8 @@
5e69ef1a
MT
7940 pri_destroycall(pri->pri, pri->pvts[x]->call);
7941 pri->pvts[x]->call = NULL;
7942 }
7943- if (pri->pvts[chanpos]->realcall)
7944- pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
7945+ if (pri->pvts[x]->realcall)
7946+ pri_hangup_all(pri->pvts[x]->realcall, pri);
7947 else if (pri->pvts[x]->owner)
7948 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7949 ast_mutex_unlock(&pri->pvts[x]->lock);
b684b13b 7950@@ -8347,7 +9066,6 @@
5e69ef1a
MT
7951 }
7952 }
7953 break;
7954-
7955 case PRI_EVENT_INFO_RECEIVED:
7956 chanpos = pri_find_principle(pri, e->ring.channel);
7957 if (chanpos < 0) {
b684b13b 7958@@ -8356,9 +9074,11 @@
5e69ef1a
MT
7959 } else {
7960 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
7961 if (chanpos > -1) {
7962+// ast_log(LOG_NOTICE, "INFO received on channel %d/%d span %d\n",
7963+// PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
7964 ast_mutex_lock(&pri->pvts[chanpos]->lock);
7965 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
7966- if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
7967+ if (pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
7968 /* how to do that */
7969 int digitlen = strlen(e->ring.callednum);
7970 char digit;
b684b13b 7971@@ -8370,6 +9090,14 @@
5e69ef1a
MT
7972 zap_queue_frame(pri->pvts[chanpos], &f, pri);
7973 }
7974 }
7975+ if (!pri->overlapdial) {
7976+ strncat(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
7977+ if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
7978+ tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
7979+ } else {
7980+ tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
7981+ }
7982+ }
7983 }
7984 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7985 }
b684b13b 7986@@ -8377,39 +9105,58 @@
5e69ef1a
MT
7987 break;
7988 case PRI_EVENT_RING:
7989 crv = NULL;
7990- if (e->ring.channel == -1)
7991+ if (e->ring.channel == -1) {
7992+ /* if no channel specified find one empty */
7993 chanpos = pri_find_empty_chan(pri, 1);
7994- else
7995+ } else {
7996 chanpos = pri_find_principle(pri, e->ring.channel);
7997- /* if no channel specified find one empty */
7998+ }
7999 if (chanpos < 0) {
8000- ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
8001- PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8002+ /* no channel specified and no free channel. this is a callwating SETUP */
8003+ if (e->ring.channel == -1) {
8004+ if (option_verbose > 2)
8005+ ast_verbose(VERBOSE_PREFIX_3 "Ignoring callwaiting SETUP on channel %d/%d span %d %d\n", PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span, e->ring.channel);
5f892677 8006+ pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_USER_BUSY, -1);
5e69ef1a
MT
8007+ break;
8008+ }
8009 } else {
8010+ /* ok, we got a b channel for this call, lock it */
8011 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8012 if (pri->pvts[chanpos]->owner) {
8013- if (pri->pvts[chanpos]->call == e->ring.call) {
8014- ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
8015- PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8016- break;
8017- } else {
8018- ast_log(LOG_WARNING, "Ring requested on channel %d/%d already in use on span %d. Hanging up owner.\n",
8019+ /* safety check, for messed up retransmissions? */
8020+ if (pri->pvts[chanpos]->call == e->ring.call) {
8021+ ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
8022 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8023- if (pri->pvts[chanpos]->realcall)
8024- pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8025- else
8026- pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8027- ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8028- chanpos = -1;
b684b13b 8029+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
5e69ef1a
MT
8030+ chanpos = -1;
8031+ break;
8032+ } else {
8033+ ast_log(LOG_WARNING, "Ring requested on channel %d/%d already in use on span %d. Hanging up owner.\n",
8034+ PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
b684b13b 8035+ if (pri->pvts[chanpos]->realcall) {
5e69ef1a 8036+ pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
b684b13b 8037+ } else {
5e69ef1a 8038+ pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
b684b13b
MT
8039+ /* XXX destroy the call here, so we can accept the retransmission as a new call */
8040+ pri_destroycall(pri->pri, e->ring.call);
8041 }
8042- }
8043- if (chanpos > -1)
8044 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
5e69ef1a
MT
8045+ chanpos = -1;
8046+ break;
8047+ }
8048+ }
8049+ if (chanpos > -1) {
8050+ /* everything is ok with the b channel */
8051+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8052+ }
8053 }
8054- if ((chanpos < 0) && (e->ring.flexible))
8055- chanpos = pri_find_empty_chan(pri, 1);
8056+ /* actually, we already got a valid channel by now */
8057 if (chanpos > -1) {
8058 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8059+ /* dont detect dtmfs before the signalling is done */
8060+ disable_dtmf_detect(pri->pvts[chanpos]);
8061+ /* this channel is owned by this TEI */
8062+ pri->pvts[chanpos]->tei = e->ring.tei;
8063 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
8064 /* Should be safe to lock CRV AFAIK while bearer is still locked */
8065 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
b684b13b 8066@@ -8423,13 +9170,14 @@
5f892677
MT
8067 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);
8068 } else
8069 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);
8070- pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
8071+ pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE, -1);
8072 if (crv)
8073 ast_mutex_unlock(&crv->lock);
8074 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
5e69ef1a
MT
8075 break;
8076 }
8077 }
8078+ /* assign call to b channel */
8079 pri->pvts[chanpos]->call = e->ring.call;
8080 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
8081 if (pri->pvts[chanpos]->use_callerid) {
b684b13b 8082@@ -8454,29 +9202,78 @@
5e69ef1a
MT
8083 }
8084 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
8085 e->ring.redirectingnum, e->ring.callingplanrdnis);
8086+ /* get callingpres */
8087+ pri->pvts[chanpos]->cid_pres = e->ring.callingpres;
8088+ switch (e->ring.callingpres) {
8089+ case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
8090+ case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
8091+ case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
8092+ case PRES_PROHIB_NETWORK_NUMBER:
8093+ strncpy(pri->pvts[chanpos]->cid_name, pri->withheldcid, sizeof(pri->pvts[chanpos]->cid_name));
8094+ break;
8095+ case PRES_NUMBER_NOT_AVAILABLE:
8096+ strncpy(pri->pvts[chanpos]->cid_name, pri->nocid, sizeof(pri->pvts[chanpos]->cid_name));
8097+ break;
8098+ }
8099 /* If immediate=yes go to s|1 */
8100 if (pri->pvts[chanpos]->immediate) {
8101 if (option_verbose > 2)
8102 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
8103 pri->pvts[chanpos]->exten[0] = 's';
8104 pri->pvts[chanpos]->exten[1] = '\0';
8105- }
8106- /* Get called number */
8107- else if (!ast_strlen_zero(e->ring.callednum)) {
8108- ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
8109- ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
8110- } else
8111- pri->pvts[chanpos]->exten[0] = '\0';
8112- /* Set DNID on all incoming calls -- even immediate */
8113- if (!ast_strlen_zero(e->ring.callednum))
8114- ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
8115- /* No number yet, but received "sending complete"? */
8116- if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
8117+ } else if (ast_strlen_zero(e->ring.callednum)) {
8118+ /* called party number is empty */
8119+ if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
8120+ if (!pri->overlapdial) {
8121+ // be able to set digittimeout for BRI phones
8122+ pri->pvts[chanpos]->exten[0] = 's';
8123+ pri->pvts[chanpos]->exten[1] = '\0';
8124+ tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
8125+ } else {
8126+ pri->pvts[chanpos]->exten[0] = '\0';
8127+ }
8128+ } else {
8129+ if (pri->nodetype == BRI_CPE) {
8130+ /* fix for .at p2p bri lines */
8131+ pri->pvts[chanpos]->exten[0] = 's';
8132+ pri->pvts[chanpos]->exten[1] = '\0';
8133+ } else {
8134+ pri->pvts[chanpos]->exten[0] = '\0';
8135+ }
8136+ }
8137+ /* No number yet, but received "sending complete"? */
8138+ if (e->ring.complete) {
8139 if (option_verbose > 2)
8140 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
8141 pri->pvts[chanpos]->exten[0] = 's';
8142 pri->pvts[chanpos]->exten[1] = '\0';
8143- }
8144+ }
8145+ } else {
8146+ /* Get called number */
8147+ pri_make_callerid(pri, pri->pvts[chanpos]->dnid, sizeof(pri->pvts[chanpos]->dnid), e->ring.callednum, sizeof(e->ring.callednum), e->ring.calledplan, 0, pri->pvts[chanpos]->stripmsd);
8148+ pri_make_callerid(pri, pri->pvts[chanpos]->exten, sizeof(pri->pvts[chanpos]->exten), e->ring.callednum, sizeof(e->ring.callednum), e->ring.calledplan, 0, pri->pvts[chanpos]->stripmsd);
8149+ if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
8150+ /* if we get the next digit we should stop the dialtone */
8151+ if (!pri->overlapdial) {
8152+ // with overlapdial=no the exten is always prefixed by "s"
8153+ if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
8154+ tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
8155+ } else {
8156+ tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
8157+ }
8158+ } else {
8159+ if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten)) {
8160+ tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
8161+ } else {
8162+ tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
8163+ }
8164+ }
8165+ }
8166+ }
8167+ /* Part 3: create channel, setup audio... */
8168+ /* Set DNID on all incoming calls -- even immediate */
8169+ if (!ast_strlen_zero(e->ring.callednum))
8170+ strncpy(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid) - 1);
8171 /* Make sure extension exists (or in overlap dial mode, can exist) */
8172 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
8173 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
b684b13b 8174@@ -8495,22 +9292,38 @@
5e69ef1a
MT
8175 res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
8176 if (res < 0)
8177 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
8178- res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
8179+ if (IS_DIGITAL(e->ring.ctype)) {
8180+ res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[chanpos]->law);
8181+ } else {
8182+ res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
8183+ }
8184 if (res < 0)
8185 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
8186- if (e->ring.complete || !pri->overlapdial)
8187+ if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
8188+ if (e->ring.complete || !pri->overlapdial) {
8189 /* Just announce proceeding */
8190 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
8191- else {
8192+ // pri->pvts[chanpos]->ignoredtmf = 0;
8193+ } else {
8194 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
8195 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
8196 else
8197 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
8198+ }
8199+ } else {
8200+ /* BRI_NETWORK | BRI_NETWORK_PTMP */
8201+ if (pri->overlapdial || (!strcasecmp(pri->pvts[chanpos]->exten, "s"))) {
8202+ /* send a SETUP_ACKNOWLEDGE */
8203+ pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
8204+ } else {
8205+ /* send an ALERTING ??? wtf */
8206+ // pri_acknowledge(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
8207+ pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
8208+ }
8209 }
8210- /* Get the use_callingpres state */
8211- pri->pvts[chanpos]->callingpres = e->ring.callingpres;
8212-
8213- /* Start PBX */
8214+
8215+ /* overlapdial = yes and the extension can be valid */
8216+
8217 if (pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
8218 /* Release the PRI lock while we create the channel */
8219 ast_mutex_unlock(&pri->lock);
b684b13b 8220@@ -8518,14 +9331,31 @@
5f892677
MT
8221 /* Set bearer and such */
8222 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
8223 c = zt_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
8224+ if (c && (e->ring.lowlayercompat[0] > 0)) {
8225+ memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
8226+ }
8227 pri->pvts[chanpos]->owner = &inuse;
5e69ef1a
MT
8228 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
8229 } else {
8230 c = zt_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
5f892677
MT
8231+ if (c && (e->ring.lowlayercompat[0] > 0)) {
8232+ memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
8233+ }
5e69ef1a
MT
8234+ zt_enable_ec(pri->pvts[chanpos]);
8235 }
8236 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
8237 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
8238 }
8239+ if (!ast_strlen_zero(e->ring.callingnum)) {
8240+ char tmpstr[256];
8241+ pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
8242+ pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
8243+ }
8244+ if (!ast_strlen_zero(e->ring.callingani)) {
8245+ char tmpstr[256];
8246+ pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
5f892677 8247+ pbx_builtin_setvar_helper(c, "PRI_USER_CID", tmpstr);
5e69ef1a
MT
8248+ }
8249 if(e->ring.ani2 >= 0) {
8250 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
8251 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
b684b13b 8252@@ -8545,8 +9375,8 @@
5e69ef1a
MT
8253 ast_mutex_lock(&pri->lock);
8254 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
8255 if (option_verbose > 2)
8256- ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
8257- plancallingnum, !ast_strlen_zero(pri->pvts[chanpos]->exten) ? pri->pvts[chanpos]->exten : "<unspecified>",
8258+ ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap %s call from '%s' to '%s' on channel %d/%d, span %d\n",
8259+ pri->pvts[chanpos]->digital ? "data" : "voice", plancallingnum, !ast_strlen_zero(pri->pvts[chanpos]->exten) ? pri->pvts[chanpos]->exten : "<unspecified>",
8260 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8261 } else {
8262 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
b684b13b 8263@@ -8554,14 +9384,18 @@
5f892677
MT
8264 if (c)
8265 ast_hangup(c);
8266 else {
8267- pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
8268+ pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION, -1);
8269 pri->pvts[chanpos]->call = NULL;
5e69ef1a
MT
8270 }
8271 }
8272 } else {
8273+ /* overlapdial = no */
8274 ast_mutex_unlock(&pri->lock);
8275 /* Release PRI lock while we create the channel */
8276 c = zt_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
5f892677
MT
8277+ if (c && (e->ring.lowlayercompat[0] > 0)) {
8278+ memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
8279+ }
8280 ast_mutex_lock(&pri->lock);
8281 if (c) {
8282 char calledtonstr[10];
b684b13b 8283@@ -8582,23 +9416,40 @@
5e69ef1a
MT
8284 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
8285 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
8286 if (option_verbose > 2)
8287- ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
8288- plancallingnum, pri->pvts[chanpos]->exten,
8289+ ast_verbose(VERBOSE_PREFIX_3 "Accepting %s call from '%s' to '%s' on channel %d/%d, span %d\n",
8290+ pri->pvts[chanpos]->digital ? "data" : "voice", e->ring.callingnum, pri->pvts[chanpos]->exten,
8291 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8292 zt_enable_ec(pri->pvts[chanpos]);
8293+ if(!ast_strlen_zero(e->ring.callingsubaddr)) {
8294+ pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
8295+ }
8296+ if (!ast_strlen_zero(e->ring.callingnum)) {
8297+ char tmpstr[256];
8298+ pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
8299+ pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
8300+ }
8301+ if (!ast_strlen_zero(e->ring.callingani)) {
8302+ char tmpstr[256];
8303+ pri_make_callerid(pri, tmpstr,sizeof(tmpstr), e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
8304+ pbx_builtin_setvar_helper(c, "PRI_USER_CID", e->ring.callednum);
8305+ }
8306+ if (!ast_strlen_zero(e->ring.useruserinfo)) {
8307+ pbx_builtin_setvar_helper(c, "UUI", e->ring.useruserinfo);
8308+ }
8309 } else {
8310 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
8311 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
5f892677
MT
8312- pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
8313+ pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION, -1);
8314 pri->pvts[chanpos]->call = NULL;
5e69ef1a
MT
8315 }
8316 }
8317 } else {
8318+ /* invalid extension */
8319 if (option_verbose > 2)
8320 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
8321 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
5f892677
MT
8322 pri->pvts[chanpos]->prioffset, pri->span);
8323- pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
8324+ pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED, -1);
8325 pri->pvts[chanpos]->call = NULL;
8326 pri->pvts[chanpos]->exten[0] = '\0';
8327 }
b684b13b 8328@@ -8606,7 +9457,7 @@
5f892677
MT
8329 ast_mutex_unlock(&crv->lock);
8330 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8331 } else
8332- pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
8333+ pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL, -1);
8334 break;
8335 case PRI_EVENT_RINGING:
8336 chanpos = pri_find_principle(pri, e->ringing.channel);
b684b13b 8337@@ -8624,7 +9475,7 @@
5e69ef1a
MT
8338 } else {
8339 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8340 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
8341- zt_enable_ec(pri->pvts[chanpos]);
8342+ // XXX zt_enable_ec(pri->pvts[chanpos]);
8343 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
8344 pri->pvts[chanpos]->alerting = 1;
8345 } else
b684b13b 8346@@ -8653,9 +9504,15 @@
5e69ef1a
MT
8347 }
8348 break;
8349 case PRI_EVENT_PROGRESS:
8350- /* Get chan value if e->e is not PRI_EVNT_RINGING */
8351+ /* Get chan value if e->e is not PRI_EVENT_RINGING */
8352 chanpos = pri_find_principle(pri, e->proceeding.channel);
8353 if (chanpos > -1) {
8354+ if ((pri->pvts[chanpos]->priindication_oob == 2) && (e->proceeding.cause == PRI_CAUSE_USER_BUSY)) {
8355+ /* received PROGRESS with cause BUSY, no inband callprogress wanted => hang up! */
8356+ if (pri->pvts[chanpos]->owner) {
8357+ pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8358+ }
8359+ } else {
8360 #ifdef PRI_PROGRESS_MASK
8361 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
8362 #else
b684b13b 8363@@ -8702,6 +9559,12 @@
5e69ef1a
MT
8364 case PRI_EVENT_PROCEEDING:
8365 chanpos = pri_find_principle(pri, e->proceeding.channel);
8366 if (chanpos > -1) {
8367+ chanpos = pri_fixup_principle(pri, chanpos, e->proceeding.call);
8368+ if (chanpos < 0) {
8369+ ast_log(LOG_WARNING, "Received PROCEEDING on channel %d/%d not in use on span %d\n",
8370+ PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), pri->span);
8371+ chanpos = -1;
8372+ } else {
8373 if (!pri->pvts[chanpos]->proceeding) {
8374 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
8375
b684b13b 8376@@ -8752,6 +9615,295 @@
5e69ef1a
MT
8377 }
8378 }
8379 break;
8380+ case PRI_EVENT_SUSPEND_REQ:
8381+ if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
8382+ pri_suspend_reject(pri->pri, e->suspend_req.call, "");
8383+ break;
8384+ }
8385+ chanpos = pri_find_principle(pri, e->suspend_req.channel);
8386+ if (chanpos < 0) {
8387+ ast_log(LOG_WARNING, "Suspend requested on unconfigured channel %d span %d\n", chanpos, pri->span);
8388+ chanpos = -1;
8389+ }
8390+
8391+ if (chanpos > -1) {
8392+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
8393+ if (pri->pvts[chanpos]->owner) {
8394+ if (ast_bridged_channel(pri->pvts[chanpos]->owner)) {
8395+ struct zt_suspended_call *zpc;
8396+ char tmpstr[256];
8397+ zpc = malloc(sizeof(struct zt_suspended_call));
8398+ if (!zpc) {
8399+ ast_log(LOG_ERROR, "unable to malloc zt_suspended_call\n");
8400+ break;
8401+ }
8402+ strncpy(zpc->msn, pri->pvts[chanpos]->cid_num, sizeof(zpc->msn));
8403+ strncpy(zpc->callid, e->suspend_req.callid, sizeof(zpc->callid));
8404+ ast_masq_park_call(ast_bridged_channel(pri->pvts[chanpos]->owner), NULL, 0, &zpc->parked_at);
8405+ zpc->next = pri->suspended_calls;
8406+ pri->suspended_calls = zpc;
8407+ snprintf(tmpstr, sizeof(tmpstr), "Parked at %d", zpc->parked_at);
8408+ pri_suspend_acknowledge(pri->pri, e->suspend_req.call,tmpstr);
8409+ pri->pvts[chanpos]->call = NULL;
8410+ pri->pvts[chanpos]->tei = -1;
8411+ pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8412+ } else {
8413+ pri_suspend_reject(pri->pri, e->suspend_req.call, "cant park a non-bridge");
8414+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8415+ break;
8416+ }
8417+ } else {
8418+ pri_suspend_reject(pri->pri, e->suspend_req.call, "");
8419+ }
8420+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8421+ }
8422+ break;
8423+ case PRI_EVENT_RESUME_REQ:
8424+ if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
8425+ break;
8426+ }
8427+ chanpos = pri_find_empty_chan(pri, 1);
8428+ if (chanpos < 0) {
8429+ pri_resume_reject(pri->pri, e->resume_req.call,"All channels busy");
8430+ ast_log(LOG_WARNING, "Resume requested on odd channel number %d span %d\n", chanpos, pri->span);
8431+ chanpos = -1;
8432+ } else if (!pri->pvts[chanpos]) {
8433+ pri_resume_reject(pri->pri, e->resume_req.call,"General protection fault in module 0x0BRI");
8434+ chanpos = -1;
8435+ }
8436+
8437+ if (chanpos > -1) {
8438+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
8439+ if (!pri->pvts[chanpos]->owner) {
8440+ struct zt_suspended_call *zpc, *zpcl;
8441+ int unparked=0;
8442+ char extenstr[255], temp[255];
8443+ zpc = NULL;
8444+ zpcl = pri->suspended_calls;
8445+ while (zpcl) {
8446+ // ast_log(LOG_NOTICE, "zpc->parked_at %d zpcl->callid %s\n",zpcl->parked_at, zpcl->callid);
8447+ if (((strlen(zpcl->callid) == 0) && (strlen(e->resume_req.callid)==0)) || (!strcmp(zpcl->callid,e->resume_req.callid))) {
8448+ int law;
8449+ // found a parked call
8450+ snprintf(extenstr, sizeof(extenstr), "%d", zpcl->parked_at);
8451+ strncpy(pri->pvts[chanpos]->exten, extenstr, sizeof(pri->pvts[chanpos]->exten));
8452+ // strncpy(pri->pvts[chanpos]->context, ast_parking_con(), sizeof(pri->pvts[chanpos]->context));
8453+ pri->pvts[chanpos]->call = e->resume_req.call;
8454+ law = 1;
8455+ if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
8456+ ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]), law);
8457+ // uhh ohh...what shall we do without the bearer cap???
8458+ law = ZT_LAW_ALAW;
8459+ res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
8460+ if (res < 0)
8461+ ast_log(LOG_WARNING, "Unable to set law on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
8462+ if (!pri->pvts[chanpos]->digital) {
8463+ res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
8464+ } else {
8465+ res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[chanpos]->law);
8466+ }
8467+ if (res < 0)
8468+ ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
8469+ /* Start PBX */
8470+ c = zt_new(pri->pvts[chanpos], AST_STATE_UP, 1, SUB_REAL, law, PRI_TRANS_CAP_SPEECH);
8471+ if (c) {
8472+ pri->pvts[chanpos]->owner = c;
8473+ pri->pvts[chanpos]->call = e->resume_req.call;
8474+ zt_enable_ec(pri->pvts[chanpos]);
8475+ zt_train_ec(pri->pvts[chanpos]);
8476+ } else {
8477+ ast_log(LOG_ERROR, "unable to start pbx\n");
8478+ }
8479+
8480+ if (zpc) {
8481+ zpc->next = zpcl->next;
8482+ free(zpcl);
8483+ zpcl = zpc->next;
8484+ } else {
8485+ // remove head
8486+ pri->suspended_calls = zpcl->next;
8487+ free(zpcl);
8488+ zpcl = pri->suspended_calls;
8489+ zpc = NULL;
8490+ }
8491+ unparked = 1;
8492+ snprintf(temp, sizeof(temp), "Unparked %s", extenstr);
8493+ pri_resume_acknowledge(pri->pri, e->resume_req.call, chanpos + 1, temp);
8494+ break;
8495+ }
8496+ zpc = zpcl;
8497+ if (zpcl) zpcl = zpcl->next;
8498+ }
8499+ if (!unparked)
8500+ pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
8501+ } else {
8502+ pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
8503+ }
8504+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8505+ }
8506+ break;
8507+ case PRI_EVENT_HOLD_REQ:
8508+ if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
8509+ pri_hold_reject(pri->pri, e->hold_req.call);
8510+ break;
8511+ }
8512+ chanpos = pri_find_principle(pri, e->hold_req.channel);
8513+ if (chanpos < 0) {
8514+ ast_log(LOG_WARNING, "Hold requested on unconfigured channel %d span %d\n", chanpos, pri->span);
8515+ chanpos = -1;
8516+ }
8517+ if (chanpos > -1) {
8518+ // ast_log(LOG_NOTICE, "Hold request for channel number %d span %d\n", chanpos, pri->span);
8519+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
8520+ if (pri->pvts[chanpos]->owner) {
8521+ struct zt_pvt *p = pri->pvts[chanpos];
8522+ struct zt_holded_call *zhc;
8523+ int holdacked=0;
8524+
8525+// ast_log(LOG_NOTICE,"HOLD request from channel %s tei %d\n",p->owner->name, e->hold_req.tei);
8526+ if (ast_bridged_channel(p->owner)) {
8527+ zhc = malloc(sizeof(struct zt_holded_call));
8528+ if (!zhc) {
8529+ ast_log(LOG_ERROR, "unable to malloc zt_holded_call\n");
8530+ break;
8531+ }
8532+ memset(zhc, 0, sizeof(zhc));
8533+ strncpy(zhc->msn, pri->pvts[chanpos]->cid_num, sizeof(zhc->msn));
8534+ strncpy(zhc->uniqueid, ast_bridged_channel(p->owner)->uniqueid, sizeof(zhc->uniqueid));
8535+ zhc->tei = e->hold_req.tei;
8536+ zhc->cref = e->hold_req.cref;
8537+ zhc->call = e->hold_req.call;
8538+ zhc->channel = p->owner;
8539+ zhc->alreadyhungup = 0;
8540+ zhc->bridge = ast_bridged_channel(p->owner);
8541+ zhc->next = pri->holded_calls;
8542+ pri->holded_calls = zhc;
8543+
8544+ /* put channel on hold */
8545+ ast_masq_hold_call(ast_bridged_channel(p->owner), p->owner);
8546+
8547+ pri_hold_acknowledge(pri->pri, e->hold_req.call);
8548+ holdacked = 1;
8549+ p->call = NULL; // free the bchannel withouth destroying the call
8550+ p->tei = -1;
8551+ } else {
8552+ // cant hold a non-bridge,...yet
8553+
8554+ // make a fake channel
8555+
8556+ // masquerade
8557+
8558+ // put on hold
8559+ pri_hold_reject(pri->pri, e->hold_req.call);
8560+ }
8561+ } else {
8562+ pri_hold_reject(pri->pri, e->hold_req.call);
8563+ }
8564+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8565+ } else {
8566+ pri_hold_reject(pri->pri, e->hold_req.call);
8567+ }
8568+ break;
8569+ case PRI_EVENT_RETRIEVE_REQ:
8570+ if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
8571+ pri_retrieve_reject(pri->pri, e->retrieve_req.call);
8572+ break;
8573+ }
8574+ chanpos = pri_find_empty_chan(pri, 1);
8575+ if (chanpos < 0) {
8576+ pri_retrieve_reject(pri->pri, e->retrieve_req.call);
8577+ ast_log(LOG_WARNING, "Retrieve requested on odd channel number %d span %d\n", chanpos, pri->span);
8578+ chanpos = -1;
8579+ break;
8580+ } else if (!pri->pvts[chanpos]) {
8581+ ast_log(LOG_WARNING, "Retrieve requested on unconfigured channel number %d span %d\n", chanpos, pri->span);
8582+ pri_retrieve_reject(pri->pri, e->retrieve_req.call);
8583+ chanpos = -1;
8584+ break;
8585+ }
8586+ if (chanpos > -1) {
8587+ struct zt_holded_call *onhold = NULL;
8588+ int retrieved = 0;
8589+ int res = -1;
8590+ struct app_tmp *tmp;
8591+ pthread_attr_t attr;
8592+ int law;
8593+
8594+ onhold = pri_get_callonhold(pri, e->retrieve_req.cref, e->retrieve_req.tei);
8595+
8596+ if (!onhold) {
8597+ pri_retrieve_reject(pri->pri, e->retrieve_req.call);
8598+ break;
8599+ }
8600+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
8601+ // found a parked call
8602+ law = 1;
8603+ if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
8604+ ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]), law);
8605+ // uhh ohh...what shall we do without the bearer cap???
8606+ law = ZT_LAW_ALAW;
8607+ res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
8608+ if (res < 0)
8609+ ast_log(LOG_WARNING, "Unable to set law on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
8610+ res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
8611+ if (res < 0)
8612+ ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
8613+ /* Start PBX */
8614+ c = zt_new(pri->pvts[chanpos], AST_STATE_UP, 0, SUB_REAL, law, PRI_TRANS_CAP_SPEECH);
8615+ if (c) {
8616+ pri->pvts[chanpos]->owner = c;
8617+ pri->pvts[chanpos]->outgoing = 1; /* for not sending proceedings... */
8618+ pri->pvts[chanpos]->call = e->retrieve_req.call;
8619+ pri->pvts[chanpos]->tei = e->retrieve_req.tei;
8620+ zt_enable_ec(pri->pvts[chanpos]);
8621+ zt_train_ec(pri->pvts[chanpos]);
8622+ } else {
8623+ ast_log(LOG_ERROR, "unable to start pbx\n");
8624+ }
8625+
8626+ retrieved = 1;
8627+ // ast_log(LOG_NOTICE, "sending RETRIEVE ACK on channel %d, span %d for tei %d cref %d\n",chanpos,pri->span, e->retrieve_req.tei, e->retrieve_req.cref);
8628+ pri_retrieve_acknowledge(pri->pri, e->retrieve_req.call, chanpos + 1);
8629+
8630+ // the magic begins here: ....
8631+ tmp = malloc(sizeof(struct app_tmp));
8632+ if (tmp) {
8633+ memset(tmp, 0, sizeof(struct app_tmp));
8634+ strncpy(tmp->app, "holdedcall", sizeof(tmp->app) - 1);
8635+ strncpy(tmp->data, onhold->uniqueid, sizeof(tmp->data) - 1);
8636+ tmp->chan = c;
8637+ }
8638+ pri_destroy_callonhold(pri, onhold);
8639+ onhold = NULL;
8640+
8641+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8642+ pthread_attr_init(&attr);
8643+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
8644+ if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
8645+ ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", c->name, strerror(errno));
8646+ free(tmp);
8647+ ast_hangup(c);
8648+ retrieved = 0;
8649+ }
8650+
8651+ if (!retrieved) {
8652+ pri_retrieve_reject(pri->pri, e->retrieve_req.call);
8653+ }
8654+ }
8655+ break;
8656+ case PRI_EVENT_DISPLAY_RECEIVED:
8657+ ast_log(LOG_NOTICE, "DISPLAY IE: [ %s ] received\n",e->display.text);
8658+ chanpos = pri_find_principle(pri, e->display.channel);
8659+ if (chanpos < 0) {
8660+ ast_log(LOG_WARNING, "odd channel number %d span %d\n", chanpos, pri->span);
8661+ chanpos = -1;
8662+ }
8663+ if (chanpos > -1) {
8664+ if (pri->pvts[chanpos]->owner) {
8665+ // ast_sendtext(pri->pvt[chanpos]->owner, e->display.text);
8666+ }
8667+ }
8668+ break;
8669 case PRI_EVENT_ANSWER:
8670 chanpos = pri_find_principle(pri, e->answer.channel);
8671 if (chanpos < 0) {
b684b13b 8672@@ -8767,6 +9919,7 @@
5e69ef1a
MT
8673 chanpos = -1;
8674 } else {
8675 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8676+ pri->pvts[chanpos]->tei = e->answer.tei;
8677 /* Now we can do call progress detection */
8678
8679 /* We changed this so it turns on the DSP no matter what... progress or no progress.
b684b13b 8680@@ -8796,11 +9949,16 @@
5e69ef1a
MT
8681 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
8682 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
8683 } else if (pri->pvts[chanpos]->confirmanswer) {
8684- ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
8685+ ast_log(LOG_DEBUG, "Waiting for answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
b684b13b 8686+ enable_dtmf_detect(pri->pvts[chanpos]);
5e69ef1a
MT
8687 } else {
8688+ pri->pvts[chanpos]->dialing = 0;
8689 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
8690 /* Enable echo cancellation if it's not on already */
8691 zt_enable_ec(pri->pvts[chanpos]);
8692+ zt_train_ec(pri->pvts[chanpos]);
8693+ /* stop ignoring inband dtmf */
8694+ enable_dtmf_detect(pri->pvts[chanpos]);
8695 }
8696
8697 #ifdef SUPPORT_USERUSER
b684b13b 8698@@ -8849,23 +10007,32 @@
5e69ef1a
MT
8699 }
8700 }
8701 if (option_verbose > 2)
8702- ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup\n",
8703- pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8704+ ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
8705+ pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
8706 } else {
5f892677
MT
8707- pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
8708+ pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
5e69ef1a
MT
8709 pri->pvts[chanpos]->call = NULL;
8710+ pri->pvts[chanpos]->tei = -1;
8711 }
8712 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
8713- if (option_verbose > 2)
8714+ if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
8715+ if (option_verbose > 2)
8716 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
8717 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
8718- pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
8719- pri->pvts[chanpos]->resetting = 1;
8720+ pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
8721+ pri->pvts[chanpos]->resetting = 1;
8722+ }
8723 }
5f892677
MT
8724- if (e->hangup.aoc_units > -1)
8725+ if (e->hangup.aoc_units > -1) {
8726+ if (pri->pvts[chanpos]->owner) {
8727+ char tmpstr[256];
8728+ snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
8729+ pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
8730+ }
5e69ef1a 8731 if (option_verbose > 2)
5f892677
MT
8732 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
8733 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
8734+ }
8735
8736 #ifdef SUPPORT_USERUSER
8737 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
b684b13b 8738@@ -8875,8 +10042,20 @@
5e69ef1a
MT
8739
8740 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8741 } else {
8742- ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
8743- PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
8744+ struct zt_holded_call *onhold = NULL;
8745+ /* check calls on hold */
8746+ onhold = pri_get_callonhold(pri, e->hangup.cref, e->hangup.tei);
8747+
8748+ if (onhold) {
8749+ // ast_log(LOG_NOTICE, "hangup, found cref %d, tei %d\n",e->hangup.cref, e->hangup.tei);
5f892677 8750+ pri_hangup(pri->pri, onhold->call, e->hangup.cause, -1);
5e69ef1a
MT
8751+ pri_destroy_callonhold(pri, onhold);
8752+ onhold = NULL;
8753+ } else {
8754+ ast_log(LOG_NOTICE, "Hangup, did not find cref %d, tei %d\n",e->hangup.cref, e->hangup.tei);
8755+ ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
8756+ PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
8757+ }
8758 }
8759 }
8760 break;
b684b13b 8761@@ -8886,17 +10065,25 @@
5e69ef1a
MT
8762 case PRI_EVENT_HANGUP_REQ:
8763 chanpos = pri_find_principle(pri, e->hangup.channel);
8764 if (chanpos < 0) {
8765- ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
8766- PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
8767+ if (pri->nodetype == BRI_NETWORK_PTMP) {
5f892677 8768+ pri_hangup(pri->pri, e->hangup.call, e->hangup.cause, -1);
5e69ef1a
MT
8769+ } else {
8770+ ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
8771+ PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
8772+ }
8773 chanpos = -1;
8774 }
8775- if (chanpos > -1) {
8776+ /* dont hang up if we want to hear inband call progress */
8777+ if ((chanpos > -1) && ((pri->pvts[chanpos]->priindication_oob != 2) || (!e->hangup.inband_progress) || (!pri->pvts[chanpos]->outgoing))){
8778 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
8779 if (chanpos > -1) {
8780 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8781 if (pri->pvts[chanpos]->realcall)
8782 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8783 else if (pri->pvts[chanpos]->owner) {
8784+ char tmpstr[256];
8785+ snprintf(tmpstr, sizeof(tmpstr), "%d", e->hangup.cause);
8786+ pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "PRI_CAUSE", tmpstr);
8787 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
8788 switch(e->hangup.cause) {
8789 case PRI_CAUSE_USER_BUSY:
b684b13b 8790@@ -8915,20 +10102,87 @@
5f892677
MT
8791 }
8792 if (option_verbose > 2)
8793 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup request\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
8794- if (e->hangup.aoc_units > -1)
8795- if (option_verbose > 2)
8796- ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
8797- pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
8798+ if (e->hangup.aoc_units > -1) {
8799+ if (pri->pvts[chanpos]->owner) {
8800+ char tmpstr[256];
8801+ snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
8802+ pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
8803+ }
8804+ if (option_verbose > 2)
8805+ ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
8806+ pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
8807+ }
5e69ef1a
MT
8808+ if (pri->nodetype == BRI_NETWORK_PTMP) {
8809+ // check for bri transfers, not everybody uses ECT...
8810+ if (pri->pvts[chanpos]->owner) {
8811+ // find on hold call
8812+ struct zt_holded_call *onhold = NULL;
8813+ struct ast_channel *transferee = NULL;
8814+ int transfer_ok = 0;
8815+
8816+ onhold = pri_get_callonhold(pri, -1, e->hangup.tei);
8817+
8818+ if (onhold) {
8819+ if (pri->pvts[chanpos]->pritransfer == 2) {
8820+ if (((pri->pvts[chanpos]->owner->_state != AST_STATE_RING) && (pri->pvts[chanpos]->owner->_state != AST_STATE_RESERVED)) || ((!ast_strlen_zero(pri->pvts[chanpos]->exten)) && (strncasecmp(pri->pvts[chanpos]->exten, "s", sizeof(pri->pvts[chanpos]->exten))))) {
8821+ transferee = ast_get_holded_call(onhold->uniqueid);
8822+
8823+ if (transferee) {
8824+ if (pri->pvts[chanpos]->owner->_state == AST_STATE_RINGING) {
8825+ ast_indicate(transferee, AST_CONTROL_RINGING);
8826+ }
8827+
8828+ pri->pvts[chanpos]->owner->_softhangup &= ~AST_SOFTHANGUP_DEV;
8829+
8830+ ast_mutex_unlock(&transferee->lock);
8831+ if (ast_channel_masquerade(pri->pvts[chanpos]->owner, transferee)) {
8832+ ast_log(LOG_WARNING, "unable to masquerade\n");
8833+ } else {
8834+ /* beware of zombies!!! */
8835+ ast_set_flag(transferee, AST_FLAG_ZOMBIE);
8836+ pri->pvts[chanpos]->owner = NULL;
8837+ pri->pvts[chanpos]->tei = -1;
8838+ transfer_ok = 1;
8839+ }
8840+ }
8841+ }
8842+ } else if (pri->pvts[chanpos]->pritransfer == 0) {
8843+ ast_log(LOG_NOTICE, "killing channel %s \n", onhold->uniqueid);
8844+ ast_retrieve_call_to_death(onhold->uniqueid);
8845+ transfer_ok = 1;
8846+ } else if (pri->pvts[chanpos]->pritransfer == 1) {
8847+ /* we use ECT transfers, so just ignore this */
8848+ transfer_ok = 0;
8849+ }
8850+
8851+ if (transfer_ok) {
8852+ onhold->alreadyhungup = 1;
5f892677 8853+ pri_hangup(pri->pri, onhold->call, e->hangup.cause, -1);
5e69ef1a
MT
8854+ onhold = NULL;
8855+ }
8856+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8857+ break;
5f892677
MT
8858+ } else {
8859+ pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
8860+ pri->pvts[chanpos]->call = NULL;
8861+ pri->pvts[chanpos]->tei = -1;
8862+ }
5e69ef1a
MT
8863+ }
8864+ }
8865 } else {
5f892677
MT
8866- pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
8867+ pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
5e69ef1a
MT
8868 pri->pvts[chanpos]->call = NULL;
8869+ pri->pvts[chanpos]->tei = -1;
8870 }
8871 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
8872- if (option_verbose > 2)
8873- ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
8874- PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
8875- pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
8876- pri->pvts[chanpos]->resetting = 1;
8877+ if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
8878+ if (option_verbose > 2)
8879+ ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
8880+ PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
8881+ pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
8882+ pri->pvts[chanpos]->resetting = 1;
8883+ }
8884+
8885 }
8886
8887 #ifdef SUPPORT_USERUSER
b684b13b 8888@@ -8939,9 +10193,36 @@
5e69ef1a
MT
8889
8890 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8891 } else {
8892- 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);
8893+ if (pri->nodetype != BRI_NETWORK_PTMP) {
8894+ 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);
8895+ } else {
8896+ // check holded_calls!!!
8897+ struct zt_holded_call *onhold = NULL;
8898+
8899+ onhold = pri_get_callonhold(pri, e->hangup.cref, e->hangup.tei);
8900+
8901+ if (onhold) {
5f892677 8902+ pri_hangup(pri->pri, e->hangup.call, e->hangup.cause, -1);
5e69ef1a
MT
8903+ ast_retrieve_call_to_death(onhold->uniqueid);
8904+ pri_destroy_callonhold(pri, onhold);
8905+ onhold = NULL;
8906+ } else {
8907+ 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);
8908+ }
8909+ }
8910 }
8911 }
8912+ if ((chanpos > -1) && (pri->pvts[chanpos]->owner) && (pri->pvts[chanpos]->priindication_oob == 2) && (e->hangup.inband_progress) && (pri->pvts[chanpos]->outgoing)) {
5f892677
MT
8913+ if (e->hangup.aoc_units > -1) {
8914+ char tmpstr[256];
8915+ snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
8916+ pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
8917+ if (option_verbose > 2)
8918+ ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
8919+ pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
8920+ }
5e69ef1a
MT
8921+ ast_channel_setwhentohangup(pri->pvts[chanpos]->owner, 5);
8922+ }
8923 break;
8924 case PRI_EVENT_HANGUP_ACK:
8925 chanpos = pri_find_principle(pri, e->hangup.channel);
b684b13b 8926@@ -8955,6 +10236,7 @@
5e69ef1a
MT
8927 if (chanpos > -1) {
8928 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8929 pri->pvts[chanpos]->call = NULL;
8930+ pri->pvts[chanpos]->tei = -1;
8931 pri->pvts[chanpos]->resetting = 0;
8932 if (pri->pvts[chanpos]->owner) {
8933 if (option_verbose > 2)
b684b13b 8934@@ -8968,7 +10250,9 @@
5e69ef1a
MT
8935 #endif
8936
8937 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8938+ }
8939 }
8940+ }
8941 }
8942 break;
8943 case PRI_EVENT_CONFIG_ERR:
b684b13b 8944@@ -9060,10 +10344,22 @@
5f892677
MT
8945 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8946 switch(e->notify.info) {
8947 case PRI_NOTIFY_REMOTE_HOLD:
8948+ if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
8949+ ast_log(LOG_DEBUG, "Received REMOTE_HOLD notification on NETWORK channel. Starting MoH\n");
8950+ ast_moh_start(ast_bridged_channel(pri->pvts[chanpos]->owner), NULL);
8951+ } else {
8952+ ast_log(LOG_DEBUG, "Received REMOTE_HOLD notification on CPE channel. Not Starting MoH\n");
8953+ }
8954 f.subclass = AST_CONTROL_HOLD;
8955 zap_queue_frame(pri->pvts[chanpos], &f, pri);
8956 break;
8957 case PRI_NOTIFY_REMOTE_RETRIEVAL:
8958+ if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
8959+ ast_log(LOG_DEBUG, "Received REMOTE_RETRIEVAL notification on NETWORK channel. Stopping MoH\n");
8960+ ast_moh_stop(ast_bridged_channel(pri->pvts[chanpos]->owner));
8961+ } else {
8962+ ast_log(LOG_DEBUG, "Received REMOTE_RETRIEVAL notification on CPE channel.\n");
8963+ }
8964 f.subclass = AST_CONTROL_UNHOLD;
8965 zap_queue_frame(pri->pvts[chanpos], &f, pri);
8966 break;
b684b13b 8967@@ -9071,6 +10367,77 @@
5e69ef1a
MT
8968 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8969 }
8970 break;
8971+ case PRI_EVENT_FACILITY:
8972+ if (e->facility.operation == 0x06) {
8973+ struct ast_channel *chan = NULL;
8974+ struct zt_holded_call *onhold = NULL;
8975+ if (option_verbose > 2) {
8976+ ast_verbose(VERBOSE_PREFIX_3 "ECT requested by TEI %d for cref %d\n", e->facility.tei, e->facility.cref);
8977+ }
8978+ /* search for cref/tei in held calls */
8979+ onhold = pri_get_callonhold(pri, e->facility.cref, e->facility.tei);
8980+ if (onhold) {
8981+ chan = ast_get_holded_call(onhold->uniqueid);
8982+ onhold->alreadyhungup = 1;
8983+ onhold = NULL;
8984+ if (!chan) {
8985+ /* hang up */
5f892677 8986+ pri_hangup(pri->pri, e->facility.call, 16, -1);
5e69ef1a
MT
8987+ break;
8988+ }
8989+ } else {
8990+ /* unknown cref/tei */
8991+ ast_log(LOG_WARNING, "did not find call on hold for cref %d tei %d\n", e->facility.tei, e->facility.cref);
8992+ /* hang up */
5f892677 8993+ pri_hangup(pri->pri, e->facility.call, 16, -1);
5e69ef1a
MT
8994+ break;
8995+ }
8996+
8997+ /* find an active call for the same tei */
8998+ chanpos = pri_find_tei(pri, e->facility.call, e->facility.tei);
8999+ if (chanpos < 0) {
9000+ /* did not find active call, hangup call on hold */
9001+ if (chan) {
9002+ ast_hangup(chan);
9003+ chan = NULL;
9004+ }
9005+ } else {
9006+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
9007+ /* transfer */
9008+ if (pri->pvts[chanpos]->owner) {
9009+ if (option_verbose > 3) {
9010+ ast_verbose(VERBOSE_PREFIX_3 "ECT: found %s on channel %d for tei %d\n", pri->pvts[chanpos]->owner->name ,chanpos, e->facility.tei);
9011+ }
9012+ /* pass callprogress if the channel is not up yet */
9013+ if (pri->pvts[chanpos]->owner->_state == AST_STATE_RINGING) {
9014+ ast_indicate(chan, AST_CONTROL_RINGING);
9015+ }
9016+ /* unlock the channel we removed from hold */
9017+ ast_mutex_unlock(&chan->lock);
9018+ if (ast_channel_masquerade(pri->pvts[chanpos]->owner, chan)) {
9019+ ast_log(LOG_WARNING, "unable to masquerade\n");
9020+ } else {
9021+ /* beware of zombies !!! */
9022+ ast_set_flag(chan, AST_FLAG_ZOMBIE);
9023+ // chan->zombie = 1;
9024+ }
9025+ }
9026+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9027+ }
9028+ /* disconnect */
5f892677 9029+ pri_hangup(pri->pri, e->facility.call, 16, -1);
5e69ef1a
MT
9030+ } else if (e->facility.operation == 0x0D) {
9031+ ast_log(LOG_NOTICE, "call deflection to %s requested.\n", e->facility.forwardnum);
5f892677
MT
9032+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
9033+ /* transfer */
9034+ if (pri->pvts[chanpos]->owner) {
9035+ snprintf(pri->pvts[chanpos]->owner->call_forward, sizeof(pri->pvts[chanpos]->owner->call_forward), "Local/%s@%s", e->facility.forwardnum, pri->pvts[chanpos]->owner->context);
9036+ }
9037+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
5e69ef1a
MT
9038+ } else {
9039+ ast_log(LOG_WARNING, "Unknown facility operation %#x requested.\n", e->facility.operation);
9040+ }
9041+ break;
9042 default:
9043 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
9044 }
b684b13b 9045@@ -9132,7 +10499,7 @@
5e69ef1a
MT
9046 pri->fds[i] = -1;
9047 return -1;
9048 }
9049- pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
9050+ pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype, pri->span);
9051 /* Force overlap dial if we're doing GR-303! */
9052 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
9053 pri->overlapdial = 1;
b684b13b 9054@@ -9201,39 +10568,77 @@
5e69ef1a
MT
9055
9056 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
9057 {
9058- int myfd;
9059+ int myfd, x, d;
9060+ int span;
9061+
9062+ if (argc < 6)
9063+ return RESULT_SHOWUSAGE;
9064
9065 if (!strncasecmp(argv[1], "set", 3)) {
9066- if (argc < 5)
9067+ if (argc < 7)
9068 return RESULT_SHOWUSAGE;
9069
9070- if (ast_strlen_zero(argv[4]))
9071+ if (!argv[4] || ast_strlen_zero(argv[4]))
9072 return RESULT_SHOWUSAGE;
9073
9074+ if (!argv[5])
9075+ return RESULT_SHOWUSAGE;
9076+
9077+ if (!argv[6] || ast_strlen_zero(argv[6]))
9078+ return RESULT_SHOWUSAGE;
9079+
9080+ span = atoi(argv[6]);
9081+ if ((span < 1) && (span > NUM_SPANS)) {
9082+ return RESULT_SUCCESS;
9083+ }
9084+
9085+
9086 myfd = open(argv[4], O_CREAT|O_WRONLY);
9087 if (myfd < 0) {
9088- ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
9089- return RESULT_SUCCESS;
9090+ ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
9091+ return RESULT_SUCCESS;
9092 }
9093-
9094- ast_mutex_lock(&pridebugfdlock);
9095-
9096- if (pridebugfd >= 0)
9097- close(pridebugfd);
9098-
9099- pridebugfd = myfd;
9100- ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
9101-
9102- ast_mutex_unlock(&pridebugfdlock);
9103-
9104- ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
9105+ for (x=0; x < NUM_SPANS; x++) {
9106+ ast_mutex_lock(&pris[x].lock);
9107+
9108+ if (pris[x].span == span) {
9109+ if (pris[x].debugfd >= 0)
9110+ close(pris[x].debugfd);
9111+ pris[x].debugfd = myfd;
9112+ for (d=0; d < NUM_DCHANS; d++) {
9113+ if (pris[x].dchans[d])
9114+ pri_set_debug_fd(pris[x].dchans[d], myfd);
9115+ }
9116+ }
9117+ ast_mutex_unlock(&pris[x].lock);
9118+ }
9119+
9120+ ast_cli(fd, "PRI debug output for span %d will be sent to '%s'\n", span, argv[4]);
9121 } else {
9122+ if (!argv[5] || ast_strlen_zero(argv[5]))
9123+ return RESULT_SHOWUSAGE;
9124 /* Assume it is unset */
9125- ast_mutex_lock(&pridebugfdlock);
9126- close(pridebugfd);
9127- pridebugfd = -1;
9128- ast_cli(fd, "PRI debug output to file disabled\n");
9129- ast_mutex_unlock(&pridebugfdlock);
9130+ span = atoi(argv[5]);
9131+ if ((span < 1) && (span > NUM_SPANS)) {
9132+ return RESULT_SUCCESS;
9133+ }
9134+
9135+ for (x=0; x < NUM_SPANS; x++) {
9136+ ast_mutex_lock(&pris[x].lock);
9137+
9138+ if (pris[x].span == span) {
9139+ if (pris[x].debugfd >= 0)
9140+ close(pris[x].debugfd);
9141+ pris[x].debugfd = -1;
9142+ for (d=0; d < NUM_DCHANS; d++) {
9143+ if (pris[x].dchans[d])
9144+ pri_set_debug_fd(pris[x].dchans[d], -1);
9145+ }
9146+ }
9147+ ast_mutex_unlock(&pris[x].lock);
9148+ }
9149+
9150+ ast_cli(fd, "PRI debug output to file for span %d disabled\n", span);
9151 }
9152
9153 return RESULT_SUCCESS;
b684b13b 9154@@ -9265,6 +10670,7 @@
5e69ef1a
MT
9155
9156
9157
9158+
9159 static int handle_pri_no_debug(int fd, int argc, char *argv[])
9160 {
9161 int span;
b684b13b 9162@@ -9371,36 +10777,6 @@
5e69ef1a
MT
9163 return RESULT_SUCCESS;
9164 }
9165
9166-static int handle_pri_show_debug(int fd, int argc, char *argv[])
9167-{
9168- int x;
9169- int span;
9170- int count=0;
9171- int debug=0;
9172-
9173- for(span=0;span<NUM_SPANS;span++) {
9174- if (pris[span].pri) {
9175- for(x=0;x<NUM_DCHANS;x++) {
9176- debug=0;
9177- if (pris[span].dchans[x]) {
9178- debug = pri_get_debug(pris[span].dchans[x]);
9179- 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" );
9180- count++;
9181- }
9182- }
9183- }
9184-
9185- }
9186- ast_mutex_lock(&pridebugfdlock);
9187- if (pridebugfd >= 0)
9188- ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
9189- ast_mutex_unlock(&pridebugfdlock);
9190-
9191- if (!count)
9192- ast_cli(fd, "No debug set or no PRI running\n");
9193- return RESULT_SUCCESS;
9194-}
9195-
9196 static char pri_debug_help[] =
9197 "Usage: pri debug span <span>\n"
9198 " Enables debugging on a given PRI span\n";
b684b13b 9199@@ -9417,6 +10793,18 @@
5e69ef1a
MT
9200 "Usage: pri show span <span>\n"
9201 " Displays PRI Information\n";
9202
9203+static char bri_debug_help[] =
9204+ "Usage: bri debug span <span>\n"
9205+ " Enables debugging on a given BRI span\n";
9206+
9207+static char bri_no_debug_help[] =
9208+ "Usage: bri no debug span <span>\n"
9209+ " Disables debugging on a given BRI span\n";
9210+
9211+static char bri_really_debug_help[] =
9212+ "Usage: bri intensive debug span <span>\n"
9213+ " Enables debugging down to the Q.921 level\n";
9214+
9215 static struct ast_cli_entry zap_pri_cli[] = {
9216 { { "pri", "debug", "span", NULL }, handle_pri_debug,
9217 "Enables PRI debugging on a span", pri_debug_help, complete_span_4 },
b684b13b 9218@@ -9424,19 +10812,218 @@
5e69ef1a
MT
9219 "Disables PRI debugging on a span", pri_no_debug_help, complete_span_5 },
9220 { { "pri", "intense", "debug", "span", NULL }, handle_pri_really_debug,
9221 "Enables REALLY INTENSE PRI debugging", pri_really_debug_help, complete_span_5 },
9222+ { { "bri", "debug", "span", NULL }, handle_pri_debug,
9223+ "Enables BRI debugging on a span", bri_debug_help, complete_span_4 },
9224+ { { "bri", "no", "debug", "span", NULL }, handle_pri_no_debug,
9225+ "Disables BRI debugging on a span", bri_no_debug_help, complete_span_5 },
9226+ { { "bri", "intense", "debug", "span", NULL }, handle_pri_really_debug,
9227+ "Enables REALLY INTENSE BRI debugging", bri_really_debug_help, complete_span_5 },
9228 { { "pri", "show", "span", NULL }, handle_pri_show_span,
9229 "Displays PRI Information", pri_show_span_help, complete_span_4 },
9230- { { "pri", "show", "debug", NULL }, handle_pri_show_debug,
9231- "Displays current PRI debug settings" },
9232 { { "pri", "set", "debug", "file", NULL }, handle_pri_set_debug_file,
9233 "Sends PRI debug output to the specified file" },
9234- { { "pri", "unset", "debug", "file", NULL }, handle_pri_set_debug_file,
9235+ { { "pri", "unset", "debug", "file", "span", NULL }, handle_pri_set_debug_file,
9236 "Ends PRI debug output to file" },
9237 };
9238
b684b13b
MT
9239+static char *zapCD_tdesc = "Call Deflection";
9240+static char *zapCD_app = "zapCD";
9241+static char *zapCD_synopsis = "Call Deflection";
9242+
5e69ef1a
MT
9243+static int app_zapCD(struct ast_channel *chan, void *data)
9244+{
9245+ struct zt_pvt *p = chan->tech_pvt;
9246+
9247+ if(!data) {
9248+ ast_log(LOG_WARNING, "zapCD wants a number to deflect to\n");
9249+ return -1;
9250+ }
9251+ return pri_deflect(p->pri->pri, p->call, data);
9252+}
9253+
b684b13b
MT
9254+static char *zapInband_tdesc = "Inband Call Progress (pre-answer)";
9255+static char *zapInband_app = "zapInband";
9256+static char *zapInband_synopsis = "Inband Call Progress";
9257+
9258+static int app_zapInband(struct ast_channel *chan, void *data)
9259+{
9260+ struct zt_pvt *p = chan->tech_pvt;
9261+
9262+ return pri_acknowledge(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1);
9263+}
5e69ef1a
MT
9264 #endif /* ZAPATA_PRI */
9265
9266
5f892677
MT
9267+#ifdef ZAPATA_GSM
9268+
9269+static char gsm_send_pdu_help[] =
9270+ "Usage: gsm send pdu <channel> <length> <pdu>\n"
9271+ " Sends a PDU on a GSM channel\n";
9272+
9273+
9274+static int handle_gsm_send_pdu(int fd, int argc, char *argv[])
9275+{
9276+/* gsm send sms <channel> <destination> <message> */
9277+ int channel;
9278+ int len;
9279+ struct zt_pvt *pvt = NULL;
9280+ if (argc < 6) {
9281+ return RESULT_SHOWUSAGE;
9282+ }
9283+ channel = atoi(argv[3]);
9284+ if (channel < 1) {
9285+ ast_cli(fd, "Invalid channel %s. Should be a number.\n", argv[3]);
9286+ return RESULT_SUCCESS;
9287+ }
9288+ len = atoi(argv[4]);
9289+ if (len < 1) {
9290+ ast_cli(fd, "Invalid length %s. Should be a number.\n", argv[4]);
9291+ return RESULT_SUCCESS;
9292+ }
9293+ pvt = iflist;
9294+ while (pvt) {
9295+ if (pvt->channel == channel) {
9296+ if (pvt->owner) {
9297+ ast_cli(fd, "Channel in use.\n");
9298+ return RESULT_FAILURE;
9299+ } else {
9300+ ast_mutex_lock(&pvt->lock);
9301+ gsm_sms_send_pdu(pvt->gsm.modul, argv[5], len);
9302+ ast_mutex_unlock(&pvt->lock);
9303+ return RESULT_SUCCESS;
9304+ }
9305+ }
9306+ pvt = pvt->next;
9307+ }
9308+
9309+ return RESULT_SUCCESS;
9310+}
9311+
9312+static struct ast_cli_entry gsm_send_pdu = {
9313+ { "gsm", "send", "pdu", NULL }, handle_gsm_send_pdu, "Sends a SM on a GSM channel", gsm_send_pdu_help, complete_span_4 };
9314+
9315+
9316+static char gsm_send_sms_help[] =
9317+ "Usage: gsm send sms <channel> <destination> <message>\n"
9318+ " Sends a SM on a GSM channel\n";
9319+
9320+
9321+static int handle_gsm_send_sms(int fd, int argc, char *argv[])
9322+{
9323+/* gsm send sms <channel> <destination> <message> */
9324+ int channel;
9325+ struct zt_pvt *pvt = NULL;
9326+ if (argc < 6) {
9327+ return RESULT_SHOWUSAGE;
9328+ }
9329+ channel = atoi(argv[3]);
9330+ if (channel < 1) {
9331+ ast_cli(fd, "Invalid channel %s. Should be a number.\n", argv[3]);
9332+ return RESULT_SUCCESS;
9333+ }
9334+ pvt = iflist;
9335+ while (pvt) {
9336+ if (pvt->channel == channel) {
9337+ if (pvt->owner) {
9338+ ast_cli(fd, "Channel in use.\n");
9339+ return RESULT_FAILURE;
9340+ } else {
9341+ ast_mutex_lock(&pvt->lock);
9342+ gsm_sms_send_text(pvt->gsm.modul, argv[4], argv[5]);
9343+ ast_mutex_unlock(&pvt->lock);
9344+ return RESULT_SUCCESS;
9345+ }
9346+ }
9347+ pvt = pvt->next;
9348+ }
9349+
9350+ return RESULT_SUCCESS;
9351+}
9352+
9353+static struct ast_cli_entry gsm_send_sms = {
9354+ { "gsm", "send", "sms", NULL }, handle_gsm_send_sms, "Sends a SM on a GSM channel", gsm_send_sms_help, complete_span_4 };
9355+
9356+static char gsm_show_status_help[] =
9357+ "Usage: gsm show status <channel>>\n"
9358+ " Displays status information about the GSM channel.\n";
9359+
9360+
9361+static int handle_gsm_show_status(int fd, int argc, char *argv[])
9362+{
9363+ int channel;
9364+ struct zt_pvt *pvt = NULL;
9365+ if (argc < 4) {
9366+ return RESULT_SHOWUSAGE;
9367+ }
9368+ channel = atoi(argv[3]);
9369+ if (channel < 1) {
9370+ ast_cli(fd, "Invalid channel %s. Should be a number.\n", argv[3]);
9371+ return RESULT_SUCCESS;
9372+ }
9373+ pvt = iflist;
9374+ while (pvt) {
9375+ if (pvt->channel == channel) {
9376+ if (pvt->owner) {
9377+ ast_cli(fd, "Channel in use.\n");
9378+ return RESULT_FAILURE;
9379+ } else {
9380+ ast_mutex_lock(&pvt->lock);
9381+ gsm_request_status(pvt->gsm.modul);
9382+ ast_mutex_unlock(&pvt->lock);
9383+ return RESULT_SUCCESS;
9384+ }
9385+ }
9386+ pvt = pvt->next;
9387+ }
9388+
9389+ return RESULT_SUCCESS;
9390+}
9391+
9392+static struct ast_cli_entry gsm_show_status = {
9393+ { "gsm", "show", "status", NULL }, handle_gsm_show_status, "Displays status information about the GSM channel.", gsm_show_status_help, complete_span_4 };
9394+
9395+#endif /* ZAPATA_GSM */
9396+
5e69ef1a
MT
9397+static int app_zapEC(struct ast_channel *chan, void *data)
9398+{
9399+ int res=-1;
9400+ struct zt_pvt *p = NULL;
9401+
9402+ if (!data) {
9403+ ast_log(LOG_WARNING, "zapEC requires one argument (on | off)\n");
9404+ }
9405+ if (chan && !strcasecmp("ZAP",chan->type)) {
9406+ p = chan->tech_pvt;
9407+ if (!p) return res;
9408+ if (!strcasecmp("on",(char *)data)) {
9409+ zt_enable_ec(p);
9410+ res = 0;
9411+ if (option_verbose > 3) {
9412+ ast_verbose(VERBOSE_PREFIX_3 "Enabled echo cancelation on channel %s.\n", chan->name);
9413+ }
9414+ } else if (!strcasecmp("off",(char *)data)) {
9415+ zt_disable_ec(p);
9416+ res = 0;
9417+ if (option_verbose > 3) {
9418+ ast_verbose(VERBOSE_PREFIX_3 "Disabled echo cancelation on channel %s.\n", chan->name);
9419+ }
9420+ } else {
9421+ ast_log(LOG_WARNING, "Unknown argument %s to zapEC\n", (char *)data);
9422+ }
9423+ } else {
9424+ ast_log(LOG_WARNING, "zapNoEC only works on ZAP channels, check your extensions.conf!\n");
9425+ res = 0;
9426+ }
9427+
9428+ return res;
9429+}
9430+
9431+static char *zapEC_tdesc = "Enable/disable Echo cancelation";
9432+static char *zapEC_app = "zapEC";
9433+static char *zapEC_synopsis = "Enable/Disable Echo Cancelation on a Zap channel";
9434+
9435+
9436+
9437 #ifdef ZAPATA_R2
9438 static int handle_r2_no_debug(int fd, int argc, char *argv[])
9439 {
b684b13b
MT
9440@@ -10048,6 +11635,13 @@
9441 pthread_cancel(pris[i].master);
5f892677
MT
9442 }
9443 ast_cli_unregister_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(zap_pri_cli[0]));
b684b13b
MT
9444+ ast_unregister_application(zapCD_app);
9445+ ast_unregister_application(zapInband_app);
9446+#endif
5f892677
MT
9447+#ifdef ZAPATA_GSM
9448+ ast_cli_unregister(&gsm_send_sms);
9449+ ast_cli_unregister(&gsm_send_pdu);
9450+ ast_cli_unregister(&gsm_show_status);
b684b13b 9451 #endif
5f892677
MT
9452 #ifdef ZAPATA_R2
9453 ast_cli_unregister_multiple(zap_r2_cli, sizeof(zap_r2_cli) / sizeof(zap_r2_cli[0]));
b684b13b 9454@@ -10059,6 +11653,7 @@
5e69ef1a
MT
9455 ast_manager_unregister( "ZapDNDoff" );
9456 ast_manager_unregister( "ZapDNDon" );
9457 ast_manager_unregister("ZapShowChannels");
9458+ ast_unregister_application(zapEC_app);
9459 ast_channel_unregister(&zap_tech);
9460 if (!ast_mutex_lock(&iflock)) {
9461 /* Hangup all interfaces if they have an owner */
b684b13b 9462@@ -10417,8 +12012,8 @@
5e69ef1a
MT
9463 }
9464 } else if (!strcasecmp(v->name, "echotraining")) {
9465 if (sscanf(v->value, "%d", &y) == 1) {
9466- if ((y < 10) || (y > 4000)) {
9467- ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 2000 ms at line %d\n", v->lineno);
9468+ if ((y < 10) || (y > 1000)) {
9469+ ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 1000 ms at line %d\n", v->lineno);
9470 } else {
9471 echotraining = y;
9472 }
b684b13b 9473@@ -10604,12 +12199,33 @@
5e69ef1a
MT
9474 cur_signalling = SIG_GR303FXSKS;
9475 cur_radio = 0;
9476 pritype = PRI_CPE;
9477+ } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
9478+ cur_radio = 0;
9479+ cur_signalling = SIG_PRI;
9480+ pritype = BRI_NETWORK_PTMP;
9481+ } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
9482+ cur_signalling = SIG_PRI;
9483+ cur_radio = 0;
9484+ pritype = BRI_CPE_PTMP;
9485+ } else if (!strcasecmp(v->value, "bri_net")) {
9486+ cur_radio = 0;
9487+ cur_signalling = SIG_PRI;
9488+ pritype = BRI_NETWORK;
9489+ } else if (!strcasecmp(v->value, "bri_cpe")) {
9490+ cur_signalling = SIG_PRI;
9491+ cur_radio = 0;
9492+ pritype = BRI_CPE;
9493 #endif
9494 #ifdef ZAPATA_R2
9495 } else if (!strcasecmp(v->value, "r2")) {
5f892677
MT
9496 cur_signalling = SIG_R2;
9497 cur_radio = 0;
9498 #endif
9499+#ifdef ZAPATA_GSM
9500+ } else if (!strcasecmp(v->value, "gsm")) {
9501+ cur_signalling = SIG_GSM;
9502+ cur_radio = 0;
9503+#endif
9504 } else {
9505 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
9506 }
b684b13b 9507@@ -10692,8 +12308,20 @@
5e69ef1a
MT
9508 priindication_oob = 1;
9509 else if (!strcasecmp(v->value, "inband"))
9510 priindication_oob = 0;
9511+ else if (!strcasecmp(v->value, "passthrough"))
9512+ priindication_oob = 2;
9513 else
9514- ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
9515+ ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' , 'outofband' or 'passthrough' at line %d\n",
9516+ v->value, v->lineno);
9517+ } else if (!strcasecmp(v->name, "pritransfer")) {
9518+ if (!strcasecmp(v->value, "no"))
9519+ pritransfer = 0;
9520+ else if (!strcasecmp(v->value, "ect"))
9521+ pritransfer = 1;
9522+ else if (!strcasecmp(v->value, "hangup"))
9523+ pritransfer = 2;
9524+ else
9525+ ast_log(LOG_WARNING, "'%s' is not a valid pri transfer value, should be 'no' , 'ect' or 'hangup' at line %d\n",
9526 v->value, v->lineno);
9527 } else if (!strcasecmp(v->name, "priexclusive")) {
9528 cur_priexclusive = ast_true(v->value);
b684b13b 9529@@ -10707,6 +12335,14 @@
5e69ef1a
MT
9530 ast_copy_string(privateprefix, v->value, sizeof(privateprefix));
9531 } else if (!strcasecmp(v->name, "unknownprefix")) {
9532 ast_copy_string(unknownprefix, v->value, sizeof(unknownprefix));
9533+ } else if (!strcasecmp(v->name, "nocid")) {
9534+ ast_copy_string(nocid, v->value, sizeof(nocid) - 1);
9535+ } else if (!strcasecmp(v->name, "withheldcid")) {
9536+ ast_copy_string(withheldcid, v->value, sizeof(withheldcid) - 1);
5f892677
MT
9537+ } else if (!strcasecmp(v->name, "pin")) {
9538+ ast_copy_string(gsm_modem_pin, v->value, sizeof(gsm_modem_pin) - 1);
9539+ } else if (!strcasecmp(v->name, "exten")) {
9540+ ast_copy_string(gsm_modem_exten, v->value, sizeof(gsm_modem_exten) - 1);
5e69ef1a
MT
9541 } else if (!strcasecmp(v->name, "resetinterval")) {
9542 if (!strcasecmp(v->value, "never"))
9543 resetinterval = -1;
b684b13b 9544@@ -10723,6 +12359,8 @@
5e69ef1a
MT
9545 ast_copy_string(idleext, v->value, sizeof(idleext));
9546 } else if (!strcasecmp(v->name, "idledial")) {
9547 ast_copy_string(idledial, v->value, sizeof(idledial));
9548+ } else if (!strcasecmp(v->name, "pritrustusercid")) {
9549+ usercid = ast_true(v->value);
9550 } else if (!strcasecmp(v->name, "overlapdial")) {
9551 overlapdial = ast_true(v->value);
9552 } else if (!strcasecmp(v->name, "pritimer")) {
b684b13b 9553@@ -10908,6 +12546,7 @@
5e69ef1a
MT
9554 #ifdef ZAPATA_PRI
9555 if (!reload) {
9556 for (x=0;x<NUM_SPANS;x++) {
9557+ pris[x].debugfd = -1;
9558 if (pris[x].pvts[0]) {
9559 if (start_pri(pris + x)) {
9560 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
b684b13b 9561@@ -10940,6 +12579,10 @@
5f892677
MT
9562 pri_set_error(zt_pri_error);
9563 pri_set_message(zt_pri_message);
9564 #endif
9565+#ifdef ZAPATA_GSM
9566+ gsm_set_error(zt_gsm_error);
9567+ gsm_set_message(zt_gsm_message);
9568+#endif
9569 res = setup_zap(0);
9570 /* Make sure we can register our Zap channel type */
9571 if(res) {
b684b13b 9572@@ -10957,6 +12600,11 @@
5f892677
MT
9573 ast_cli_register_multiple(zap_r2_cli, sizeof(zap_r2_cli) / sizeof(zap_r2_cli[0]));
9574 #endif
9575 ast_cli_register_multiple(zap_cli, sizeof(zap_cli) / sizeof(zap_cli[0]));
9576+#ifdef ZAPATA_GSM
9577+ ast_cli_register(&gsm_send_sms);
9578+ ast_cli_register(&gsm_send_pdu);
9579+ ast_cli_register(&gsm_show_status);
9580+#endif
9581
9582 memset(round_robin, 0, sizeof(round_robin));
9583 ast_manager_register( "ZapTransfer", 0, action_transfer, "Transfer Zap Channel" );
b684b13b 9584@@ -10965,11 +12613,47 @@
5e69ef1a
MT
9585 ast_manager_register( "ZapDNDon", 0, action_zapdndon, "Toggle Zap channel Do Not Disturb status ON" );
9586 ast_manager_register( "ZapDNDoff", 0, action_zapdndoff, "Toggle Zap channel Do Not Disturb status OFF" );
9587 ast_manager_register("ZapShowChannels", 0, action_zapshowchannels, "Show status zapata channels");
9588-
9589+ ast_register_application(zapEC_app, app_zapEC, zapEC_synopsis, zapEC_tdesc);
9590+#ifdef ZAPATA_PRI
9591+ ast_register_application(zapCD_app, app_zapCD, zapCD_synopsis, zapCD_tdesc);
b684b13b 9592+ ast_register_application(zapInband_app, app_zapInband, zapInband_synopsis, zapInband_tdesc);
5e69ef1a
MT
9593+#endif
9594 return res;
9595 }
9596
9597+#ifdef ZAPATA_PRI
9598+static int zt_tdd_sendtext(struct ast_channel *c, const char *text);
9599+
9600+static int zt_pri_sendtext(struct ast_channel *c, const char *text) {
9601+ struct zt_pvt *p = c->tech_pvt;
9602+ if (!p) return -1;
9603+ if (!p->pri) return -1;
9604+ if (strlen(text)) {
9605+ if (p->pri) {
9606+ if (!pri_grab(p, p->pri)) {
9607+ // ast_log(LOG_NOTICE, "Sending Display IE '%s'\n", text);
9608+ pri_information_display(p->pri->pri,p->call,(char *)text);
9609+ pri_rel(p->pri);
9610+ } else ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
9611+ }
9612+ }
9613+ return 0;
9614+}
9615+
9616+static int zt_sendtext(struct ast_channel *c, const char *text) {
9617+ struct zt_pvt *p = c->tech_pvt;
9618+ if (!p) return -1;
9619+ if (p->sig == SIG_PRI) {
9620+ return zt_pri_sendtext(c, text);
9621+ } else {
9622+ return zt_tdd_sendtext(c, text);
9623+ }
9624+}
9625+
9626+static int zt_tdd_sendtext(struct ast_channel *c, const char *text)
9627+#else
9628 static int zt_sendtext(struct ast_channel *c, const char *text)
9629+#endif
9630 {
9631 #define END_SILENCE_LEN 400
9632 #define HEADER_MS 50
b684b13b 9633@@ -10988,6 +12672,7 @@
5e69ef1a
MT
9634 float scont = 0.0;
9635 int index;
9636
9637+
9638 index = zt_get_index(c, p, 0);
9639 if (index < 0) {
9640 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
b684b13b
MT
9641diff -urN asterisk-1.2.9.1.orig/codecs/codec_ilbc.c asterisk-1.2.9.1/codecs/codec_ilbc.c
9642--- asterisk-1.2.9.1.orig/codecs/codec_ilbc.c 2005-11-29 19:24:39.000000000 +0100
9643+++ asterisk-1.2.9.1/codecs/codec_ilbc.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
9644@@ -49,7 +49,7 @@
9645 #include "slin_ilbc_ex.h"
9646 #include "ilbc_slin_ex.h"
9647
9648-#define USE_ILBC_ENHANCER 0
9649+#define USE_ILBC_ENHANCER 1
9650 #define ILBC_MS 30
9651 /* #define ILBC_MS 20 */
9652
b684b13b
MT
9653diff -urN asterisk-1.2.9.1.orig/configs/capi.conf.sample asterisk-1.2.9.1/configs/capi.conf.sample
9654--- asterisk-1.2.9.1.orig/configs/capi.conf.sample 1970-01-01 01:00:00.000000000 +0100
9655+++ asterisk-1.2.9.1/configs/capi.conf.sample 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
9656@@ -0,0 +1,44 @@
9657+;
9658+; CAPI config
9659+;
9660+;
9661+[general]
9662+nationalprefix=0
9663+internationalprefix=00
9664+rxgain=0.8
9665+txgain=0.8
9666+
9667+[interfaces]
9668+
9669+; mode: ptmp (point-to-multipoint) or ptp (point-to-point)
9670+isdnmode=ptmp
9671+; allow incoming calls to this list of MSNs, * == any
9672+incomingmsn=*
9673+; capi controller number
9674+controller=1
9675+; dialout group
9676+group=1
9677+; enable/disable software dtmf detection, recommended for AVM cards
9678+softdtmf=1
9679+; accountcode to use in CDRs
9680+accountcode=
9681+; context for incoming calls
9682+context=capi-in
9683+; _VERY_PRIMITIVE_ echo suppression
9684+;echosquelch=1
9685+; EICON DIVA SERVER echo cancelation
9686+;echocancel=yes
9687+;echotail=64
9688+; call group
9689+;callgroup=1
9690+; deflect incoming calls to 12345678 if all B channels are busy
9691+;deflect=12345678
9692+; number of concurrent calls on this controller (2 makes sense for single BRI)
9693+devices => 2
9694+
9695+
9696+;PointToPoint (55512-0)
9697+;isdnmode=ptp
9698+;msn=55512
9699+;controller=2
9700+;devices => 30
b684b13b
MT
9701diff -urN asterisk-1.2.9.1.orig/configs/modules.conf.sample asterisk-1.2.9.1/configs/modules.conf.sample
9702--- asterisk-1.2.9.1.orig/configs/modules.conf.sample 2005-11-29 19:24:39.000000000 +0100
9703+++ asterisk-1.2.9.1/configs/modules.conf.sample 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
9704@@ -51,3 +51,4 @@
9705 ; exported to modules loaded after them.
9706 ;
9707 [global]
9708+chan_capi.so=yes
b684b13b
MT
9709diff -urN asterisk-1.2.9.1.orig/configs/watchdog.conf.sample asterisk-1.2.9.1/configs/watchdog.conf.sample
9710--- asterisk-1.2.9.1.orig/configs/watchdog.conf.sample 1970-01-01 01:00:00.000000000 +0100
9711+++ asterisk-1.2.9.1/configs/watchdog.conf.sample 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
9712@@ -0,0 +1,22 @@
9713+;
9714+; Configuration file for res_watchdog
9715+;
9716+; type = isdnguard | watchdog
9717+; device = /dev/...
9718+; interval = interval to trigger the watchdog in ms
9719+
9720+;[ISDNguard-direct]
9721+;type = isdnguard
9722+;device = /dev/ttyS0
9723+;interval = 200
9724+
9725+;[ISDNguard-with-daemon]
9726+;type = isdnguard
9727+;device = /var/run/guard.ctl
9728+;interval = 200
9729+
9730+;[kernel_watchdog]
9731+;type = watchdog
9732+;device = /dev/watchdog
9733+;interval = 100
9734+
b684b13b
MT
9735diff -urN asterisk-1.2.9.1.orig/configs/zapata.conf.sample asterisk-1.2.9.1/configs/zapata.conf.sample
9736--- asterisk-1.2.9.1.orig/configs/zapata.conf.sample 2006-04-28 18:40:32.000000000 +0200
9737+++ asterisk-1.2.9.1/configs/zapata.conf.sample 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
9738@@ -121,9 +121,20 @@
9739 ;
9740 ; outofband: Signal Busy/Congestion out of band with RELEASE/DISCONNECT
9741 ; inband: Signal Busy/Congestion using in-band tones
9742+; passthrough: Listen to the telco
9743 ;
9744 ; priindication = outofband
9745 ;
9746+; PRI/BRI transfers (HOLD -> SETUP -> ECT/Hangup)
9747+;
9748+; Configure how transfers are initiated. ECT should be preferred
9749+;
9750+; no: no transfers allowed (results in hangup)
9751+; ect: use ECT (facility)
9752+: hangup: transfer on hangup (if your phones dont support ECT)
9753+;
9754+; pritransfer = ect
9755+;
9756 ; If you need to override the existing channels selection routine and force all
9757 ; PRI channels to be marked as exclusively selected, set this to yes.
9758 ; priexclusive = yes
b684b13b
MT
9759diff -urN asterisk-1.2.9.1.orig/db.c asterisk-1.2.9.1/db.c
9760--- asterisk-1.2.9.1.orig/db.c 2006-01-09 19:09:53.000000000 +0100
9761+++ asterisk-1.2.9.1/db.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
9762@@ -516,11 +516,18 @@
9763 struct ast_cli_entry cli_database_deltree =
9764 { { "database", "deltree", NULL }, database_deltree, "Removes database keytree/values", database_deltree_usage };
9765
9766+static char mandescr_dbput[] =
9767+"Description: Put a value into astdb\n"
9768+"Variables: \n"
9769+" Family: ...\n"
9770+" Key: ...\n"
9771+" Value: ...\n";
9772+
9773 static int manager_dbput(struct mansession *s, struct message *m)
9774 {
9775 char *family = astman_get_header(m, "Family");
9776 char *key = astman_get_header(m, "Key");
9777- char *val = astman_get_header(m, "Val");
9778+ char *val = astman_get_header(m, "Value");
9779 int res;
9780
9781 if (!strlen(family)) {
9782@@ -545,6 +552,12 @@
9783 return 0;
9784 }
9785
9786+static char mandescr_dbget[] =
9787+"Description: Get a value from astdb\n"
9788+"Variables: \n"
9789+" Family: ...\n"
9790+" Key: ...\n";
9791+
9792 static int manager_dbget(struct mansession *s, struct message *m)
9793 {
9794 char *id = astman_get_header(m,"ActionID");
9795@@ -574,7 +587,7 @@
9796 ast_cli(s->fd, "Event: DBGetResponse\r\n"
9797 "Family: %s\r\n"
9798 "Key: %s\r\n"
9799- "Val: %s\r\n"
9800+ "Value: %s\r\n"
9801 "%s"
9802 "\r\n",
9803 family, key, tmp, idText);
9804@@ -582,6 +595,39 @@
9805 return 0;
9806 }
9807
9808+static char mandescr_dbdel[] =
9809+"Description: remove value from astdb\n"
9810+"Variables: \n"
9811+" Family: ...\n"
9812+" Key: ...\n";
9813+
9814+static int manager_dbdel(struct mansession *s, struct message *m)
9815+{
9816+ char *family = astman_get_header(m, "Family");
9817+ char *key = astman_get_header(m, "Key");
9818+ char *id = astman_get_header(m,"ActionID");
9819+
9820+ if (!strlen(family)) {
9821+ astman_send_error(s, m, "No family specified");
9822+ return 0;
9823+ }
9824+ if (!strlen(key)) {
9825+ astman_send_error(s, m, "No key specified");
9826+ return 0;
9827+ }
9828+
9829+ if (ast_db_del(family, key)) {
9830+ ast_cli(s->fd, "Response: Failed\r\n");
9831+ } else {
9832+ ast_cli(s->fd, "Response: Success\r\n");
9833+ }
9834+ if (id && !ast_strlen_zero(id))
9835+ ast_cli(s->fd, "ActionID: %s\r\n",id);
9836+ ast_cli(s->fd, "\r\n");
9837+
9838+ return 0;
9839+}
9840+
9841 int astdb_init(void)
9842 {
9843 dbinit();
9844@@ -591,7 +637,8 @@
9845 ast_cli_register(&cli_database_put);
9846 ast_cli_register(&cli_database_del);
9847 ast_cli_register(&cli_database_deltree);
9848- ast_manager_register("DBGet", EVENT_FLAG_SYSTEM, manager_dbget, "Get DB Entry");
9849- ast_manager_register("DBPut", EVENT_FLAG_SYSTEM, manager_dbput, "Put DB Entry");
9850+ ast_manager_register("DBget", EVENT_FLAG_SYSTEM, manager_dbget, mandescr_dbget);
9851+ ast_manager_register("DBput", EVENT_FLAG_SYSTEM, manager_dbput, mandescr_dbput);
9852+ ast_manager_register("DBdel", EVENT_FLAG_SYSTEM, manager_dbdel, mandescr_dbdel);
9853 return 0;
9854 }
b684b13b
MT
9855diff -urN asterisk-1.2.9.1.orig/devicestate.c asterisk-1.2.9.1/devicestate.c
9856--- asterisk-1.2.9.1.orig/devicestate.c 2006-02-10 21:38:59.000000000 +0100
9857+++ asterisk-1.2.9.1/devicestate.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
9858@@ -62,6 +62,8 @@
9859
9860 struct state_change {
9861 AST_LIST_ENTRY(state_change) list;
9862+ char cid_num[AST_MAX_EXTENSION];
9863+ char cid_name[AST_MAX_EXTENSION];
9864 char device[1];
9865 };
9866
9867@@ -177,7 +179,7 @@
9868 }
9869
9870 /*--- do_state_change: Notify callback watchers of change, and notify PBX core for hint updates */
9871-static void do_state_change(const char *device)
9872+static void do_state_change(const char *device, char *cid_num, char *cid_name)
9873 {
9874 int state;
9875 struct devstate_cb *devcb;
9876@@ -188,13 +190,13 @@
9877
9878 AST_LIST_LOCK(&devstate_cbs);
9879 AST_LIST_TRAVERSE(&devstate_cbs, devcb, list)
9880- devcb->callback(device, state, devcb->data);
9881+ devcb->callback(device, state, devcb->data, cid_num, cid_name);
9882 AST_LIST_UNLOCK(&devstate_cbs);
9883
9884- ast_hint_state_changed(device);
9885+ ast_hint_state_changed(device, cid_num, cid_name);
9886 }
9887
9888-static int __ast_device_state_changed_literal(char *buf)
9889+static int __ast_device_state_changed_literal(char *buf, char *cid_num, char *cid_name)
9890 {
9891 char *device, *tmp;
9892 struct state_change *change = NULL;
9893@@ -209,10 +211,16 @@
9894 if (!change) {
9895 /* we could not allocate a change struct, or */
9896 /* there is no background thread, so process the change now */
9897- do_state_change(device);
9898+ do_state_change(device, cid_num, cid_name);
9899 } else {
9900 /* queue the change */
9901 strcpy(change->device, device);
9902+ if (cid_num && (!ast_strlen_zero(cid_num))) {
9903+ strncpy(change->cid_num, cid_num, sizeof(change->cid_num) - 1);
9904+ }
9905+ if (cid_name && (!ast_strlen_zero(cid_name))) {
9906+ strncpy(change->cid_name, cid_name, sizeof(change->cid_name) - 1);
9907+ }
9908 AST_LIST_LOCK(&state_changes);
9909 AST_LIST_INSERT_TAIL(&state_changes, change, list);
9910 if (AST_LIST_FIRST(&state_changes) == change)
9911@@ -224,23 +232,49 @@
9912 return 1;
9913 }
9914
9915-int ast_device_state_changed_literal(const char *dev)
9916+int ast_device_state_changed_literal(const char *dev, const char *cid_num, const char *cid_name)
9917 {
9918 char *buf;
9919+ char *buf2 = NULL;
9920+ char *buf3 = NULL;
9921 buf = ast_strdupa(dev);
9922- return __ast_device_state_changed_literal(buf);
9923+ if (cid_num)
9924+ buf2 = ast_strdupa(cid_num);
9925+ if (cid_name)
9926+ buf3 = ast_strdupa(cid_name);
9927+ return __ast_device_state_changed_literal(buf, buf2, buf3);
9928 }
9929
9930 /*--- ast_device_state_changed: Accept change notification, add it to change queue */
9931 int ast_device_state_changed(const char *fmt, ...)
9932 {
9933 char buf[AST_MAX_EXTENSION];
9934+ char cid_num[AST_MAX_EXTENSION];
9935+ char cid_name[AST_MAX_EXTENSION];
9936+ char *s = NULL;
9937 va_list ap;
9938
9939 va_start(ap, fmt);
9940- vsnprintf(buf, sizeof(buf), fmt, ap);
9941+ if (*fmt == 's') {
9942+ s = va_arg(ap, char *);
9943+ snprintf(buf, sizeof(buf), s);
9944+ *fmt++;
9945+ if (*fmt == 's') {
9946+ s = va_arg(ap, char *);
9947+ if (s) {
9948+ snprintf(cid_num, sizeof(cid_num), s);
9949+ }
9950+ *fmt++;
9951+ if (*fmt == 's') {
9952+ s = va_arg(ap, char *);
9953+ if (s) {
9954+ snprintf(cid_name, sizeof(cid_name), s);
9955+ }
9956+ }
9957+ }
9958+ }
9959 va_end(ap);
9960- return __ast_device_state_changed_literal(buf);
9961+ return __ast_device_state_changed_literal(buf, cid_num, cid_name);
9962 }
9963
9964 /*--- do_devstate_changes: Go through the dev state change queue and update changes in the dev state thread */
9965@@ -255,7 +289,7 @@
9966 if (cur) {
9967 /* we got an entry, so unlock the list while we process it */
9968 AST_LIST_UNLOCK(&state_changes);
9969- do_state_change(cur->device);
9970+ do_state_change(cur->device, cur->cid_num, cur->cid_name);
9971 free(cur);
9972 AST_LIST_LOCK(&state_changes);
9973 } else {
b684b13b
MT
9974diff -urN asterisk-1.2.9.1.orig/doc/README.asterisk.conf asterisk-1.2.9.1/doc/README.asterisk.conf
9975--- asterisk-1.2.9.1.orig/doc/README.asterisk.conf 2005-11-29 19:24:39.000000000 +0100
9976+++ asterisk-1.2.9.1/doc/README.asterisk.conf 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
9977@@ -62,6 +62,7 @@
9978 maxcalls = 255 ; The maximum number of concurrent calls you want to allow
9979 execincludes = yes | no ; Allow #exec entries in configuration files
9980 dontwarn = yes | no ; Don't over-inform the Asterisk sysadm, he's a guru
9981+uniquename = asterisk ; host name part to be included in the uniqueid
9982
9983 [files]
9984 ; Changing the following lines may compromise your security
b684b13b
MT
9985diff -urN asterisk-1.2.9.1.orig/editline/cygdef.h asterisk-1.2.9.1/editline/cygdef.h
9986--- asterisk-1.2.9.1.orig/editline/cygdef.h 1970-01-01 01:00:00.000000000 +0100
9987+++ asterisk-1.2.9.1/editline/cygdef.h 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
9988@@ -0,0 +1,11 @@
9989+/* cygdef.h. Generated automatically by configure. */
9990+#ifndef _CYGDEF_H_
9991+#define _CYGDEF_H_ 1
9992+#include <sys/ioctl.h>
9993+#define __linux__ 1
9994+
9995+
9996+typedef void (*sig_t)(int);
9997+
9998+
9999+#endif /* _CYGDEF_H_ */
b684b13b
MT
10000diff -urN asterisk-1.2.9.1.orig/include/asterisk/agi.h asterisk-1.2.9.1/include/asterisk/agi.h
10001--- asterisk-1.2.9.1.orig/include/asterisk/agi.h 2005-11-29 19:24:39.000000000 +0100
10002+++ asterisk-1.2.9.1/include/asterisk/agi.h 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
10003@@ -29,7 +29,8 @@
10004
10005 typedef struct agi_state {
10006 int fd; /* FD for general output */
10007- int audio; /* FD for audio output */
10008+ int audio_out; /* FD for audio output */
10009+ int audio_in; /* FD for audio output */
10010 int ctrl; /* FD for input control */
10011 } AGI;
10012
b684b13b
MT
10013diff -urN asterisk-1.2.9.1.orig/include/asterisk/chan_capi.h asterisk-1.2.9.1/include/asterisk/chan_capi.h
10014--- asterisk-1.2.9.1.orig/include/asterisk/chan_capi.h 1970-01-01 01:00:00.000000000 +0100
10015+++ asterisk-1.2.9.1/include/asterisk/chan_capi.h 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
10016@@ -0,0 +1,276 @@
10017+/*
10018+ * (CAPI*)
10019+ *
10020+ * An implementation of Common ISDN API 2.0 for Asterisk
10021+ *
10022+ * Copyright (C) 2002, 2003, 2004, Junghanns.NET GmbH
10023+ *
10024+ * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
10025+ *
10026+ * This program is free software and may be modified and
10027+ * distributed under the terms of the GNU Public License.
10028+ */
10029+
10030+#ifndef _ASTERISK_CAPI_H
10031+#define _ASTERISK_CAPI_H
10032+
10033+#define AST_CAPI_MAX_CONTROLLERS 16
10034+#define AST_CAPI_MAX_DEVICES 30
10035+#define AST_CAPI_MAX_BUF 160
10036+
10037+#define AST_CAPI_MAX_B3_BLOCKS 7
10038+
10039+/* was : 130 bytes Alaw = 16.25 ms audio not suitable for VoIP */
10040+/* now : 160 bytes Alaw = 20 ms audio */
10041+/* you can tune this to your need. higher value == more latency */
10042+#define AST_CAPI_MAX_B3_BLOCK_SIZE 160
10043+
10044+#define AST_CAPI_BCHANS 120
10045+#define ALL_SERVICES 0x1FFF03FF
10046+
10047+/* duration in ms for sending and detecting dtmfs */
10048+#define AST_CAPI_DTMF_DURATION 0x40
10049+
10050+#define AST_CAPI_NATIONAL_PREF "0"
10051+#define AST_CAPI_INTERNAT_PREF "00"
10052+
10053+#ifdef CAPI_ES
10054+#define ECHO_TX_COUNT 5 // 5 x 20ms = 100ms
10055+#define ECHO_EFFECTIVE_TX_COUNT 3 // 2 x 20ms = 40ms == 40-100ms ... ignore first 40ms
10056+#define ECHO_TXRX_RATIO 2.3 // if( rx < (txavg/ECHO_TXRX_RATIO) ) rx=0;
10057+#endif
10058+
10059+/*
10060+ * state combination for a normal incoming call:
10061+ * DIS -> ALERT -> CON -> BCON -> CON -> DIS
10062+ *
10063+ * outgoing call:
10064+ * DIS -> CONP -> BCONNECTED -> CON -> DIS
10065+ */
10066+
10067+#define CAPI_STATE_ALERTING 1
10068+#define CAPI_STATE_CONNECTED 2
10069+#define CAPI_STATE_BCONNECTED 3
10070+
10071+#define CAPI_STATE_DISCONNECTING 4
10072+#define CAPI_STATE_DISCONNECTED 5
10073+#define CAPI_STATE_REMOTE_HANGUP 6
10074+
10075+#define CAPI_STATE_CONNECTPENDING 7
10076+#define CAPI_STATE_ONHOLD 8
10077+#define CAPI_STATE_NETWORKHANGUP 9
10078+#define CAPI_STATE_ANSWERING 10
10079+#define CAPI_STATE_PUTTINGONHOLD 11
10080+#define CAPI_STATE_RETRIEVING 12
10081+
10082+#define CAPI_STATE_DID 13
10083+
10084+#define AST_CAPI_B3_DONT 0
10085+#define AST_CAPI_B3_ALWAYS 1
10086+#define AST_CAPI_B3_ON_SUCCESS 2
10087+
10088+#ifdef CAPI_GAIN
10089+struct ast_capi_gains {
10090+ unsigned char txgains[256];
10091+ unsigned char rxgains[256];
10092+};
10093+#endif
10094+
10095+#define PRES_ALLOWED_USER_NUMBER_NOT_SCREENED 0x00
10096+#define PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN 0x01
10097+#define PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN 0x02
10098+#define PRES_ALLOWED_NETWORK_NUMBER 0x03
10099+#define PRES_PROHIB_USER_NUMBER_NOT_SCREENED 0x20
10100+#define PRES_PROHIB_USER_NUMBER_PASSED_SCREEN 0x21
10101+#define PRES_PROHIB_USER_NUMBER_FAILED_SCREEN 0x22
10102+#define PRES_PROHIB_NETWORK_NUMBER 0x23
10103+#define PRES_NUMBER_NOT_AVAILABLE 0x43
10104+
10105+
10106+//! Private data for a capi device
10107+struct ast_capi_pvt {
10108+ ast_mutex_t lock;
10109+ int fd;
10110+
10111+ /*! Channel we belong to, possibly NULL */
10112+ struct ast_channel *owner;
10113+ /*! Frame */
10114+ struct ast_frame fr;
10115+
10116+ char offset[AST_FRIENDLY_OFFSET];
10117+
10118+ // capi message number
10119+ _cword MessageNumber;
10120+ int NCCI;
10121+ int PLCI;
10122+ /* on which controller we do live */
10123+ int controller;
10124+
10125+ /* we could live on those */
10126+ unsigned long controllers;
10127+
10128+ int datahandle;
10129+
10130+ short buf[AST_CAPI_MAX_BUF];
10131+ int buflen;
10132+ /*! Immediate, or wait for an answer */
10133+ int mode;
10134+ /*! State of modem in miniature */
10135+ int state;
10136+ /*! Digits to strip on outgoing numbers */
10137+ int stripmsd;
10138+ /*! ringer timeout */
10139+ int ringt;
10140+ /*! actual time of last ring */
10141+ time_t lastring;
10142+ /*! dtmf receive state/data */
10143+ char dtmfrx;
10144+
10145+ char context[AST_MAX_EXTENSION];
10146+ /*! Multiple Subscriber Number we listen to (, seperated list) */
10147+ char incomingmsn[AST_MAX_EXTENSION];
10148+ /*! Prefix to Build CID */
10149+ char prefix[AST_MAX_EXTENSION];
10150+ /*! Caller ID if available */
10151+ char cid[AST_MAX_EXTENSION];
10152+ /*! Dialed Number if available */
10153+ char dnid[AST_MAX_EXTENSION];
10154+
10155+ char accountcode[20];
10156+
10157+ unsigned int callgroup;
10158+ unsigned int group;
10159+
10160+ /*! default language */
10161+ char language[MAX_LANGUAGE];
10162+ /*! Static response buffer */
10163+ char response[256];
10164+
10165+ int calledPartyIsISDN;
10166+ // this is an outgoing channel
10167+ int outgoing;
10168+ // use CLIR
10169+ int CLIR;
10170+ // are we doing early B3 connect on this interface?
10171+ int earlyB3;
10172+ // should we do early B3 on this interface?
10173+ int doB3;
10174+ // store plci here for the call that is onhold
10175+ int onholdPLCI;
10176+ // do software dtmf detection
10177+ int doDTMF;
10178+ // CAPI echo cancellation
10179+ int doEC;
10180+ int ecOption;
10181+ int ecTail;
10182+ // isdnmode ptp or ptm
10183+ int isdnmode;
10184+#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
10185+ // deflect on circuitbusy
10186+ char deflect2[AST_MAX_EXTENSION];
10187+#endif
10188+
10189+ // not all codecs supply frames in nice 320 byte chunks
10190+ struct ast_smoother *smoother;
10191+ // ok, we stop to be nice and give them the lowest possible latency 130 samples * 2 = 260 bytes */
10192+#ifdef CAPI_SYNC
10193+ int B3in;
10194+ ast_mutex_t lockB3in;
10195+#endif
10196+
10197+ // do ECHO SURPRESSION
10198+ int doES;
10199+#ifdef CAPI_ES
10200+ short txavg[ECHO_TX_COUNT];
10201+ float rxmin;
10202+ float txmin;
10203+#endif
10204+#ifdef CAPI_GAIN
10205+ struct ast_capi_gains g;
10206+#endif
10207+ float txgain;
10208+ float rxgain;
10209+ struct ast_dsp *vad;
10210+
10211+
10212+ struct capi_pipe *mypipe;
10213+ /*! Next channel in list */
10214+ struct ast_capi_pvt *next;
10215+};
10216+
10217+
10218+struct ast_capi_profile {
10219+ unsigned short ncontrollers;
10220+ unsigned short nbchannels;
10221+ unsigned char globaloptions;
10222+ unsigned char globaloptions2;
10223+ unsigned char globaloptions3;
10224+ unsigned char globaloptions4;
10225+ unsigned int b1protocols;
10226+ unsigned int b2protocols;
10227+ unsigned int b3protocols;
10228+ unsigned int reserved3[6];
10229+ unsigned int manufacturer[5];
10230+};
10231+
10232+struct capi_pipe {
10233+ // lock
10234+ ast_mutex_t lock;
10235+
10236+ // fd for writing to the channel
10237+ int fd;
10238+
10239+ // PLCI and NCCI of the B3 CON
10240+ int PLCI;
10241+ int NCCI;
10242+ // pointer to the interface
10243+ struct ast_capi_pvt *i;
10244+ // pointer to the channel
10245+ struct ast_channel *c;
10246+ // next pipe
10247+ struct capi_pipe *next;
10248+};
10249+
10250+struct ast_capi_controller {
10251+ // which controller is this?
10252+ int controller;
10253+ // how many bchans?
10254+ int nbchannels;
10255+ // free bchans
10256+ int nfreebchannels;
10257+ // DID
10258+ int isdnmode;
10259+ // features:
10260+ int dtmf;
10261+ int echocancel;
10262+ int sservices; // supplementray services
10263+ // supported sservices:
10264+ int holdretrieve;
10265+ int terminalportability;
10266+ int ECT;
10267+ int threePTY;
10268+ int CF;
10269+ int CD;
10270+ int MCID;
10271+ int CCBS;
10272+ int MWI;
10273+ int CCNR;
10274+ int CONF;
10275+};
10276+
10277+
10278+// ETSI 300 102-1 information element identifiers
10279+#define CAPI_ETSI_IE_CAUSE 0x08;
10280+#define CAPI_ETSI_IE_PROGRESS_INDICATOR 0x1e;
10281+#define CAPI_ETSI_IE_CALLED_PARTY_NUMBER 0x70;
10282+
10283+// ETIS 300 102-1 message types
10284+#define CAPI_ETSI_ALERTING 0x01;
10285+#define CAPI_ETSI_SETUP_ACKKNOWLEDGE 0x0d;
10286+#define CAPI_ETSI_DISCONNECT 0x45;
10287+
10288+// ETSI 300 102-1 Numbering Plans
10289+#define CAPI_ETSI_NPLAN_NATIONAL 0x20
10290+#define CAPI_ETSI_NPLAN_INTERNAT 0x10
10291+
10292+#endif
b684b13b
MT
10293diff -urN asterisk-1.2.9.1.orig/include/asterisk/chan_capi_app.h asterisk-1.2.9.1/include/asterisk/chan_capi_app.h
10294--- asterisk-1.2.9.1.orig/include/asterisk/chan_capi_app.h 1970-01-01 01:00:00.000000000 +0100
10295+++ asterisk-1.2.9.1/include/asterisk/chan_capi_app.h 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
10296@@ -0,0 +1,30 @@
10297+/*
10298+ * (CAPI*)
10299+ *
10300+ * An implementation of Common ISDN API 2.0 for Asterisk
10301+ *
10302+ * include file for helper applications
10303+ *
10304+ * Copyright (C) 2002, 2003, 2004, Junghanns.NET GmbH
10305+ *
10306+ * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
10307+ *
10308+ * This program is free software and may be modified and
10309+ * distributed under the terms of the GNU Public License.
10310+ */
10311+
10312+#ifndef _ASTERISK_CAPI_IF_H
10313+#define _ASTERISK_CAPI_IF_H
10314+
10315+// exported symbols from chan_capi
10316+
10317+// important things we need
10318+extern unsigned ast_capi_ApplID;
10319+extern unsigned ast_capi_MessageNumber;
10320+extern int capidebug;
10321+
10322+extern int capi_call(struct ast_channel *c, char *idest, int timeout);
10323+extern int capi_detect_dtmf(struct ast_channel *c, int flag);
10324+extern MESSAGE_EXCHANGE_ERROR _capi_put_cmsg(_cmsg *CMSG);
10325+
10326+#endif
b684b13b
MT
10327diff -urN asterisk-1.2.9.1.orig/include/asterisk/channel.h asterisk-1.2.9.1/include/asterisk/channel.h
10328--- asterisk-1.2.9.1.orig/include/asterisk/channel.h 2006-06-01 22:27:50.000000000 +0200
10329+++ asterisk-1.2.9.1/include/asterisk/channel.h 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
10330@@ -86,6 +86,9 @@
10331 #ifndef _ASTERISK_CHANNEL_H
10332 #define _ASTERISK_CHANNEL_H
10333
10334+/* Max length of the uniqueid */
10335+#define AST_MAX_UNIQUEID 64
10336+
10337 #include <unistd.h>
10338 #include <setjmp.h>
10339 #ifdef POLLCOMPAT
b684b13b 10340@@ -381,7 +384,7 @@
5e69ef1a
MT
10341 unsigned int fout;
10342
10343 /* Unique Channel Identifier */
10344- char uniqueid[32];
10345+ char uniqueid[AST_MAX_UNIQUEID];
10346
10347 /* Why is the channel hanged up */
10348 int hangupcause;
b684b13b 10349@@ -398,6 +401,12 @@
5f892677
MT
10350 /*! ISDN Transfer Capbility - AST_FLAG_DIGITAL is not enough */
10351 unsigned short transfercapability;
10352
10353+ /*! ISDN Low Layer Compatibility */
10354+ char lowlayercompat[16];
10355+
10356+ /*! ISDN High Layer Compatibility */
10357+ char highlayercompat[4];
10358+
10359 struct ast_frame *readq;
10360 int alertpipe[2];
10361 /*! Write translation path */
b684b13b 10362@@ -534,6 +543,11 @@
5e69ef1a
MT
10363 #define AST_STATE_MUTE (1 << 16)
10364 /*! @} */
10365
10366+extern ast_mutex_t uniquelock;
10367+
10368+/*! \brief Change the state of a channel and the callerid of the calling channel*/
10369+int ast_setstate_and_cid(struct ast_channel *chan, int state, char *cid_num, char *cid_name);
10370+
10371 /*! \brief Change the state of a channel */
10372 int ast_setstate(struct ast_channel *chan, int state);
10373
b684b13b 10374@@ -570,7 +584,7 @@
5e69ef1a
MT
10375 * by the low level module
10376 * \return Returns an ast_channel on success, NULL on failure.
10377 */
10378-struct ast_channel *ast_request(const char *type, int format, void *data, int *status);
10379+struct ast_channel *ast_request(const char *type, int format, void *data, int *status, char *uniqueid);
10380
10381 /*!
10382 * \brief Request a channel of a given type, with data as optional information used
b684b13b 10383@@ -585,9 +599,9 @@
5e69ef1a
MT
10384 * \return Returns an ast_channel on success or no answer, NULL on failure. Check the value of chan->_state
10385 * to know if the call was answered or not.
10386 */
10387-struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, const char *cidnum, const char *cidname);
10388+struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, int callingpres, const char *cidnum, const char *cidname, char *uniqueid);
10389
10390-struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, const char *cidnum, const char *cidname, struct outgoing_helper *oh);
10391+struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, int callingpres, const char *cidnum, const char *cidname, struct outgoing_helper *oh, char *uniqueid);
10392
10393 /*!\brief Register a channel technology (a new channel driver)
10394 * Called by a channel module to register the kind of channels it supports.
b684b13b 10395@@ -840,6 +854,10 @@
5e69ef1a
MT
10396 /*--- ast_get_channel_by_exten_locked: Get channel by exten (and optionally context) and lock it */
10397 struct ast_channel *ast_get_channel_by_exten_locked(const char *exten, const char *context);
10398
10399+/*! Get channel by uniqueid (locks channel) */
10400+struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid);
10401+
10402+
10403 /*! Waits for a digit */
10404 /*!
10405 * \param c channel to wait for a digit on
b684b13b 10406@@ -910,6 +928,9 @@
5e69ef1a
MT
10407 p->owner pointer) that is affected by the change. The physical layer of the original
10408 channel is hung up. */
10409 int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone);
10410+int ast_channel_masquerade_locked(struct ast_channel *original, struct ast_channel *clone);
10411+
10412+char *ast_alloc_uniqueid(void);
10413
10414 /*! Gives the string form of a given cause code */
10415 /*!
b684b13b
MT
10416diff -urN asterisk-1.2.9.1.orig/include/asterisk/devicestate.h asterisk-1.2.9.1/include/asterisk/devicestate.h
10417--- asterisk-1.2.9.1.orig/include/asterisk/devicestate.h 2005-11-29 19:24:39.000000000 +0100
10418+++ asterisk-1.2.9.1/include/asterisk/devicestate.h 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
10419@@ -42,7 +42,7 @@
10420 /*! Device is ringing */
10421 #define AST_DEVICE_RINGING 6
10422
10423-typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data);
10424+typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data, char *cid_num, char *cid_name);
10425
10426 /*! \brief Convert device state to text string for output
10427 * \param devstate Current device state
10428@@ -84,7 +84,7 @@
10429 * callbacks for the changed extensions
10430 * Returns 0 on success, -1 on failure
10431 */
10432-int ast_device_state_changed_literal(const char *device);
10433+int ast_device_state_changed_literal(const char *device, const char *cid_num, const char *cid_name);
10434
10435 /*! \brief Registers a device state change callback
10436 * \param callback Callback
b684b13b
MT
10437diff -urN asterisk-1.2.9.1.orig/include/asterisk/features.h asterisk-1.2.9.1/include/asterisk/features.h
10438--- asterisk-1.2.9.1.orig/include/asterisk/features.h 2005-11-29 19:24:39.000000000 +0100
10439+++ asterisk-1.2.9.1/include/asterisk/features.h 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
10440@@ -45,6 +45,8 @@
10441 };
10442
10443
10444+extern int ast_autoanswer_login(struct ast_channel *chan, void *data);
10445+extern int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data);
10446
10447 /*! \brief Park a call and read back parked location
10448 * \param chan the channel to actually be parked
10449@@ -68,11 +70,19 @@
10450 */
10451 extern int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *host, int timeout, int *extout);
10452
10453+extern int ast_hold_call(struct ast_channel *chan, struct ast_channel *host);
10454+extern int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *host);
10455+extern int ast_retrieve_call(struct ast_channel *chan, char *uniqueid);
10456+extern int ast_retrieve_call_to_death(char *uniqueid);
10457+extern struct ast_channel *ast_get_holded_call(char *uniqueid);
10458+
10459 /*! \brief Determine system parking extension
10460 * Returns the call parking extension for drivers that provide special
10461 call parking help */
10462 extern char *ast_parking_ext(void);
10463
10464+extern char *ast_parking_con(void);
10465+
10466 /*! \brief Determine system call pickup extension */
10467 extern char *ast_pickup_ext(void);
10468
10469@@ -92,4 +102,12 @@
10470 \param feature the ast_call_feature object which was registered before*/
10471 extern void ast_unregister_feature(struct ast_call_feature *feature);
10472
10473+/*! \brief find a feature by name
10474+ \param name of the feature to be returned */
10475+extern struct ast_call_feature *ast_find_feature(char *name);
10476+
10477+/*! \brief find a builtin feature by name
10478+ \param name of the feature to be returned */
10479+extern struct ast_call_feature *ast_find_builtin_feature(char *name);
10480+
10481 #endif /* _AST_FEATURES_H */
b684b13b
MT
10482diff -urN asterisk-1.2.9.1.orig/include/asterisk/monitor.h asterisk-1.2.9.1/include/asterisk/monitor.h
10483--- asterisk-1.2.9.1.orig/include/asterisk/monitor.h 2005-11-29 19:24:39.000000000 +0100
10484+++ asterisk-1.2.9.1/include/asterisk/monitor.h 2006-06-09 10:25:04.000000000 +0200
10485@@ -35,6 +35,8 @@
10486 char write_filename[FILENAME_MAX];
10487 char filename_base[FILENAME_MAX];
10488 int filename_changed;
10489+ char target_url[FILENAME_MAX];
10490+ char target_script[FILENAME_MAX];
10491 char *format;
10492 int joinfiles;
10493 int (*stop)(struct ast_channel *chan, int need_lock);
10494@@ -42,7 +44,7 @@
10495
10496 /* Start monitoring a channel */
10497 int ast_monitor_start(struct ast_channel *chan, const char *format_spec,
10498- const char *fname_base, int need_lock );
10499+ const char *fname_base, const char *target_url, const char *target_script, int need_lock );
10500
10501 /* Stop monitoring a channel */
10502 int ast_monitor_stop(struct ast_channel *chan, int need_lock);
10503diff -urN asterisk-1.2.9.1.orig/include/asterisk/pbx.h asterisk-1.2.9.1/include/asterisk/pbx.h
10504--- asterisk-1.2.9.1.orig/include/asterisk/pbx.h 2006-03-29 21:11:18.000000000 +0200
10505+++ asterisk-1.2.9.1/include/asterisk/pbx.h 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
10506@@ -57,7 +57,7 @@
10507 AST_EXTENSION_BUSY = 1 << 1,
10508 /*! All devices UNAVAILABLE/UNREGISTERED */
10509 AST_EXTENSION_UNAVAILABLE = 1 << 2,
10510- /*! All devices RINGING */
10511+ /*! One or more devices RINGING */
10512 AST_EXTENSION_RINGING = 1 << 3,
10513 };
10514
10515@@ -80,7 +80,7 @@
10516 struct ast_ignorepat;
10517 struct ast_sw;
10518
10519-typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data);
10520+typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data, char *cid_num, char *cid_name);
10521
10522 /*! Data structure associated with a custom function */
10523 struct ast_custom_function {
10524@@ -156,6 +156,8 @@
10525 */
10526 extern struct ast_app *pbx_findapp(const char *app);
10527
10528+void *ast_pbx_run_app(void *data);
10529+
10530 /*! executes an application */
10531 /*!
10532 * \param c channel to execute on
10533@@ -563,11 +565,11 @@
10534
10535 /* Synchronously or asynchronously make an outbound call and send it to a
10536 particular extension */
5f892677
MT
10537-int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel);
10538+int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid);
5e69ef1a
MT
10539
10540 /* Synchronously or asynchronously make an outbound call and send it to a
10541 particular application with given extension */
5f892677
MT
10542-int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel);
10543+int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid);
5e69ef1a 10544
5f892677
MT
10545 /* Evaluate a condition for non-falseness and return a boolean */
10546 int pbx_checkcondition(char *condition);
10547@@ -659,7 +661,7 @@
5e69ef1a
MT
10548 */
10549 void ast_func_write(struct ast_channel *chan, const char *in, const char *value);
10550
10551-void ast_hint_state_changed(const char *device);
5f892677 10552+void ast_hint_state_changed(const char *device, char *cid_num, char *cid_name);
5e69ef1a
MT
10553
10554 #if defined(__cplusplus) || defined(c_plusplus)
10555 }
b684b13b
MT
10556diff -urN asterisk-1.2.9.1.orig/include/asterisk/xlaw.h asterisk-1.2.9.1/include/asterisk/xlaw.h
10557--- asterisk-1.2.9.1.orig/include/asterisk/xlaw.h 1970-01-01 01:00:00.000000000 +0100
10558+++ asterisk-1.2.9.1/include/asterisk/xlaw.h 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
10559@@ -0,0 +1,1665 @@
10560+#ifndef _ASTERISK_XLAW_H
10561+#define _ASTERISK_XLAW_H
10562+
10563+#ifdef CAPI_ULAW
10564+#define capiXLAW2INT(x) capiULAW2INT[x]
10565+#define capiINT2XLAW(x) capiINT2ULAW[((unsigned short)x) >> 2]
10566+#else
10567+#define capiXLAW2INT(x) capiALAW2INT[x]
10568+#define capiINT2XLAW(x) capiINT2ALAW[(x>>4)+4096]
10569+#endif
10570+
10571+static unsigned char reversebits[256] =
10572+{
10573+0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
10574+0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
10575+0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
10576+0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
10577+0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
10578+0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
10579+0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
10580+0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
10581+0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
10582+0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
10583+0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
10584+0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
10585+0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
10586+0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
10587+0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
10588+0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
10589+0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
10590+0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
10591+0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
10592+0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
10593+0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
10594+0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
10595+0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
10596+0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
10597+0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
10598+0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
10599+0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
10600+0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
10601+0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
10602+0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
10603+0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
10604+0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
10605+};
10606+
10607+#ifdef CAPI_ULAW
10608+static short capiULAW2INT[] =
10609+{
10610+0x8284, 0x7d7c, 0xf8a4, 0x075c, 0xe104, 0x1efc, 0xfe8c, 0x0174,
10611+0xc184, 0x3e7c, 0xfc94, 0x036c, 0xf0c4, 0x0f3c, 0xff88, 0x0078,
10612+0xa284, 0x5d7c, 0xfaa4, 0x055c, 0xe904, 0x16fc, 0xff0c, 0x00f4,
10613+0xd184, 0x2e7c, 0xfd94, 0x026c, 0xf4c4, 0x0b3c, 0xffc8, 0x0038,
10614+0x9284, 0x6d7c, 0xf9a4, 0x065c, 0xe504, 0x1afc, 0xfecc, 0x0134,
10615+0xc984, 0x367c, 0xfd14, 0x02ec, 0xf2c4, 0x0d3c, 0xffa8, 0x0058,
10616+0xb284, 0x4d7c, 0xfba4, 0x045c, 0xed04, 0x12fc, 0xff4c, 0x00b4,
10617+0xd984, 0x267c, 0xfe14, 0x01ec, 0xf6c4, 0x093c, 0xffe8, 0x0018,
10618+0x8a84, 0x757c, 0xf924, 0x06dc, 0xe304, 0x1cfc, 0xfeac, 0x0154,
10619+0xc584, 0x3a7c, 0xfcd4, 0x032c, 0xf1c4, 0x0e3c, 0xff98, 0x0068,
10620+0xaa84, 0x557c, 0xfb24, 0x04dc, 0xeb04, 0x14fc, 0xff2c, 0x00d4,
10621+0xd584, 0x2a7c, 0xfdd4, 0x022c, 0xf5c4, 0x0a3c, 0xffd8, 0x0028,
10622+0x9a84, 0x657c, 0xfa24, 0x05dc, 0xe704, 0x18fc, 0xfeec, 0x0114,
10623+0xcd84, 0x327c, 0xfd54, 0x02ac, 0xf3c4, 0x0c3c, 0xffb8, 0x0048,
10624+0xba84, 0x457c, 0xfc24, 0x03dc, 0xef04, 0x10fc, 0xff6c, 0x0094,
10625+0xdd84, 0x227c, 0xfe54, 0x01ac, 0xf7c4, 0x083c, 0xfff8, 0x0008,
10626+0x8684, 0x797c, 0xf8e4, 0x071c, 0xe204, 0x1dfc, 0xfe9c, 0x0164,
10627+0xc384, 0x3c7c, 0xfcb4, 0x034c, 0xf144, 0x0ebc, 0xff90, 0x0070,
10628+0xa684, 0x597c, 0xfae4, 0x051c, 0xea04, 0x15fc, 0xff1c, 0x00e4,
10629+0xd384, 0x2c7c, 0xfdb4, 0x024c, 0xf544, 0x0abc, 0xffd0, 0x0030,
10630+0x9684, 0x697c, 0xf9e4, 0x061c, 0xe604, 0x19fc, 0xfedc, 0x0124,
10631+0xcb84, 0x347c, 0xfd34, 0x02cc, 0xf344, 0x0cbc, 0xffb0, 0x0050,
10632+0xb684, 0x497c, 0xfbe4, 0x041c, 0xee04, 0x11fc, 0xff5c, 0x00a4,
10633+0xdb84, 0x247c, 0xfe34, 0x01cc, 0xf744, 0x08bc, 0xfff0, 0x0010,
10634+0x8e84, 0x717c, 0xf964, 0x069c, 0xe404, 0x1bfc, 0xfebc, 0x0144,
10635+0xc784, 0x387c, 0xfcf4, 0x030c, 0xf244, 0x0dbc, 0xffa0, 0x0060,
10636+0xae84, 0x517c, 0xfb64, 0x049c, 0xec04, 0x13fc, 0xff3c, 0x00c4,
10637+0xd784, 0x287c, 0xfdf4, 0x020c, 0xf644, 0x09bc, 0xffe0, 0x0020,
10638+0x9e84, 0x617c, 0xfa64, 0x059c, 0xe804, 0x17fc, 0xfefc, 0x0104,
10639+0xcf84, 0x307c, 0xfd74, 0x028c, 0xf444, 0x0bbc, 0xffc0, 0x0040,
10640+0xbe84, 0x417c, 0xfc64, 0x039c, 0xf004, 0x0ffc, 0xff7c, 0x0084,
10641+0xdf84, 0x207c, 0xfe74, 0x018c, 0xf844, 0x07bc, 0x0000, 0x0000
10642+};
10643+
10644+const unsigned char capiINT2ULAW[16384] = {
10645+255,127,127,191,191,63,63,223,223,95,95,159,159,31,31,239,
10646+239,111,111,175,175,47,47,207,207,79,79,143,143,15,15,247,
10647+247,247,247,119,119,119,119,183,183,183,183,55,55,55,55,215,
10648+215,215,215,87,87,87,87,151,151,151,151,23,23,23,23,231,
10649+231,231,231,103,103,103,103,167,167,167,167,39,39,39,39,199,
10650+199,199,199,71,71,71,71,135,135,135,135,7,7,7,7,251,
10651+251,251,251,251,251,251,251,123,123,123,123,123,123,123,123,187,
10652+187,187,187,187,187,187,187,59,59,59,59,59,59,59,59,219,
10653+219,219,219,219,219,219,219,91,91,91,91,91,91,91,91,155,
10654+155,155,155,155,155,155,155,27,27,27,27,27,27,27,27,235,
10655+235,235,235,235,235,235,235,107,107,107,107,107,107,107,107,171,
10656+171,171,171,171,171,171,171,43,43,43,43,43,43,43,43,203,
10657+203,203,203,203,203,203,203,75,75,75,75,75,75,75,75,139,
10658+139,139,139,139,139,139,139,11,11,11,11,11,11,11,11,243,
10659+243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,115,
10660+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,179,
10661+179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,51,
10662+51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,211,
10663+211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,83,
10664+83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,147,
10665+147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,19,
10666+19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,227,
10667+227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,99,
10668+99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,163,
10669+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,35,
10670+35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,195,
10671+195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,67,
10672+67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,131,
10673+131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,3,
10674+3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,253,
10675+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
10676+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,125,
10677+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
10678+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,189,
10679+189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
10680+189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,61,
10681+61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,
10682+61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,221,
10683+221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
10684+221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,93,
10685+93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,
10686+93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,157,
10687+157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
10688+157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,29,
10689+29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,
10690+29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,237,
10691+237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,
10692+237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,109,
10693+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
10694+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,173,
10695+173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
10696+173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,45,
10697+45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,
10698+45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,205,
10699+205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
10700+205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,77,
10701+77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
10702+77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,141,
10703+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
10704+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,13,
10705+13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
10706+13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,245,
10707+245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
10708+245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
10709+245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
10710+245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,117,
10711+117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
10712+117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
10713+117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
10714+117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,181,
10715+181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
10716+181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
10717+181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
10718+181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,53,
10719+53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
10720+53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
10721+53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
10722+53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,213,
10723+213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
10724+213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
10725+213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
10726+213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,85,
10727+85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10728+85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10729+85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10730+85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,149,
10731+149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
10732+149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
10733+149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
10734+149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,21,
10735+21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
10736+21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
10737+21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
10738+21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,229,
10739+229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
10740+229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
10741+229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
10742+229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,101,
10743+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
10744+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
10745+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
10746+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,165,
10747+165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
10748+165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
10749+165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
10750+165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,37,
10751+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
10752+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
10753+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
10754+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,197,
10755+197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
10756+197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
10757+197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
10758+197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,69,
10759+69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
10760+69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
10761+69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
10762+69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,133,
10763+133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
10764+133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
10765+133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
10766+133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,5,
10767+5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
10768+5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
10769+5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
10770+5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,249,
10771+249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
10772+249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
10773+249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
10774+249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
10775+249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
10776+249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
10777+249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
10778+249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,121,
10779+121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
10780+121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
10781+121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
10782+121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
10783+121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
10784+121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
10785+121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
10786+121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,185,
10787+185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
10788+185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
10789+185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
10790+185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
10791+185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
10792+185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
10793+185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
10794+185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,57,
10795+57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
10796+57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
10797+57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
10798+57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
10799+57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
10800+57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
10801+57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
10802+57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,217,
10803+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
10804+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
10805+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
10806+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
10807+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
10808+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
10809+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
10810+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,89,
10811+89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
10812+89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
10813+89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
10814+89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
10815+89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
10816+89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
10817+89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
10818+89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,153,
10819+153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
10820+153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
10821+153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
10822+153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
10823+153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
10824+153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
10825+153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
10826+153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,25,
10827+25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
10828+25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
10829+25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
10830+25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
10831+25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
10832+25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
10833+25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
10834+25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,233,
10835+233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
10836+233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
10837+233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
10838+233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
10839+233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
10840+233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
10841+233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
10842+233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,105,
10843+105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
10844+105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
10845+105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
10846+105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
10847+105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
10848+105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
10849+105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
10850+105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,169,
10851+169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
10852+169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
10853+169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
10854+169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
10855+169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
10856+169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
10857+169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
10858+169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,41,
10859+41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
10860+41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
10861+41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
10862+41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
10863+41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
10864+41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
10865+41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
10866+41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,201,
10867+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
10868+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
10869+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
10870+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
10871+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
10872+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
10873+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
10874+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,73,
10875+73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
10876+73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
10877+73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
10878+73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
10879+73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
10880+73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
10881+73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
10882+73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,137,
10883+137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
10884+137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
10885+137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
10886+137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
10887+137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
10888+137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
10889+137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
10890+137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,9,
10891+9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
10892+9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
10893+9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
10894+9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
10895+9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
10896+9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
10897+9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
10898+9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,241,
10899+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10900+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10901+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10902+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10903+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10904+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10905+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10906+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10907+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10908+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10909+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10910+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10911+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10912+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10913+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10914+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,113,
10915+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10916+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10917+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10918+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10919+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10920+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10921+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10922+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10923+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10924+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10925+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10926+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10927+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10928+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10929+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10930+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,177,
10931+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10932+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10933+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10934+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10935+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10936+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10937+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10938+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10939+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10940+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10941+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10942+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10943+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10944+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10945+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10946+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,49,
10947+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10948+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10949+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10950+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10951+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10952+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10953+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10954+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10955+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10956+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10957+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10958+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10959+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10960+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10961+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10962+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,209,
10963+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10964+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10965+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10966+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10967+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10968+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10969+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10970+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10971+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10972+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10973+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10974+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10975+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10976+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10977+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10978+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,81,
10979+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10980+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10981+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10982+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10983+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10984+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10985+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10986+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10987+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10988+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10989+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10990+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10991+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10992+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10993+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10994+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,145,
10995+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10996+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10997+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10998+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10999+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11000+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11001+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11002+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11003+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11004+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11005+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11006+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11007+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11008+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11009+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11010+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,17,
11011+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11012+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11013+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11014+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11015+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11016+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11017+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11018+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11019+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11020+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11021+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11022+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11023+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11024+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11025+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11026+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,225,
11027+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11028+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11029+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11030+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11031+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11032+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11033+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11034+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11035+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11036+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11037+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11038+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11039+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11040+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11041+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11042+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,97,
11043+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11044+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11045+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11046+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11047+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11048+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11049+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11050+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11051+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11052+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11053+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11054+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11055+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11056+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11057+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11058+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,161,
11059+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11060+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11061+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11062+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11063+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11064+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11065+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11066+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11067+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11068+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11069+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11070+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11071+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11072+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11073+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11074+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,33,
11075+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11076+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11077+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11078+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11079+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11080+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11081+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11082+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11083+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11084+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11085+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11086+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11087+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11088+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11089+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11090+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,193,
11091+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11092+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11093+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11094+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11095+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11096+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11097+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11098+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11099+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11100+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11101+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11102+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11103+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11104+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11105+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11106+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,65,
11107+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11108+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11109+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11110+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11111+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11112+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11113+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11114+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11115+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11116+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11117+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11118+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11119+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11120+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11121+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11122+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,129,
11123+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11124+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11125+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11126+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11127+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11128+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11129+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11130+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11131+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11132+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11133+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11134+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11135+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11136+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11137+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11138+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,1,
11139+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11140+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11141+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11142+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11143+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11144+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11145+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11146+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11147+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11148+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11149+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11150+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11151+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11152+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11153+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11154+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11155+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11156+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11157+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11158+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11159+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11160+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11161+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11162+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11163+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11164+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11165+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11166+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11167+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11168+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11169+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11170+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11171+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11172+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11173+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11174+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11175+64,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11176+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11177+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11178+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11179+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11180+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11181+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11182+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11183+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11184+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11185+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11186+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11187+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11188+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11189+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11190+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11191+128,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11192+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11193+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11194+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11195+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11196+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11197+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11198+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11199+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11200+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11201+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11202+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11203+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11204+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11205+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11206+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11207+64,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11208+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11209+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11210+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11211+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11212+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11213+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11214+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11215+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11216+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11217+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11218+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11219+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11220+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11221+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11222+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11223+192,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11224+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11225+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11226+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11227+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11228+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11229+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11230+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11231+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11232+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11233+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11234+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11235+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11236+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11237+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11238+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11239+32,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11240+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11241+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11242+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11243+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11244+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11245+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11246+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11247+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11248+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11249+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11250+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11251+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11252+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11253+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11254+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11255+160,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11256+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11257+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11258+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11259+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11260+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11261+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11262+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11263+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11264+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11265+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11266+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11267+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11268+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11269+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11270+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11271+96,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11272+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11273+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11274+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11275+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11276+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11277+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11278+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11279+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11280+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11281+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11282+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11283+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11284+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11285+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11286+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11287+224,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11288+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11289+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11290+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11291+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11292+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11293+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11294+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11295+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11296+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11297+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11298+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11299+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11300+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11301+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11302+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11303+16,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11304+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11305+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11306+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11307+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11308+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11309+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11310+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11311+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11312+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11313+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11314+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11315+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11316+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11317+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11318+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11319+144,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11320+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11321+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11322+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11323+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11324+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11325+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11326+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11327+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11328+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11329+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11330+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11331+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11332+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11333+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11334+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11335+80,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11336+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11337+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11338+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11339+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11340+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11341+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11342+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11343+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11344+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11345+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11346+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11347+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11348+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11349+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11350+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11351+208,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11352+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11353+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11354+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11355+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11356+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11357+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11358+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11359+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11360+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11361+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11362+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11363+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11364+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11365+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11366+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11367+48,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11368+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11369+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11370+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11371+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11372+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11373+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11374+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11375+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11376+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11377+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11378+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11379+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11380+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11381+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11382+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11383+176,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11384+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11385+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11386+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11387+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11388+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11389+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11390+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11391+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11392+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11393+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11394+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11395+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11396+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11397+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11398+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11399+112,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11400+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11401+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11402+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11403+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11404+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11405+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11406+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11407+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11408+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11409+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11410+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11411+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11412+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11413+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11414+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11415+240,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
11416+8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
11417+8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
11418+8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
11419+8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
11420+8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
11421+8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
11422+8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
11423+8,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
11424+136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
11425+136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
11426+136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
11427+136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
11428+136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
11429+136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
11430+136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
11431+136,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
11432+72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
11433+72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
11434+72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
11435+72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
11436+72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
11437+72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
11438+72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
11439+72,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
11440+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
11441+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
11442+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
11443+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
11444+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
11445+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
11446+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
11447+200,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
11448+40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
11449+40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
11450+40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
11451+40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
11452+40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
11453+40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
11454+40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
11455+40,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
11456+168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
11457+168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
11458+168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
11459+168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
11460+168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
11461+168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
11462+168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
11463+168,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
11464+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
11465+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
11466+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
11467+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
11468+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
11469+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
11470+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
11471+104,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
11472+232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
11473+232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
11474+232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
11475+232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
11476+232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
11477+232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
11478+232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
11479+232,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
11480+24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
11481+24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
11482+24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
11483+24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
11484+24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
11485+24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
11486+24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
11487+24,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
11488+152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
11489+152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
11490+152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
11491+152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
11492+152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
11493+152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
11494+152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
11495+152,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11496+88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11497+88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11498+88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11499+88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11500+88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11501+88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11502+88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11503+88,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11504+216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11505+216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11506+216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11507+216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11508+216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11509+216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11510+216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11511+216,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11512+56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11513+56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11514+56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11515+56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11516+56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11517+56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11518+56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11519+56,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11520+184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11521+184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11522+184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11523+184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11524+184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11525+184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11526+184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11527+184,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11528+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11529+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11530+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11531+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11532+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11533+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11534+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11535+120,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11536+248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11537+248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11538+248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11539+248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11540+248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11541+248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11542+248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11543+248,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11544+4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11545+4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11546+4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11547+4,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11548+132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11549+132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11550+132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11551+132,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11552+68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11553+68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11554+68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11555+68,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11556+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11557+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11558+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11559+196,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11560+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11561+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11562+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11563+36,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11564+164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11565+164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11566+164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11567+164,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11568+100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11569+100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11570+100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11571+100,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11572+228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11573+228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11574+228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11575+228,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11576+20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11577+20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11578+20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11579+20,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11580+148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11581+148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11582+148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11583+148,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11584+84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11585+84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11586+84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11587+84,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11588+212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11589+212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11590+212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11591+212,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
11592+52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
11593+52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
11594+52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
11595+52,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
11596+180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
11597+180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
11598+180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
11599+180,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
11600+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
11601+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
11602+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
11603+116,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
11604+244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
11605+244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
11606+244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
11607+244,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
11608+12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
11609+12,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
11610+140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
11611+140,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
11612+76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
11613+76,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
11614+204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
11615+204,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
11616+44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
11617+44,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
11618+172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
11619+172,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
11620+108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
11621+108,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
11622+236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
11623+236,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
11624+28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
11625+28,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
11626+156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
11627+156,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
11628+92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
11629+92,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
11630+220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
11631+220,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
11632+60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
11633+60,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
11634+188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
11635+188,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
11636+124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
11637+124,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
11638+252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
11639+252,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
11640+2,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,
11641+130,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
11642+66,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,
11643+194,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
11644+34,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,
11645+162,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,
11646+98,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,
11647+226,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,
11648+18,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,
11649+146,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,
11650+82,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,
11651+210,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
11652+50,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,
11653+178,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
11654+114,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,
11655+242,10,10,10,10,10,10,10,10,138,138,138,138,138,138,138,
11656+138,74,74,74,74,74,74,74,74,202,202,202,202,202,202,202,
11657+202,42,42,42,42,42,42,42,42,170,170,170,170,170,170,170,
11658+170,106,106,106,106,106,106,106,106,234,234,234,234,234,234,234,
11659+234,26,26,26,26,26,26,26,26,154,154,154,154,154,154,154,
11660+154,90,90,90,90,90,90,90,90,218,218,218,218,218,218,218,
11661+218,58,58,58,58,58,58,58,58,186,186,186,186,186,186,186,
11662+186,122,122,122,122,122,122,122,122,250,250,250,250,250,250,250,
11663+250,6,6,6,6,134,134,134,134,70,70,70,70,198,198,198,
11664+198,38,38,38,38,166,166,166,166,102,102,102,102,230,230,230,
11665+230,22,22,22,22,150,150,150,150,86,86,86,86,214,214,214,
11666+214,54,54,54,54,182,182,182,182,118,118,118,118,246,246,246,
11667+246,14,14,142,142,78,78,206,206,46,46,174,174,110,110,238,
11668+238,30,30,158,158,94,94,222,222,62,62,190,190,126,126,254,
11669+};
11670+#else
11671+static short capiALAW2INT[] =
11672+{
11673+ 0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4,
11674+ 0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74,
11675+ 0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4,
11676+ 0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64,
11677+ 0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4,
11678+ 0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4,
11679+ 0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4,
11680+ 0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4,
11681+ 0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64,
11682+ 0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34,
11683+ 0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844,
11684+ 0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24,
11685+ 0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64,
11686+ 0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4,
11687+ 0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964,
11688+ 0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4,
11689+ 0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24,
11690+ 0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94,
11691+ 0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924,
11692+ 0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94,
11693+ 0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24,
11694+ 0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14,
11695+ 0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24,
11696+ 0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14,
11697+ 0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4,
11698+ 0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54,
11699+ 0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4,
11700+ 0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64,
11701+ 0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4,
11702+ 0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4,
11703+ 0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4,
11704+ 0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4
11705+};
11706+
11707+const unsigned char capiINT2ALAW[8192] = {
11708+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11709+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11710+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11711+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11712+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11713+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11714+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11715+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11716+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11717+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11718+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11719+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11720+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11721+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11722+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11723+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11724+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11725+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11726+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11727+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11728+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11729+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11730+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11731+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11732+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11733+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11734+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11735+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11736+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11737+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11738+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11739+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11740+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11741+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11742+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11743+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11744+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11745+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11746+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11747+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11748+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11749+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11750+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11751+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11752+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11753+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11754+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11755+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11756+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11757+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11758+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11759+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11760+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11761+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11762+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11763+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11764+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11765+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11766+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11767+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11768+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11769+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11770+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11771+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11772+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11773+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11774+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11775+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11776+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11777+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11778+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11779+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11780+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11781+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11782+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11783+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11784+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11785+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11786+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11787+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11788+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11789+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11790+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11791+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11792+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11793+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11794+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11795+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11796+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11797+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11798+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11799+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11800+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11801+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11802+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11803+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11804+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11805+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11806+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11807+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11808+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11809+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11810+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11811+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11812+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11813+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11814+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11815+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11816+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11817+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11818+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11819+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11820+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11821+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11822+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11823+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11824+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11825+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11826+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11827+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11828+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11829+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11830+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11831+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11832+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11833+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11834+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11835+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11836+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11837+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11838+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11839+ 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11840+ 212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11841+ 212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11842+ 212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11843+ 212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11844+ 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11845+ 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11846+ 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11847+ 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11848+ 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11849+ 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11850+ 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11851+ 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11852+ 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
11853+ 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
11854+ 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
11855+ 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
11856+ 244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
11857+ 244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
11858+ 244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
11859+ 244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
11860+ 52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
11861+ 52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
11862+ 52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
11863+ 52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
11864+ 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
11865+ 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
11866+ 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
11867+ 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
11868+ 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11869+ 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11870+ 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11871+ 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11872+ 196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11873+ 196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11874+ 196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11875+ 196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11876+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11877+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11878+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11879+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11880+ 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11881+ 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11882+ 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11883+ 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11884+ 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11885+ 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11886+ 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11887+ 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11888+ 228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11889+ 228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11890+ 228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11891+ 228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11892+ 36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11893+ 36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11894+ 36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11895+ 36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11896+ 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11897+ 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11898+ 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11899+ 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11900+ 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
11901+ 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
11902+ 220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
11903+ 220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
11904+ 28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
11905+ 28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
11906+ 156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
11907+ 156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
11908+ 124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
11909+ 124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
11910+ 252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
11911+ 252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
11912+ 60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
11913+ 60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
11914+ 188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
11915+ 188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
11916+ 76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
11917+ 76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
11918+ 204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
11919+ 204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
11920+ 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
11921+ 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
11922+ 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
11923+ 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
11924+ 108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
11925+ 108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
11926+ 236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
11927+ 236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
11928+ 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
11929+ 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
11930+ 172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
11931+ 172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
11932+ 80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11933+ 208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11934+ 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11935+ 144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11936+ 112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11937+ 240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11938+ 48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11939+ 176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11940+ 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11941+ 192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11942+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11943+ 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11944+ 96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11945+ 224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11946+ 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11947+ 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11948+ 88,88,88,88,88,88,88,88,216,216,216,216,216,216,216,216,
11949+ 24,24,24,24,24,24,24,24,152,152,152,152,152,152,152,152,
11950+ 120,120,120,120,120,120,120,120,248,248,248,248,248,248,248,248,
11951+ 56,56,56,56,56,56,56,56,184,184,184,184,184,184,184,184,
11952+ 72,72,72,72,72,72,72,72,200,200,200,200,200,200,200,200,
11953+ 8,8,8,8,8,8,8,8,136,136,136,136,136,136,136,136,
11954+ 104,104,104,104,104,104,104,104,232,232,232,232,232,232,232,232,
11955+ 40,40,40,40,40,40,40,40,168,168,168,168,168,168,168,168,
11956+ 86,86,86,86,214,214,214,214,22,22,22,22,150,150,150,150,
11957+ 118,118,118,118,246,246,246,246,54,54,54,54,182,182,182,182,
11958+ 70,70,70,70,198,198,198,198,6,6,6,6,134,134,134,134,
11959+ 102,102,102,102,230,230,230,230,38,38,38,38,166,166,166,166,
11960+ 94,94,222,222,30,30,158,158,126,126,254,254,62,62,190,190,
11961+ 78,78,206,206,14,14,142,142,110,110,238,238,46,46,174,174,
11962+ 82,210,18,146,114,242,50,178,66,194,2,130,98,226,34,162,
11963+ 90,218,26,154,122,250,58,186,74,202,10,138,106,234,42,170,
11964+ 171,43,235,107,139,11,203,75,187,59,251,123,155,27,219,91,
11965+ 163,35,227,99,131,3,195,67,179,51,243,115,147,19,211,83,
11966+ 175,175,47,47,239,239,111,111,143,143,15,15,207,207,79,79,
11967+ 191,191,63,63,255,255,127,127,159,159,31,31,223,223,95,95,
11968+ 167,167,167,167,39,39,39,39,231,231,231,231,103,103,103,103,
11969+ 135,135,135,135,7,7,7,7,199,199,199,199,71,71,71,71,
11970+ 183,183,183,183,55,55,55,55,247,247,247,247,119,119,119,119,
11971+ 151,151,151,151,23,23,23,23,215,215,215,215,87,87,87,87,
11972+ 169,169,169,169,169,169,169,169,41,41,41,41,41,41,41,41,
11973+ 233,233,233,233,233,233,233,233,105,105,105,105,105,105,105,105,
11974+ 137,137,137,137,137,137,137,137,9,9,9,9,9,9,9,9,
11975+ 201,201,201,201,201,201,201,201,73,73,73,73,73,73,73,73,
11976+ 185,185,185,185,185,185,185,185,57,57,57,57,57,57,57,57,
11977+ 249,249,249,249,249,249,249,249,121,121,121,121,121,121,121,121,
11978+ 153,153,153,153,153,153,153,153,25,25,25,25,25,25,25,25,
11979+ 217,217,217,217,217,217,217,217,89,89,89,89,89,89,89,89,
11980+ 161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11981+ 33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11982+ 225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11983+ 97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11984+ 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11985+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11986+ 193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11987+ 65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11988+ 177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
11989+ 49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
11990+ 241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
11991+ 113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
11992+ 145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11993+ 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11994+ 209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
11995+ 81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
11996+ 173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
11997+ 173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
11998+ 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,
11999+ 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,
12000+ 237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,
12001+ 237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,
12002+ 109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
12003+ 109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
12004+ 141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
12005+ 141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
12006+ 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
12007+ 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
12008+ 205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
12009+ 205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
12010+ 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
12011+ 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
12012+ 189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
12013+ 189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
12014+ 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,
12015+ 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,
12016+ 253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
12017+ 253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
12018+ 125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
12019+ 125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
12020+ 157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
12021+ 157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
12022+ 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,
12023+ 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,
12024+ 221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
12025+ 221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
12026+ 93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,
12027+ 93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,
12028+ 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
12029+ 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
12030+ 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
12031+ 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
12032+ 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
12033+ 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
12034+ 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
12035+ 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
12036+ 229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
12037+ 229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
12038+ 229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
12039+ 229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
12040+ 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
12041+ 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
12042+ 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
12043+ 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
12044+ 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
12045+ 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
12046+ 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
12047+ 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
12048+ 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
12049+ 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
12050+ 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
12051+ 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
12052+ 197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
12053+ 197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
12054+ 197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
12055+ 197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
12056+ 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
12057+ 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
12058+ 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
12059+ 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
12060+ 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
12061+ 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
12062+ 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
12063+ 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
12064+ 53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
12065+ 53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
12066+ 53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
12067+ 53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
12068+ 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
12069+ 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
12070+ 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
12071+ 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
12072+ 117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
12073+ 117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
12074+ 117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
12075+ 117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
12076+ 149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
12077+ 149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
12078+ 149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
12079+ 149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
12080+ 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
12081+ 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
12082+ 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
12083+ 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
12084+ 213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
12085+ 213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
12086+ 213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
12087+ 213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
12088+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12089+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12090+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12091+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12092+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12093+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12094+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12095+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12096+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12097+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12098+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12099+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12100+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12101+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12102+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12103+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12104+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12105+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12106+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12107+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12108+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12109+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12110+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12111+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12112+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12113+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12114+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12115+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12116+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12117+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12118+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12119+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12120+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12121+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12122+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12123+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12124+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12125+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12126+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12127+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12128+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12129+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12130+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12131+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12132+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12133+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12134+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12135+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12136+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12137+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12138+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12139+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12140+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12141+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12142+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12143+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12144+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12145+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12146+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12147+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12148+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12149+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12150+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12151+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12152+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12153+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12154+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12155+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12156+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12157+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12158+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12159+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12160+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12161+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12162+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12163+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12164+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12165+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12166+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12167+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12168+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12169+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12170+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12171+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12172+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12173+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12174+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12175+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12176+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12177+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12178+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12179+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12180+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12181+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12182+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12183+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12184+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12185+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12186+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12187+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12188+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12189+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12190+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12191+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12192+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12193+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12194+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12195+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12196+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12197+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12198+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12199+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12200+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12201+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12202+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12203+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12204+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12205+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12206+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12207+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12208+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12209+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12210+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12211+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12212+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12213+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12214+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12215+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12216+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12217+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12218+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12219+ 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85
12220+};
12221+
12222+#endif // CAPI_ULAW
12223+#endif
12224+
b684b13b
MT
12225diff -urN asterisk-1.2.9.1.orig/include/asterisk.h asterisk-1.2.9.1/include/asterisk.h
12226--- asterisk-1.2.9.1.orig/include/asterisk.h 2005-11-30 04:37:37.000000000 +0100
12227+++ asterisk-1.2.9.1/include/asterisk.h 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
12228@@ -36,6 +36,7 @@
12229 extern char ast_config_AST_PID[AST_CONFIG_MAX_PATH];
12230 extern char ast_config_AST_SOCKET[AST_CONFIG_MAX_PATH];
12231 extern char ast_config_AST_RUN_DIR[AST_CONFIG_MAX_PATH];
12232+extern char ast_config_AST_SYMBOLIC_NAME[20];
12233 extern char ast_config_AST_CTL_PERMISSIONS[AST_CONFIG_MAX_PATH];
12234 extern char ast_config_AST_CTL_OWNER[AST_CONFIG_MAX_PATH];
12235 extern char ast_config_AST_CTL_GROUP[AST_CONFIG_MAX_PATH];
b684b13b
MT
12236diff -urN asterisk-1.2.9.1.orig/manager.c asterisk-1.2.9.1/manager.c
12237--- asterisk-1.2.9.1.orig/manager.c 2006-02-11 19:15:00.000000000 +0100
12238+++ asterisk-1.2.9.1/manager.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
12239@@ -11,6 +11,9 @@
12240 * the project provides a web site, mailing lists and IRC
12241 * channels for your use.
12242 *
12243+ * Copyright (C) 2003-2004, Junghanns.NET Gmbh
12244+ * Klaus-Peter Junghanns <kpj@junghanns.net>
12245+ *
12246 * This program is free software, distributed under the terms of
12247 * the GNU General Public License Version 2. See the LICENSE file
12248 * at the top of the source tree.
12249@@ -62,6 +65,7 @@
12250 #include "asterisk/md5.h"
12251 #include "asterisk/acl.h"
12252 #include "asterisk/utils.h"
12253+#include "asterisk/astdb.h"
12254
12255 struct fast_originate_helper {
5f892677
MT
12256 char tech[AST_MAX_MANHEADER_LEN];
12257@@ -76,6 +80,8 @@
12258 char idtext[AST_MAX_MANHEADER_LEN];
12259 char account[AST_MAX_ACCOUNT_CODE];
5e69ef1a
MT
12260 int priority;
12261+ int callingpres;
12262+ char uniqueid[64];
12263 struct ast_variable *vars;
12264 };
12265
5f892677 12266@@ -657,11 +663,17 @@
5e69ef1a
MT
12267 {
12268 struct ast_channel *c = NULL;
12269 char *name = astman_get_header(m, "Channel");
12270- if (ast_strlen_zero(name)) {
12271- astman_send_error(s, m, "No channel specified");
12272+ char *uniqueid = astman_get_header(m, "Uniqueid");
12273+ if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
12274+ astman_send_error(s, m, "No channel or uniqueid specified");
12275 return 0;
12276 }
12277- c = ast_get_channel_by_name_locked(name);
12278+ if (!ast_strlen_zero(uniqueid)) {
12279+ c = ast_get_channel_by_uniqueid_locked(uniqueid);
12280+ } else {
12281+ if (!ast_strlen_zero(name))
12282+ c = ast_get_channel_by_name_locked(name);
12283+ }
12284 if (!c) {
12285 astman_send_error(s, m, "No such channel");
12286 return 0;
5f892677 12287@@ -760,6 +772,7 @@
5e69ef1a
MT
12288 }
12289
12290
12291+
12292 /*! \brief action_status: Manager "status" command to show channels */
12293 /* Needs documentation... */
12294 static int action_status(struct mansession *s, struct message *m)
5f892677 12295@@ -866,32 +879,50 @@
5e69ef1a
MT
12296 char *exten = astman_get_header(m, "Exten");
12297 char *context = astman_get_header(m, "Context");
12298 char *priority = astman_get_header(m, "Priority");
12299+ char *uniqueid = astman_get_header(m, "Uniqueid");
12300+ char *uniqueid2 = astman_get_header(m, "ExtraUniqueid");
12301+ char *exten2 = astman_get_header(m, "ExtraExten");
12302+ char *context2 = astman_get_header(m, "ExtraContext");
12303+ char *priority2 = astman_get_header(m, "ExtraPriority");
12304 struct ast_channel *chan, *chan2 = NULL;
12305 int pi = 0;
12306+ int pi2 = 0;
12307 int res;
12308
12309- if (ast_strlen_zero(name)) {
12310- astman_send_error(s, m, "Channel not specified");
12311+ if ((!name || ast_strlen_zero(name)) && (!uniqueid || ast_strlen_zero(uniqueid))) {
12312+ astman_send_error(s, m, "Channel or Uniqueid not specified");
12313 return 0;
12314 }
12315 if (!ast_strlen_zero(priority) && (sscanf(priority, "%d", &pi) != 1)) {
12316 astman_send_error(s, m, "Invalid priority\n");
12317 return 0;
12318 }
12319- chan = ast_get_channel_by_name_locked(name);
12320+ if (uniqueid && (!ast_strlen_zero(uniqueid))) {
12321+ chan = ast_get_channel_by_uniqueid_locked(uniqueid);
12322+ } else {
12323+ chan = ast_get_channel_by_name_locked(name);
12324+ }
12325 if (!chan) {
12326 char buf[BUFSIZ];
12327 snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
12328 astman_send_error(s, m, buf);
12329 return 0;
12330 }
12331- if (!ast_strlen_zero(name2))
12332+ if (!ast_strlen_zero(uniqueid2)) {
12333+ chan2 = ast_get_channel_by_uniqueid_locked(uniqueid2);
b684b13b 12334+ if (!ast_strlen_zero(priority2) && (sscanf(priority2, "%d", &pi2) != 1)) {
5e69ef1a
MT
12335+ astman_send_error(s, m, "Invalid priority2\n");
12336+ return 0;
12337+ }
12338+ } else {
12339+ if (!ast_strlen_zero(name2))
12340 chan2 = ast_get_channel_by_name_locked(name2);
12341+ }
12342 res = ast_async_goto(chan, context, exten, pi);
12343 if (!res) {
12344- if (!ast_strlen_zero(name2)) {
12345+ if ((!ast_strlen_zero(name2)) || (!ast_strlen_zero(uniqueid2))){
12346 if (chan2)
12347- res = ast_async_goto(chan2, context, exten, pi);
12348+ res = ast_async_goto(chan2, context2, exten2, pi2);
12349 else
12350 res = -1;
12351 if (!res)
5f892677 12352@@ -937,15 +968,15 @@
5e69ef1a
MT
12353 struct ast_channel *chan = NULL;
12354
12355 if (!ast_strlen_zero(in->app)) {
12356- res = ast_pbx_outgoing_app(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1,
12357+ res = ast_pbx_outgoing_app(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1, in->callingpres,
12358 !ast_strlen_zero(in->cid_num) ? in->cid_num : NULL,
12359 !ast_strlen_zero(in->cid_name) ? in->cid_name : NULL,
5f892677
MT
12360- in->vars, in->account, &chan);
12361+ in->vars, in->account, &chan, in->uniqueid);
5e69ef1a
MT
12362 } else {
12363- res = ast_pbx_outgoing_exten(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1,
12364+ res = ast_pbx_outgoing_exten(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1, in->callingpres,
12365 !ast_strlen_zero(in->cid_num) ? in->cid_num : NULL,
12366 !ast_strlen_zero(in->cid_name) ? in->cid_name : NULL,
5f892677
MT
12367- in->vars, in->account, &chan);
12368+ in->vars, in->account, &chan, in->uniqueid);
5e69ef1a
MT
12369 }
12370 if (!res)
12371 manager_event(EVENT_FLAG_CALL,
5f892677 12372@@ -956,7 +987,7 @@
5e69ef1a
MT
12373 "Exten: %s\r\n"
12374 "Reason: %d\r\n"
12375 "Uniqueid: %s\r\n",
12376- in->idtext, in->tech, in->data, in->context, in->exten, reason, chan ? chan->uniqueid : "<null>");
12377+ in->idtext, in->tech, in->data, in->context, in->exten, reason, in->uniqueid ? in->uniqueid : (chan ? chan->uniqueid : "<null>"));
12378 else
12379 manager_event(EVENT_FLAG_CALL,
12380 "OriginateFailure",
5f892677 12381@@ -966,7 +997,7 @@
5e69ef1a
MT
12382 "Exten: %s\r\n"
12383 "Reason: %d\r\n"
12384 "Uniqueid: %s\r\n",
12385- in->idtext, in->tech, in->data, in->context, in->exten, reason, chan ? chan->uniqueid : "<null>");
12386+ in->idtext, in->tech, in->data, in->context, in->exten, reason, in->uniqueid ? in->uniqueid : (chan ? chan->uniqueid : "<null>"));
12387
12388 /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */
12389 if (chan)
5f892677 12390@@ -999,6 +1030,7 @@
5e69ef1a
MT
12391 char *priority = astman_get_header(m, "Priority");
12392 char *timeout = astman_get_header(m, "Timeout");
12393 char *callerid = astman_get_header(m, "CallerID");
12394+ char *callingpres = astman_get_header(m, "CallingPres");
12395 char *account = astman_get_header(m, "Account");
12396 char *app = astman_get_header(m, "Application");
12397 char *appdata = astman_get_header(m, "Data");
5f892677 12398@@ -1007,12 +1039,15 @@
5e69ef1a
MT
12399 struct ast_variable *vars = astman_get_variables(m);
12400 char *tech, *data;
12401 char *l=NULL, *n=NULL;
12402+ char *uniqueid;
12403 int pi = 0;
12404+ int cpresi = 0;
12405 int res;
12406 int to = 30000;
12407 int reason = 0;
12408 char tmp[256];
12409 char tmp2[256];
12410+ char idText[256] = "";
12411
12412 pthread_t th;
12413 pthread_attr_t attr;
5f892677 12414@@ -1028,6 +1063,10 @@
5e69ef1a
MT
12415 astman_send_error(s, m, "Invalid timeout\n");
12416 return 0;
12417 }
12418+ if (!ast_strlen_zero(callingpres) && (sscanf(callingpres, "%d", &cpresi) != 1)) {
12419+ astman_send_error(s, m, "Invalid CallingPres\n");
12420+ return 0;
12421+ }
12422 ast_copy_string(tmp, name, sizeof(tmp));
12423 tech = tmp;
12424 data = strchr(tmp, '/');
5f892677
MT
12425@@ -1048,6 +1087,7 @@
12426 if (ast_strlen_zero(l))
12427 l = NULL;
5e69ef1a
MT
12428 }
12429+ uniqueid = ast_alloc_uniqueid();
12430 if (ast_true(async)) {
12431 struct fast_originate_helper *fast = malloc(sizeof(struct fast_originate_helper));
12432 if (!fast) {
5f892677 12433@@ -1068,8 +1108,10 @@
5e69ef1a
MT
12434 ast_copy_string(fast->context, context, sizeof(fast->context));
12435 ast_copy_string(fast->exten, exten, sizeof(fast->exten));
5f892677 12436 ast_copy_string(fast->account, account, sizeof(fast->account));
5e69ef1a
MT
12437+ ast_copy_string(fast->uniqueid, uniqueid, sizeof(fast->uniqueid));
12438 fast->timeout = to;
12439 fast->priority = pi;
12440+ fast->callingpres = cpresi;
12441 pthread_attr_init(&attr);
12442 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
12443 if (ast_pthread_create(&th, &attr, fast_originate, fast)) {
5f892677 12444@@ -1079,19 +1121,28 @@
5e69ef1a
MT
12445 }
12446 }
12447 } else if (!ast_strlen_zero(app)) {
5f892677
MT
12448- res = ast_pbx_outgoing_app(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
12449+ res = ast_pbx_outgoing_app(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, cpresi, l, n, vars, account, NULL, uniqueid);
5e69ef1a
MT
12450 } else {
12451 if (exten && context && pi)
5f892677
MT
12452- res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
12453+ res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, cpresi, l, n, vars, account, NULL, uniqueid);
5e69ef1a
MT
12454 else {
12455 astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
12456 return 0;
12457 }
12458 }
12459- if (!res)
12460- astman_send_ack(s, m, "Originate successfully queued");
12461- else
12462+ if (!res) {
12463+ if (id && !ast_strlen_zero(id)) {
5f892677 12464+ snprintf(idText,256,"ActionID: %s\r\n",id);
5e69ef1a
MT
12465+ }
12466+ ast_cli(s->fd, "Response: Success\r\n"
12467+ "%s"
12468+ "Message: Originate successfully queued\r\n"
12469+ "Uniqueid: %s\r\n"
12470+ "\r\n",
12471+ idText, uniqueid);
12472+ } else {
12473 astman_send_error(s, m, "Originate failed");
12474+ }
12475 return 0;
12476 }
12477
5f892677 12478@@ -1565,10 +1616,10 @@
5e69ef1a
MT
12479 return 0;
12480 }
12481
12482-static int manager_state_cb(char *context, char *exten, int state, void *data)
12483+static int manager_state_cb(char *context, char *exten, int state, void *data, char *cid_num, char *cid_name)
12484 {
12485 /* Notify managers of change */
12486- manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nStatus: %d\r\n", exten, context, state);
12487+ manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nStatus: %d\r\nCallerID: \"%s\" <%s>\r\n", exten, context, state, cid_num, cid_name);
12488 return 0;
12489 }
12490
b684b13b
MT
12491diff -urN asterisk-1.2.9.1.orig/pbx/pbx_spool.c asterisk-1.2.9.1/pbx/pbx_spool.c
12492--- asterisk-1.2.9.1.orig/pbx/pbx_spool.c 2006-02-11 19:15:00.000000000 +0100
12493+++ asterisk-1.2.9.1/pbx/pbx_spool.c 2006-06-09 10:25:04.000000000 +0200
5f892677 12494@@ -259,11 +259,11 @@
5e69ef1a
MT
12495 if (!ast_strlen_zero(o->app)) {
12496 if (option_verbose > 2)
12497 ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries);
5f892677
MT
12498- res = ast_pbx_outgoing_app(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
12499+ res = ast_pbx_outgoing_app(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, 0, o->cid_num, o->cid_name, o->vars, o->account, NULL, NULL);
5e69ef1a
MT
12500 } else {
12501 if (option_verbose > 2)
12502 ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries);
5f892677
MT
12503- res = ast_pbx_outgoing_exten(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
12504+ res = ast_pbx_outgoing_exten(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, 2 /* wait to finish */, 0, o->cid_num, o->cid_name, o->vars, o->account, NULL, NULL);
5e69ef1a
MT
12505 }
12506 if (res) {
12507 ast_log(LOG_NOTICE, "Call failed to go through, reason %d\n", reason);
b684b13b
MT
12508diff -urN asterisk-1.2.9.1.orig/pbx.c asterisk-1.2.9.1/pbx.c
12509--- asterisk-1.2.9.1.orig/pbx.c 2006-05-23 19:15:23.000000000 +0200
12510+++ asterisk-1.2.9.1/pbx.c 2006-06-09 10:25:04.000000000 +0200
5f892677 12511@@ -353,7 +353,8 @@
5e69ef1a
MT
12512
12513 { "Hangup", pbx_builtin_hangup,
12514 "Hang up the calling channel",
12515- " Hangup(): This application will hang up the calling channel.\n"
12516+ " Hangup(Cause): Unconditionally hangs up a given channel by returning -1 always.\n"
12517+ " If cause is given, it will set the hangup cause accordingly.\n"
12518 },
12519
12520 { "NoOp", pbx_builtin_noop,
b684b13b 12521@@ -1883,7 +1884,7 @@
5e69ef1a
MT
12522 return ast_extension_state2(e); /* Check all devices in the hint */
12523 }
12524
12525-void ast_hint_state_changed(const char *device)
5f892677 12526+void ast_hint_state_changed(const char *device, char *cid_num, char *cid_name)
5e69ef1a
MT
12527 {
12528 struct ast_hint *hint;
12529 struct ast_state_cb *cblist;
b684b13b 12530@@ -1911,11 +1912,11 @@
5e69ef1a
MT
12531
12532 /* For general callbacks */
12533 for (cblist = statecbs; cblist; cblist = cblist->next)
12534- cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
12535+ cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
12536
12537 /* For extension callbacks */
12538 for (cblist = hint->callbacks; cblist; cblist = cblist->next)
12539- cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
12540+ cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
12541
12542 hint->laststate = state;
12543 break;
b684b13b 12544@@ -2156,7 +2157,7 @@
5e69ef1a
MT
12545 /* Notify with -1 and remove all callbacks */
12546 cbprev = cblist;
12547 cblist = cblist->next;
12548- cbprev->callback(list->exten->parent->name, list->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
12549+ cbprev->callback(list->exten->parent->name, list->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data, NULL, NULL);
12550 free(cbprev);
12551 }
12552 list->callbacks = NULL;
b684b13b 12553@@ -3778,7 +3779,7 @@
5e69ef1a
MT
12554 while (thiscb) {
12555 prevcb = thiscb;
12556 thiscb = thiscb->next;
12557- prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data);
12558+ prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data, NULL, NULL);
12559 free(prevcb);
12560 }
12561 } else {
b684b13b 12562@@ -4980,7 +4981,7 @@
5e69ef1a
MT
12563 return 0; /* success */
12564 }
12565
5f892677
MT
12566-int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
12567+int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel, char *uniqueid)
5e69ef1a
MT
12568 {
12569 struct ast_channel *chan;
12570 struct async_stat *as;
b684b13b 12571@@ -4990,7 +4991,7 @@
5e69ef1a
MT
12572
12573 if (sync) {
12574 LOAD_OH(oh);
12575- chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
12576+ chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
12577 if (channel) {
12578 *channel = chan;
12579 if (chan)
b684b13b 12580@@ -5092,7 +5093,7 @@
5e69ef1a
MT
12581 goto outgoing_exten_cleanup;
12582 }
12583 memset(as, 0, sizeof(struct async_stat));
12584- chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
12585+ chan = ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, uniqueid);
12586 if (channel) {
12587 *channel = chan;
12588 if (chan)
b684b13b 12589@@ -5138,7 +5139,7 @@
5e69ef1a
MT
12590 pthread_t t;
12591 };
12592
12593-static void *ast_pbx_run_app(void *data)
12594+void *ast_pbx_run_app(void *data)
12595 {
12596 struct app_tmp *tmp = data;
12597 struct ast_app *app;
b684b13b 12598@@ -5154,7 +5155,7 @@
5e69ef1a
MT
12599 return NULL;
12600 }
12601
5f892677
MT
12602-int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
12603+int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid)
5e69ef1a
MT
12604 {
12605 struct ast_channel *chan;
12606 struct async_stat *as;
b684b13b 12607@@ -5174,7 +5175,7 @@
5e69ef1a
MT
12608 goto outgoing_app_cleanup;
12609 }
12610 if (sync) {
12611- chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
12612+ chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
12613 if (chan) {
12614 if (chan->cdr) { /* check if the channel already has a cdr record, if not give it one */
12615 ast_log(LOG_WARNING, "%s already has a call record??\n", chan->name);
b684b13b 12616@@ -5261,7 +5262,8 @@
5e69ef1a
MT
12617 goto outgoing_app_cleanup;
12618 }
12619 memset(as, 0, sizeof(struct async_stat));
12620- chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
12621+ chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
12622+// chan = ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, uniqueid);
12623 if (!chan) {
12624 free(as);
12625 res = -1;
b684b13b 12626@@ -5548,6 +5550,9 @@
5e69ef1a
MT
12627 */
12628 static int pbx_builtin_hangup(struct ast_channel *chan, void *data)
12629 {
12630+ /* Copy the hangup cause as specified */
12631+ if (data)
12632+ chan->hangupcause = atoi(data);
12633 /* Just return non-zero and it will hang up */
12634 if (!chan->hangupcause)
12635 chan->hangupcause = AST_CAUSE_NORMAL_CLEARING;
b684b13b 12636@@ -6204,6 +6209,9 @@
5e69ef1a
MT
12637 return -1;
12638 }
12639 }
12640+ if (chan->_state != AST_STATE_UP) {
12641+ ast_answer(chan);
12642+ }
12643 return res = ast_say_number(chan, atoi((char *) tmp), "", chan->language, options);
12644 }
12645
b684b13b 12646@@ -6211,8 +6219,12 @@
5e69ef1a
MT
12647 {
12648 int res = 0;
12649
12650- if (data)
12651+ if (data) {
12652+ if (chan->_state != AST_STATE_UP) {
12653+ ast_answer(chan);
12654+ }
12655 res = ast_say_digit_str(chan, (char *)data, "", chan->language);
12656+ }
12657 return res;
12658 }
12659
b684b13b 12660@@ -6220,8 +6232,12 @@
5e69ef1a
MT
12661 {
12662 int res = 0;
12663
12664- if (data)
12665+ if (data) {
12666+ if (chan->_state != AST_STATE_UP) {
12667+ ast_answer(chan);
12668+ }
12669 res = ast_say_character_str(chan, (char *)data, "", chan->language);
12670+ }
12671 return res;
12672 }
12673
b684b13b 12674@@ -6229,8 +6245,12 @@
5e69ef1a
MT
12675 {
12676 int res = 0;
12677
12678- if (data)
12679+ if (data) {
12680+ if (chan->_state != AST_STATE_UP) {
12681+ ast_answer(chan);
12682+ }
12683 res = ast_say_phonetic_str(chan, (char *)data, "", chan->language);
12684+ }
12685 return res;
12686 }
12687
b684b13b
MT
12688diff -urN asterisk-1.2.9.1.orig/res/Makefile asterisk-1.2.9.1/res/Makefile
12689--- asterisk-1.2.9.1.orig/res/Makefile 2005-11-29 19:24:39.000000000 +0100
12690+++ asterisk-1.2.9.1/res/Makefile 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
12691@@ -11,7 +11,7 @@
12692 # the GNU General Public License
12693 #
12694
12695-MODS=res_indications.so res_monitor.so res_adsi.so res_agi.so res_features.so
12696+MODS=res_indications.so res_monitor.so res_adsi.so res_agi.so res_features.so res_watchdog.so
12697
12698 ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/odbcinst.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/odbcinst.h),)
12699 ifneq (${OSARCH},FreeBSD)
b684b13b
MT
12700diff -urN asterisk-1.2.9.1.orig/res/res_agi.c asterisk-1.2.9.1/res/res_agi.c
12701--- asterisk-1.2.9.1.orig/res/res_agi.c 2006-06-01 01:50:00.000000000 +0200
12702+++ asterisk-1.2.9.1/res/res_agi.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
12703@@ -11,6 +11,9 @@
12704 * the project provides a web site, mailing lists and IRC
12705 * channels for your use.
12706 *
12707+ * Copyright (C) 2005 Junghanns.NET GmbH
12708+ * Klaus-Peter Junghanns <kpj@junghanns.net>
12709+ *
12710 * This program is free software, distributed under the terms of
12711 * the GNU General Public License Version 2. See the LICENSE file
12712 * at the top of the source tree.
12713@@ -74,16 +77,19 @@
12714
12715 static char *app = "AGI";
12716
12717+static char *xapp = "XAGI";
12718+
12719 static char *eapp = "EAGI";
12720
12721 static char *deadapp = "DeadAGI";
12722
12723 static char *synopsis = "Executes an AGI compliant application";
12724+static char *xsynopsis = "Executes an XAGI compliant application";
12725 static char *esynopsis = "Executes an EAGI compliant application";
12726 static char *deadsynopsis = "Executes AGI on a hungup channel";
12727
12728 static char *descrip =
12729-" [E|Dead]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
12730+" [E|Dead|X]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
12731 "program on a channel. AGI allows Asterisk to launch external programs\n"
12732 "written in any language to control a telephony channel, play audio,\n"
12733 "read DTMF digits, etc. by communicating with the AGI protocol on stdin\n"
5f892677 12734@@ -92,6 +98,8 @@
5e69ef1a 12735 " hangup, or 0 on non-hangup exit. \n"
5f892677
MT
12736 "Using 'EAGI' provides enhanced AGI, with incoming audio available out of band\n"
12737 "on file descriptor 3\n\n"
5e69ef1a
MT
12738+"Using 'XAGI' provides enhanced AGI, with incoming audio available out of band"
12739+" on file descriptor 3 and outgoing audio available out of band on file descriptor 4\n\n"
12740 "Use the CLI command 'show agi' to list available agi commands\n";
12741
12742 static int agidebug = 0;
b684b13b 12743@@ -225,13 +233,14 @@
5e69ef1a
MT
12744 return 0;
12745 }
12746
12747-static int launch_script(char *script, char *argv[], int *fds, int *efd, int *opid)
12748+static int launch_script(char *script, char *argv[], int *fds, int *efd, int *efd2, int *opid)
12749 {
12750 char tmp[256];
12751 int pid;
12752 int toast[2];
12753 int fromast[2];
12754 int audio[2];
12755+ int audio2[2];
12756 int x;
12757 int res;
12758 sigset_t signal_set;
b684b13b 12759@@ -276,6 +285,33 @@
5e69ef1a
MT
12760 return -1;
12761 }
12762 }
12763+ if (efd2) {
12764+ if (pipe(audio2)) {
12765+ ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
12766+ close(fromast[0]);
12767+ close(fromast[1]);
12768+ close(toast[0]);
12769+ close(toast[1]);
12770+ close(audio[0]);
12771+ close(audio[1]);
12772+ return -1;
12773+ }
12774+ res = fcntl(audio2[0], F_GETFL);
12775+ if (res > -1)
12776+ res = fcntl(audio2[0], F_SETFL, res | O_NONBLOCK);
12777+ if (res < 0) {
12778+ ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
12779+ close(fromast[0]);
12780+ close(fromast[1]);
12781+ close(toast[0]);
12782+ close(toast[1]);
12783+ close(audio[0]);
12784+ close(audio[1]);
12785+ close(audio2[0]);
12786+ close(audio2[1]);
12787+ return -1;
12788+ }
12789+ }
12790 pid = fork();
12791 if (pid < 0) {
12792 ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
b684b13b 12793@@ -290,15 +326,19 @@
5e69ef1a
MT
12794 } else {
12795 close(STDERR_FILENO + 1);
12796 }
12797+ if (efd2) {
12798+ dup2(audio2[1], STDERR_FILENO + 2);
12799+ } else {
12800+ close(STDERR_FILENO + 2);
12801+ }
12802
12803 /* unblock important signal handlers */
12804 if (sigfillset(&signal_set) || pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
12805 ast_log(LOG_WARNING, "unable to unblock signals for AGI script: %s\n", strerror(errno));
12806 exit(1);
12807 }
12808-
12809 /* Close everything but stdin/out/error */
12810- for (x=STDERR_FILENO + 2;x<1024;x++)
12811+ for (x=STDERR_FILENO + 3;x<1024;x++)
12812 close(x);
12813
12814 /* Don't run AGI scripts with realtime priority -- it causes audio stutter */
b684b13b 12815@@ -317,6 +357,9 @@
5e69ef1a
MT
12816 if (efd) {
12817 *efd = audio[1];
12818 }
12819+ if (efd2) {
12820+ *efd2 = audio2[0];
12821+ }
12822 /* close what we're not using in the parent */
12823 close(toast[1]);
12824 close(fromast[0]);
b684b13b 12825@@ -325,6 +368,9 @@
5e69ef1a
MT
12826 /* [PHM 12/18/03] */
12827 close(audio[0]);
12828 }
12829+ if (efd2) {
12830+ close(audio2[1]);
12831+ }
12832
12833 *opid = pid;
12834 return 0;
b684b13b 12835@@ -355,7 +401,7 @@
5e69ef1a
MT
12836 fdprintf(fd, "agi_context: %s\n", chan->context);
12837 fdprintf(fd, "agi_extension: %s\n", chan->exten);
12838 fdprintf(fd, "agi_priority: %d\n", chan->priority);
12839- fdprintf(fd, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
12840+ fdprintf(fd, "agi_enhanced: %d%s\n", enhanced, ".0");
12841
12842 /* User information */
12843 fdprintf(fd, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
b684b13b 12844@@ -387,7 +433,7 @@
5e69ef1a
MT
12845 return RESULT_SHOWUSAGE;
12846 if (sscanf(argv[3], "%d", &to) != 1)
12847 return RESULT_SHOWUSAGE;
12848- res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl);
12849+ res = ast_waitfordigit_full(chan, to, agi->audio_out, agi->ctrl);
12850 fdprintf(agi->fd, "200 result=%d\n", res);
12851 if (res >= 0)
12852 return RESULT_SUCCESS;
b684b13b 12853@@ -563,7 +609,7 @@
5e69ef1a
MT
12854 else
12855 return RESULT_FAILURE;
12856 }
12857- res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
12858+ res = ast_waitstream_full(chan, argv[3], agi->audio_out, agi->ctrl);
12859 /* this is to check for if ast_waitstream closed the stream, we probably are at
12860 * the end of the stream, return that amount, else check for the amount */
12861 sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length;
b684b13b 12862@@ -623,7 +669,7 @@
5e69ef1a
MT
12863 else
12864 return RESULT_FAILURE;
12865 }
12866- res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
12867+ res = ast_waitstream_full(chan, argv[3], agi->audio_out, agi->ctrl);
12868 /* this is to check for if ast_waitstream closed the stream, we probably are at
12869 * the end of the stream, return that amount, else check for the amount */
12870 sample_offset = (chan->stream)?ast_tellstream(fs):max_length;
b684b13b 12871@@ -635,7 +681,7 @@
5e69ef1a
MT
12872
12873 /* If the user didnt press a key, wait for digitTimeout*/
12874 if (res == 0 ) {
12875- res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl);
12876+ res = ast_waitfordigit_full(chan, timeout, agi->audio_out, agi->ctrl);
12877 /* Make sure the new result is in the escape digits of the GET OPTION */
12878 if ( !strchr(edigits,res) )
12879 res=0;
b684b13b 12880@@ -662,7 +708,7 @@
5e69ef1a
MT
12881 return RESULT_SHOWUSAGE;
12882 if (sscanf(argv[2], "%d", &num) != 1)
12883 return RESULT_SHOWUSAGE;
12884- res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio, agi->ctrl);
12885+ res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio_out, agi->ctrl);
12886 if (res == 1)
12887 return RESULT_SUCCESS;
12888 fdprintf(agi->fd, "200 result=%d\n", res);
b684b13b 12889@@ -682,7 +728,7 @@
5e69ef1a
MT
12890 if (sscanf(argv[2], "%d", &num) != 1)
12891 return RESULT_SHOWUSAGE;
12892
12893- res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
12894+ res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio_out, agi->ctrl);
12895 if (res == 1) /* New command */
12896 return RESULT_SUCCESS;
12897 fdprintf(agi->fd, "200 result=%d\n", res);
b684b13b 12898@@ -699,7 +745,7 @@
5e69ef1a
MT
12899 if (argc != 4)
12900 return RESULT_SHOWUSAGE;
12901
12902- res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
12903+ res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio_out, agi->ctrl);
12904 if (res == 1) /* New command */
12905 return RESULT_SUCCESS;
12906 fdprintf(agi->fd, "200 result=%d\n", res);
b684b13b 12907@@ -789,7 +835,7 @@
5e69ef1a
MT
12908 if (argc != 4)
12909 return RESULT_SHOWUSAGE;
12910
12911- res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
12912+ res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio_out, agi->ctrl);
12913 if (res == 1) /* New command */
12914 return RESULT_SUCCESS;
12915 fdprintf(agi->fd, "200 result=%d\n", res);
b684b13b 12916@@ -816,7 +862,7 @@
5e69ef1a
MT
12917 max = atoi(argv[4]);
12918 else
12919 max = 1024;
12920- res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl);
12921+ res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio_out, agi->ctrl);
12922 if (res == 2) /* New command */
12923 return RESULT_SUCCESS;
12924 else if (res == 1)
b684b13b 12925@@ -1860,7 +1906,12 @@
5e69ef1a
MT
12926 int ms;
12927 int returnstatus = 0;
12928 struct ast_frame *f;
12929+ struct ast_frame fr;
12930 char buf[2048];
12931+ char audiobuf[2048];
12932+ int audiobytes;
12933+ int fds[2];
12934+ int enhanced = 0;
12935 FILE *readf;
12936 /* how many times we'll retry if ast_waitfor_nandfs will return without either
12937 channel or file descriptor in case select is interrupted by a system call (EINTR) */
b684b13b 12938@@ -1874,10 +1925,22 @@
5e69ef1a
MT
12939 return -1;
12940 }
12941 setlinebuf(readf);
12942- setup_env(chan, request, agi->fd, (agi->audio > -1));
12943+ if (agi->audio_out > -1) {
12944+ enhanced = 1;
12945+ }
12946+ if (agi->audio_in > -1) {
12947+ enhanced++;
12948+ }
12949+ setup_env(chan, request, agi->fd, enhanced);
12950+ fds[0] = agi->ctrl;
12951+ fds[1] = agi->audio_in;
12952 for (;;) {
12953 ms = -1;
12954- c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
12955+ if (agi->audio_in > -1) {
12956+ c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, fds, 2, NULL, &outfd, &ms);
12957+ } else {
12958+ c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
12959+ }
12960 if (c) {
12961 retry = RETRY;
12962 /* Idle the channel until we get a command */
b684b13b 12963@@ -1888,13 +1951,24 @@
5e69ef1a
MT
12964 break;
12965 } else {
12966 /* If it's voice, write it to the audio pipe */
12967- if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) {
12968+ if ((agi->audio_out > -1) && (f->frametype == AST_FRAME_VOICE)) {
12969 /* Write, ignoring errors */
12970- write(agi->audio, f->data, f->datalen);
12971+ write(agi->audio_out, f->data, f->datalen);
12972 }
12973 ast_frfree(f);
12974 }
12975 } else if (outfd > -1) {
12976+ if ((agi->audio_in > -1) && (outfd == agi->audio_in)) {
12977+ audiobytes = read(agi->audio_in, audiobuf, sizeof(audiobuf));
12978+ if (audiobytes > 0) {
12979+ // ast_log(LOG_NOTICE, "read %d bytes of audio\n", audiobytes);
12980+ fr.frametype = AST_FRAME_VOICE;
12981+ fr.subclass = AST_FORMAT_SLINEAR;
12982+ fr.datalen = audiobytes;
12983+ fr.data = audiobuf;
12984+ ast_write(chan, &fr);
12985+ }
12986+ } else {
12987 retry = RETRY;
12988 if (!fgets(buf, sizeof(buf), readf)) {
12989 /* Program terminated */
b684b13b 12990@@ -1916,6 +1990,7 @@
5e69ef1a
MT
12991 if ((returnstatus < 0) || (returnstatus == AST_PBX_KEEPALIVE)) {
12992 break;
12993 }
12994+ }
12995 } else {
12996 if (--retry <= 0) {
12997 ast_log(LOG_WARNING, "No channel, no fd?\n");
b684b13b 12998@@ -2022,6 +2097,7 @@
5e69ef1a
MT
12999 int argc = 0;
13000 int fds[2];
13001 int efd = -1;
13002+ int efd2 = -1;
13003 int pid;
13004 char *stringp;
13005 AGI agi;
b684b13b 13006@@ -2047,15 +2123,18 @@
5e69ef1a
MT
13007 }
13008 }
13009 #endif
13010- res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, &pid);
13011+ res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, (enhanced == 2) ? &efd2 : NULL, &pid);
13012 if (!res) {
13013 agi.fd = fds[1];
13014 agi.ctrl = fds[0];
13015- agi.audio = efd;
13016+ agi.audio_out = efd;
13017+ agi.audio_in = efd2;
13018 res = run_agi(chan, argv[0], &agi, pid, dead);
13019 close(fds[1]);
13020 if (efd > -1)
13021 close(efd);
13022+ if (efd2 > -1)
13023+ close(efd2);
13024 }
13025 LOCAL_USER_REMOVE(u);
13026 return res;
b684b13b 13027@@ -2089,6 +2168,35 @@
5e69ef1a
MT
13028 return res;
13029 }
13030
13031+static int xagi_exec(struct ast_channel *chan, void *data)
13032+{
13033+ int readformat, writeformat;
13034+ int res;
13035+
13036+ if (chan->_softhangup)
13037+ ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
13038+ readformat = chan->readformat;
13039+ if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
13040+ ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
13041+ return -1;
13042+ }
13043+ writeformat = chan->writeformat;
13044+ if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
13045+ ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
13046+ return -1;
13047+ }
13048+ res = agi_exec_full(chan, data, 2, 0);
13049+ if (!res) {
13050+ if (ast_set_read_format(chan, readformat)) {
13051+ ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat));
13052+ }
13053+ if (ast_set_write_format(chan, writeformat)) {
13054+ ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(writeformat));
13055+ }
13056+ }
13057+ return res;
13058+}
13059+
13060 static int deadagi_exec(struct ast_channel *chan, void *data)
13061 {
13062 return agi_exec_full(chan, data, 0, 1);
b684b13b 13063@@ -2118,6 +2226,7 @@
5e69ef1a
MT
13064 ast_cli_unregister(&dumpagihtml);
13065 ast_cli_unregister(&cli_debug);
13066 ast_cli_unregister(&cli_no_debug);
13067+ ast_unregister_application(xapp);
13068 ast_unregister_application(eapp);
13069 ast_unregister_application(deadapp);
13070 return ast_unregister_application(app);
b684b13b 13071@@ -2131,6 +2240,7 @@
5e69ef1a
MT
13072 ast_cli_register(&cli_no_debug);
13073 ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
13074 ast_register_application(eapp, eagi_exec, esynopsis, descrip);
13075+ ast_register_application(xapp, xagi_exec, xsynopsis, descrip);
13076 return ast_register_application(app, agi_exec, synopsis, descrip);
13077 }
13078
b684b13b
MT
13079diff -urN asterisk-1.2.9.1.orig/res/res_features.c asterisk-1.2.9.1/res/res_features.c
13080--- asterisk-1.2.9.1.orig/res/res_features.c 2006-05-23 19:15:23.000000000 +0200
13081+++ asterisk-1.2.9.1/res/res_features.c 2006-06-09 10:25:04.000000000 +0200
5e69ef1a
MT
13082@@ -11,6 +11,10 @@
13083 * the project provides a web site, mailing lists and IRC
13084 * channels for your use.
13085 *
13086+ * Copyright (C) 2004, Junghanns.NET GmbH
13087+ *
13088+ * Klaus-Peter Junghanns <kpj@junghanns.net>
13089+ *
13090 * This program is free software, distributed under the terms of
13091 * the GNU General Public License Version 2. See the LICENSE file
13092 * at the top of the source tree.
13093@@ -56,6 +60,7 @@
13094 #include "asterisk/utils.h"
13095 #include "asterisk/adsi.h"
13096 #include "asterisk/monitor.h"
13097+#include "asterisk/indications.h"
13098
13099 #ifdef __AST_DEBUG_MALLOC
13100 static void FREE(void *ptr)
13101@@ -73,6 +78,7 @@
13102 #define AST_MAX_WATCHERS 256
13103
13104 static char *parkedcall = "ParkedCall";
13105+static char *holdedcall = "HoldedCall";
13106
13107 /* No more than 45 seconds parked before you do something with them */
13108 static int parkingtime = DEFAULT_PARK_TIME;
13109@@ -132,6 +138,20 @@
13110 "into the dialplan, although you should include the 'parkedcalls'\n"
13111 "context.\n";
13112
13113+static char *autoanswerlogin = "AutoanswerLogin";
13114+
13115+static char *synopsis3 = "Log in for autoanswer";
13116+
13117+static char *descrip3 = "AutoanswerLogin(exten):"
13118+"Used to login to the autoanswer application for an extension.\n";
13119+
13120+static char *autoanswer = "Autoanswer";
13121+
13122+static char *synopsis4 = "Autoanswer a call";
13123+
13124+static char *descrip4 = "Autoanswer(exten):"
13125+"Used to autoanswer a call for an extension.\n";
13126+
13127 static struct ast_app *monitor_app=NULL;
13128 static int monitor_ok=1;
13129
13130@@ -150,12 +170,51 @@
13131 struct parkeduser *next;
13132 };
13133
13134+struct holdeduser {
13135+ struct ast_channel *chan;
13136+ struct timeval start;
13137+ int parkingnum;
13138+ int cref;
13139+ int tei;
13140+ /* Where to go if our parking time expires */
13141+ char context[AST_MAX_EXTENSION];
13142+ char exten[AST_MAX_EXTENSION];
13143+ int priority;
13144+ int parkingtime;
13145+ char uniqueid[AST_MAX_UNIQUEID];
13146+ char uniqueidpeer[AST_MAX_UNIQUEID];
13147+ struct holdeduser *next;
13148+};
13149+
13150+/* auto answer user */
13151+struct aauser {
13152+ struct ast_channel *chan;
13153+ struct timeval start;
13154+ /* waiting on this extension/context */
13155+ char exten[AST_MAX_EXTENSION];
13156+ char context[AST_MAX_EXTENSION];
13157+ int priority;
13158+ int notquiteyet;
13159+ struct aauser *next;
13160+};
13161+
13162+
13163+static struct aauser *aalot;
13164+AST_MUTEX_DEFINE_STATIC(autoanswer_lock);
13165+static pthread_t autoanswer_thread;
13166+
13167 static struct parkeduser *parkinglot;
13168
13169+static struct holdeduser *holdlist;
13170+
13171 AST_MUTEX_DEFINE_STATIC(parking_lock);
13172
13173+AST_MUTEX_DEFINE_STATIC(holding_lock);
13174+
13175 static pthread_t parking_thread;
13176
13177+static pthread_t holding_thread;
13178+
13179 STANDARD_LOCAL_USER;
13180
13181 LOCAL_USER_DECL;
13182@@ -165,6 +224,12 @@
13183 return parking_ext;
13184 }
13185
13186+char *ast_parking_con(void)
13187+{
13188+ return parking_con;
13189+}
13190+
13191+
13192 char *ast_pickup_ext(void)
13193 {
13194 return pickup_ext;
13195@@ -362,10 +427,11 @@
13196 "Timeout: %ld\r\n"
13197 "CallerID: %s\r\n"
13198 "CallerIDName: %s\r\n"
13199+ "Unqiueid: %s\r\n\r\n"
5f892677 13200 ,pu->parkingnum, pu->chan->name, peer ? peer->name : ""
5e69ef1a
MT
13201 ,(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL)
13202 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
13203- ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
13204+ ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
13205 );
13206
13207 if (peer) {
13208@@ -418,7 +484,8 @@
13209 ast_copy_string(chan->context, rchan->context, sizeof(chan->context));
13210 ast_copy_string(chan->exten, rchan->exten, sizeof(chan->exten));
13211 chan->priority = rchan->priority;
13212-
13213+ /* might be dirty but we want trackable channels */
13214+ strncpy(chan->uniqueid, rchan->uniqueid, sizeof(chan->uniqueid) - 1);
13215 /* Make the masq execute */
13216 f = ast_read(chan);
13217 if (f)
13218@@ -906,7 +973,7 @@
13219 }
13220
13221 /* find a feature by name */
13222-static struct ast_call_feature *find_feature(char *name)
13223+struct ast_call_feature *ast_find_feature(char *name)
13224 {
13225 struct ast_call_feature *tmp;
13226
13227@@ -916,10 +983,21 @@
13228 break;
13229 }
13230 AST_LIST_UNLOCK(&feature_list);
13231-
13232 return tmp;
13233 }
13234
13235+struct ast_call_feature *ast_find_builtin_feature(char *name)
13236+{
13237+ int x = 0;
13238+
13239+ for (x = 0; x < FEATURES_COUNT; x++) {
13240+ if (!strcasecmp(name, builtin_features[x].sname)) {
13241+ return &builtin_features[x];
13242+ }
13243+ }
13244+ return NULL;
13245+}
13246+
13247 /* exec an app by feature */
13248 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
13249 {
b684b13b 13250@@ -1018,7 +1096,7 @@
5e69ef1a
MT
13251 return res;
13252
13253 while ((tok = strsep(&tmp, "#")) != NULL) {
13254- feature = find_feature(tok);
13255+ feature = ast_find_feature(tok);
13256
13257 if (feature) {
13258 /* Feature is up for consideration */
b684b13b 13259@@ -1071,7 +1149,7 @@
5e69ef1a
MT
13260
13261 /* while we have a feature */
13262 while (NULL != (tok = strsep(&tmp, "#"))) {
13263- if ((feature = find_feature(tok))) {
13264+ if ((feature = ast_find_feature(tok))) {
13265 if (ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
13266 if (ast_test_flag(feature, AST_FEATURE_FLAG_CALLER))
13267 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
b684b13b 13268@@ -1096,7 +1174,7 @@
5e69ef1a
MT
13269 struct ast_frame *f = NULL;
13270 int res = 0, ready = 0;
13271
13272- if ((chan = ast_request(type, format, data, &cause))) {
13273+ if ((chan = ast_request(type, format, data, &cause, NULL))) {
13274 ast_set_callerid(chan, cid_num, cid_name, cid_num);
13275 ast_channel_inherit_variables(caller, chan);
13276 if (!ast_call(chan, data, timeout)) {
b684b13b 13277@@ -1549,9 +1627,10 @@
5e69ef1a
MT
13278 "Channel: %s\r\n"
13279 "CallerID: %s\r\n"
13280 "CallerIDName: %s\r\n"
13281+ "Uniqueid: %s\r\n\r\n"
13282 ,pu->parkingnum, pu->chan->name
13283 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
13284- ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
13285+ ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
13286 );
13287
13288 if (option_verbose > 1)
b684b13b 13289@@ -1594,9 +1673,10 @@
5e69ef1a
MT
13290 "Channel: %s\r\n"
13291 "CallerID: %s\r\n"
13292 "CallerIDName: %s\r\n"
13293+ "Uniqueid: %s\r\n\r\n"
13294 ,pu->parkingnum, pu->chan->name
13295 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
13296- ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
13297+ ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
13298 );
13299
13300 /* There's a problem, hang them up*/
b684b13b 13301@@ -1683,6 +1763,280 @@
5e69ef1a
MT
13302 return res;
13303 }
13304
13305+int ast_hold_call(struct ast_channel *chan, struct ast_channel *peer)
13306+{
13307+ /* We put the user in the parking list, then wake up the parking thread to be sure it looks
13308+ after these channels too */
13309+ struct holdeduser *pu;
13310+ pu = malloc(sizeof(struct holdeduser));
13311+ if (pu) {
13312+ memset(pu, 0, sizeof(pu));
13313+ ast_mutex_lock(&holding_lock);
13314+ chan->appl = "Holded Call";
13315+ chan->data = NULL;
13316+
13317+ pu->chan = chan;
13318+ strncpy(pu->uniqueid, chan->uniqueid, sizeof(pu->uniqueid));
13319+ strncpy(pu->uniqueidpeer, peer->uniqueid, sizeof(pu->uniqueidpeer));
13320+ /* Start music on hold */
13321+ ast_moh_start(pu->chan, NULL);
13322+ gettimeofday(&pu->start, NULL);
13323+ pu->next = holdlist;
13324+ holdlist = pu;
13325+ ast_mutex_unlock(&holding_lock);
13326+ /* Wake up the (presumably select()ing) thread */
13327+ pthread_kill(holding_thread, SIGURG);
13328+
13329+ manager_event(EVENT_FLAG_CALL, "HoldedCall",
13330+ "Channel1: %s\r\n"
13331+ "Channel2: %s\r\n"
13332+ "Uniqueid1: %s\r\n"
13333+ "Uniqueid2: %s\r\n"
13334+ ,pu->chan->name, peer->name, pu->chan->uniqueid, peer->uniqueid);
13335+
13336+ } else {
13337+ ast_log(LOG_WARNING, "Out of memory\n");
13338+ return -1;
13339+ }
13340+ return 0;
13341+}
13342+
13343+int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *peer)
13344+{
13345+ struct ast_channel *chan;
13346+ struct ast_frame *f;
13347+ /* Make a new, fake channel that we'll use to masquerade in the real one */
13348+ chan = ast_channel_alloc(0);
13349+ if (chan) {
13350+ /* Let us keep track of the channel name */
13351+ snprintf(chan->name, sizeof (chan->name), "Onhold/%s",rchan->name);
13352+ /* Make formats okay */
13353+ chan->readformat = rchan->readformat;
13354+ chan->writeformat = rchan->writeformat;
13355+ ast_channel_masquerade(chan, rchan);
13356+ /* Setup the extensions and such */
13357+ strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
13358+ strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
13359+ chan->priority = rchan->priority;
13360+ /* this might be dirty, but we need to preserve the uniqueid */
13361+ strncpy(chan->uniqueid, rchan->uniqueid, sizeof(chan->uniqueid) - 1);
13362+ /* Make the masq execute */
13363+ f = ast_read(chan);
13364+ if (f)
13365+ ast_frfree(f);
13366+ ast_hold_call(chan, peer);
13367+ return -1;
13368+ } else {
13369+ ast_log(LOG_WARNING, "Unable to create holded channel\n");
13370+ return -1;
13371+ }
13372+ return 0;
13373+}
13374+
13375+int ast_retrieve_call(struct ast_channel *chan, char *uniqueid)
13376+{
13377+ int res=-1, dres=-1;
13378+ struct ast_channel *peer=NULL;
13379+ struct ast_bridge_config config;
13380+
13381+ peer = ast_get_holded_call(uniqueid);
13382+
13383+ /* JK02: it helps to answer the channel if not already up */
13384+ if (chan->_state != AST_STATE_UP) {
13385+ ast_answer(chan);
13386+ }
13387+
13388+ if (peer) {
13389+ ast_mutex_unlock(&peer->lock);
13390+ ast_moh_stop(peer);
13391+ res = ast_channel_make_compatible(chan, peer);
13392+ if (res < 0) {
13393+ ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
13394+ ast_hangup(peer);
13395+ return -1;
13396+ }
13397+ /* This runs sorta backwards, since we give the incoming channel control, as if it
13398+ were the person called. */
13399+ if (option_verbose > 2)
13400+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to holded call %s\n", chan->name, peer->name);
13401+
13402+ memset(&config,0,sizeof(struct ast_bridge_config));
13403+ ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
13404+ ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
13405+ config.timelimit = 0;
13406+ config.play_warning = 0;
13407+ config.warning_freq = 0;
13408+ config.warning_sound=NULL;
13409+ res = ast_bridge_call(chan,peer,&config);
13410+
13411+ /* Simulate the PBX hanging up */
13412+ if (res != AST_PBX_NO_HANGUP_PEER)
13413+ ast_hangup(peer);
13414+ return res;
13415+ } else {
13416+ /* XXX Play a message XXX */
13417+ dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
13418+ if (!dres)
13419+ dres = ast_waitstream(chan, "");
13420+ else {
13421+ ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
13422+ dres = 0;
13423+ }
13424+ }
13425+ return res;
13426+}
13427+
13428+int ast_retrieve_call_to_death(char *uniqueid)
13429+{
13430+ int res=-1;
13431+ struct ast_channel *peer=NULL;
13432+
13433+ peer = ast_get_holded_call(uniqueid);
13434+
13435+ if (peer) {
13436+ res=0;
13437+ if (option_verbose > 2)
13438+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
13439+ ast_mutex_unlock(&peer->lock);
13440+ ast_hangup(peer);
13441+ } else {
13442+ ast_log(LOG_WARNING, "Could not find channel with uniqueid %s to retrieve.\n", uniqueid);
13443+ }
13444+ return res;
13445+}
13446+
13447+struct ast_channel *ast_get_holded_call(char *uniqueid)
13448+{
13449+ int res=-1;
13450+ struct ast_channel *peer=NULL;
13451+ struct holdeduser *pu, *pl=NULL;
13452+
13453+ ast_mutex_lock(&holding_lock);
13454+ pu = holdlist;
13455+ while(pu) {
13456+ if (!strncmp(uniqueid,pu->uniqueid,sizeof(pu->uniqueid))) {
13457+ if (pl)
13458+ pl->next = pu->next;
13459+ else
13460+ holdlist = pu->next;
13461+ break;
13462+ }
13463+ pl = pu;
13464+ pu = pu->next;
13465+ }
13466+ ast_mutex_unlock(&holding_lock);
13467+ if (pu) {
13468+ peer = ast_get_channel_by_uniqueid_locked(pu->uniqueid);
13469+ free(pu);
13470+ if (peer) {
13471+ res=0;
13472+ if (option_verbose > 2)
13473+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
13474+ ast_moh_stop(peer);
13475+ return peer;
13476+ } else {
13477+ if (option_verbose > 2)
13478+ ast_verbose(VERBOSE_PREFIX_3 "Could not find channel with uniqueid %s.\n", uniqueid);
13479+ return NULL;
13480+ }
13481+ } else {
13482+ ast_log(LOG_WARNING, "Could not find held channel with uniqueid %s to retrieve.\n", uniqueid);
13483+ }
13484+ return NULL;
13485+}
13486+
13487+/* this is our autmagically service thread that keeps channels onhold happy */
13488+static void *do_holding_thread(void *ignore)
13489+{
13490+ int ms, tms, max;
13491+ struct holdeduser *pu, *pl, *pt = NULL;
13492+ struct timeval tv;
13493+ struct ast_frame *f;
13494+ int x;
13495+ fd_set rfds, efds;
13496+ fd_set nrfds, nefds;
13497+ FD_ZERO(&rfds);
13498+ FD_ZERO(&efds);
13499+ for (;;) {
13500+ ms = -1;
13501+ max = -1;
13502+ ast_mutex_lock(&holding_lock);
13503+ pl = NULL;
13504+ pu = holdlist;
13505+ gettimeofday(&tv, NULL);
13506+ FD_ZERO(&nrfds);
13507+ FD_ZERO(&nefds);
13508+ while(pu) {
13509+ tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
13510+ for (x=0;x<AST_MAX_FDS;x++) {
13511+ if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
13512+ /* if (FD_ISSET(pu->chan->fds[x], &efds))
13513+ pu->chan->exception = 1; */
13514+ pu->chan->fdno = x;
13515+ /* See if they need servicing */
13516+ f = ast_read(pu->chan);
13517+ if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
13518+ /* There's a problem, hang them up*/
13519+ if (option_verbose > 1)
13520+ ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being onhold\n", pu->chan->name);
13521+ ast_hangup(pu->chan);
13522+ /* find the corresponding channel and hang them up too! */
13523+ /* but only if it is not bridged yet! */
13524+ /* And take them out of the parking lot */
13525+ if (pl)
13526+ pl->next = pu->next;
13527+ else
13528+ holdlist = pu->next;
13529+ pt = pu;
13530+ pu = pu->next;
13531+ free(pt);
13532+ break;
13533+ } else {
13534+ /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
13535+ ast_frfree(f);
13536+ goto std; /* XXX Ick: jumping into an else statement??? XXX */
13537+ }
13538+ }
13539+ }
13540+ if (x >= AST_MAX_FDS) {
13541+std: for (x=0;x<AST_MAX_FDS;x++) {
13542+ /* Keep this one for next one */
13543+ if (pu->chan->fds[x] > -1) {
13544+ FD_SET(pu->chan->fds[x], &nrfds);
13545+ FD_SET(pu->chan->fds[x], &nefds);
13546+ if (pu->chan->fds[x] > max)
13547+ max = pu->chan->fds[x];
13548+ }
13549+ }
13550+ /* Keep track of our longest wait */
13551+ if ((tms < ms) || (ms < 0))
13552+ ms = tms;
13553+ pl = pu;
13554+ pu = pu->next;
13555+ }
13556+ }
13557+ ast_mutex_unlock(&holding_lock);
13558+ rfds = nrfds;
13559+ efds = nefds;
13560+ tv.tv_sec = ms / 1000;
13561+ tv.tv_usec = (ms % 1000) * 1000;
13562+ /* Wait for something to happen */
13563+ ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
13564+ pthread_testcancel();
13565+ }
13566+ return NULL; /* Never reached */
13567+}
13568+
13569+static int retrieve_call_exec(struct ast_channel *chan, void *data) {
13570+ int res=0;
13571+ struct localuser *u;
13572+ char *uniqueid = (char *)data;
13573+ LOCAL_USER_ADD(u);
13574+ res = ast_retrieve_call(chan, uniqueid);
13575+ LOCAL_USER_REMOVE(u);
13576+ return res;
13577+}
13578+
13579 static int park_exec(struct ast_channel *chan, void *data)
13580 {
13581 int res=0;
b684b13b 13582@@ -1731,9 +2085,10 @@
5e69ef1a
MT
13583 "From: %s\r\n"
13584 "CallerID: %s\r\n"
13585 "CallerIDName: %s\r\n"
13586+ "Uniqueid: %s\r\n\r\n"
13587 ,pu->parkingnum, pu->chan->name, chan->name
13588 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
13589- ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
13590+ ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
13591 );
13592
13593 free(pu);
b684b13b 13594@@ -1901,12 +2256,13 @@
5e69ef1a
MT
13595 "Timeout: %ld\r\n"
13596 "CallerID: %s\r\n"
13597 "CallerIDName: %s\r\n"
13598+ "Uniqueid: %s\r\n"
13599 "%s"
13600 "\r\n"
13601 ,cur->parkingnum, cur->chan->name
13602 ,(long)cur->start.tv_sec + (long)(cur->parkingtime/1000) - (long)time(NULL)
13603 ,(cur->chan->cid.cid_num ? cur->chan->cid.cid_num : "")
13604- ,(cur->chan->cid.cid_name ? cur->chan->cid.cid_name : "")
13605+ ,(cur->chan->cid.cid_name ? cur->chan->cid.cid_name : ""), cur->chan->uniqueid
13606 ,idText);
13607
13608 cur = cur->next;
b684b13b 13609@@ -1922,6 +2278,386 @@
5e69ef1a
MT
13610 return RESULT_SUCCESS;
13611 }
13612
13613+static int handle_autoanswer(int fd, int argc, char *argv[])
13614+{
13615+ struct aauser *cur;
13616+
13617+ ast_cli(fd, "%25s %10s %15s \n", "Channel"
13618+ , "Extension", "Context");
13619+
13620+ ast_mutex_lock(&autoanswer_lock);
13621+
13622+ cur=aalot;
13623+ while(cur) {
13624+ ast_cli(fd, "%25s %10s %15s\n",cur->chan->name, cur->exten, cur->context);
13625+
13626+ cur = cur->next;
13627+ }
13628+
13629+ ast_mutex_unlock(&autoanswer_lock);
13630+
13631+ return RESULT_SUCCESS;
13632+}
13633+static char showautoanswer_help[] =
13634+"Usage: show autoanswer\n"
13635+" Lists currently logged in autoanswr channels.\n";
13636+
13637+static struct ast_cli_entry showautoanswer =
13638+{ { "show", "autoanswer", NULL }, handle_autoanswer, "Lists autoanswer channels", showautoanswer_help };
13639+
13640+int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data)
13641+{
13642+ struct ast_channel *chan;
13643+ struct ast_frame *f;
13644+ /* Make a new, fake channel that we'll use to masquerade in the real one */
13645+ chan = ast_channel_alloc(0);
13646+ if (chan) {
13647+ /* Let us keep track of the channel name */
13648+ snprintf(chan->name, sizeof (chan->name), "Autoanswer/%s",rchan->name);
13649+ /* Make formats okay */
13650+ chan->readformat = rchan->readformat;
13651+ chan->writeformat = rchan->writeformat;
13652+ ast_channel_masquerade(chan, rchan);
13653+ /* Setup the extensions and such */
13654+ strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
13655+ strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
13656+ chan->priority = rchan->priority;
13657+ /* Make the masq execute */
13658+ f = ast_read(chan);
13659+ if (f)
13660+ ast_frfree(f);
13661+ ast_autoanswer_login(chan, data);
13662+ } else {
13663+ ast_log(LOG_WARNING, "Unable to create aa channel\n");
13664+ return -1;
13665+ }
13666+ return 0;
13667+}
13668+
13669+static int autoanswer_login_exec(struct ast_channel *chan, void *data)
13670+{
13671+ int res=0;
13672+ struct localuser *u;
13673+ LOCAL_USER_ADD(u);
13674+ if (!data) {
13675+ ast_log(LOG_WARNING, "AutoanswerLogin requires an argument (extension number)\n");
13676+ return -1;
13677+ }
13678+ res = ast_masq_autoanswer_login(chan, data);
13679+ LOCAL_USER_REMOVE(u);
13680+ return res;
13681+}
13682+
13683+int ast_autoanswer_login(struct ast_channel *chan, void *data)
13684+{
13685+ /* We put the user in the parking list, then wake up the parking thread to be sure it looks
13686+ after these channels too */
13687+ struct ast_context *con;
13688+ char exten[AST_MAX_EXTENSION];
13689+ struct aauser *pu,*pl = NULL;
13690+ char *s, *stringp, *aacontext, *aaexten = NULL;
13691+
13692+ s = ast_strdupa((void *) data);
13693+ stringp=s;
13694+ aacontext = strsep(&stringp, "|");
13695+ aaexten = strsep(&stringp, "|");
13696+ if (!aaexten) {
13697+ aaexten = aacontext;
13698+ aacontext = NULL;
13699+ }
13700+ if (!aaexten) {
13701+ ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
13702+ return -1;
13703+ } else {
13704+ if (!aacontext) {
13705+ aacontext = "default";
13706+ }
13707+ }
13708+
13709+ ast_mutex_lock(&autoanswer_lock);
13710+ pu = aalot;
13711+ while(pu) {
13712+ if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
13713+ if (pl)
13714+ pl->next = pu->next;
13715+ else
13716+ aalot = pu->next;
13717+ break;
13718+ }
13719+ pl = pu;
13720+ pu = pu->next;
13721+ }
13722+ ast_mutex_unlock(&autoanswer_lock);
13723+ if (pu) {
13724+ ast_log(LOG_NOTICE, "Logout old Channel %s for %s@%s.\n",pu->chan->name, pu->exten, pu->context);
13725+ manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
13726+ "Channel: %s\r\n"
13727+ "Uniqueid: %s\r\n"
13728+ "Context: %s\r\n"
13729+ "Exten: %s\r\n"
13730+ ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
13731+ ast_hangup(pu->chan);
13732+ free(pu);
13733+ }
13734+ pu = malloc(sizeof(struct aauser));
13735+ if (pu) {
13736+ memset(pu, 0, sizeof(pu));
13737+ ast_mutex_lock(&autoanswer_lock);
13738+ chan->appl = "Autoanswer";
13739+ chan->data = NULL;
13740+
13741+ pu->chan = chan;
13742+ if (chan->_state != AST_STATE_UP) {
13743+ ast_answer(chan);
13744+ }
13745+
13746+ /* Start music on hold */
13747+ ast_moh_start(pu->chan, NULL);
13748+ gettimeofday(&pu->start, NULL);
13749+ strncpy(pu->exten, aaexten, sizeof(pu->exten)-1);
13750+ strncpy(pu->context, aacontext, sizeof(pu->exten)-1);
13751+ pu->next = aalot;
13752+ aalot = pu;
13753+ con = ast_context_find(aacontext);
13754+ if (!con) {
13755+ con = ast_context_create(NULL,aacontext, registrar);
13756+ if (!con) {
13757+ ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", aacontext);
13758+ }
13759+ }
13760+ if (con) {
13761+ snprintf(exten, sizeof(exten), "%s", aaexten);
13762+ ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)data), free, registrar);
13763+ }
13764+
13765+ ast_mutex_unlock(&autoanswer_lock);
13766+ /* Wake up the (presumably select()ing) thread */
13767+ pthread_kill(autoanswer_thread, SIGURG);
13768+ if (option_verbose > 1)
13769+ ast_verbose(VERBOSE_PREFIX_2 "Autoanswer login from %s for %s@%s.\n", pu->chan->name, pu->exten, pu->context);
13770+ manager_event(EVENT_FLAG_CALL, "AutoanswerLogin",
13771+ "Channel: %s\r\n"
13772+ "Uniqueid: %s\r\n"
13773+ "Context: %s\r\n"
13774+ "Exten: %s\r\n"
13775+ ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
13776+
13777+ return 0;
13778+ } else {
13779+ ast_log(LOG_WARNING, "Out of memory\n");
13780+ return -1;
13781+ }
13782+ return 0;
13783+}
13784+
13785+static void *do_autoanswer_thread(void *ignore)
13786+{
13787+ int ms, tms, max;
13788+ struct ast_context *con;
13789+ char exten[AST_MAX_EXTENSION];
13790+ struct aauser *pu, *pl, *pt = NULL;
13791+ struct timeval tv;
13792+ struct ast_frame *f;
13793+ int x;
13794+ fd_set rfds, efds;
13795+ fd_set nrfds, nefds;
13796+ FD_ZERO(&rfds);
13797+ FD_ZERO(&efds);
13798+ for (;;) {
13799+ ms = -1;
13800+ max = -1;
13801+ ast_mutex_lock(&autoanswer_lock);
13802+ pl = NULL;
13803+ pu = aalot;
13804+ gettimeofday(&tv, NULL);
13805+ FD_ZERO(&nrfds);
13806+ FD_ZERO(&nefds);
13807+ while(pu) {
13808+ tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
13809+ for (x=0;x<AST_MAX_FDS;x++) {
13810+ if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
13811+/* if (FD_ISSET(pu->chan->fds[x], &efds))
13812+ pu->chan->exception = 1; */
13813+ pu->chan->fdno = x;
13814+ /* See if they need servicing */
13815+ f = ast_read(pu->chan);
13816+ if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
13817+ /* There's a problem, hang them up*/
13818+ if (option_verbose > 1)
13819+ ast_verbose(VERBOSE_PREFIX_2 "%s logged out of autoanswer app\n", pu->chan->name);
13820+ manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
13821+ "Channel: %s\r\n"
13822+ "Uniqueid: %s\r\n"
13823+ "Context: %s\r\n"
13824+ "Exten: %s\r\n"
13825+ ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
13826+ ast_hangup(pu->chan);
13827+ con = ast_context_find(pu->context);
13828+ if (con) {
13829+ snprintf(exten, sizeof(exten), "%s", pu->exten);
13830+ if (ast_context_remove_extension2(con, exten, 1, registrar))
13831+ ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
13832+ } else {
13833+ ast_log(LOG_WARNING, "Whoa, no %s context?\n", pu->exten);
13834+ }
13835+ /* And take them out of the parking lot */
13836+ if (pl)
13837+ pl->next = pu->next;
13838+ else
13839+ aalot = pu->next;
13840+ pt = pu;
13841+ pu = pu->next;
13842+ free(pt);
13843+ break;
13844+ } else {
13845+ /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
13846+ ast_frfree(f);
13847+ goto std; /* XXX Ick: jumping into an else statement??? XXX */
13848+ }
13849+ }
13850+ }
13851+ if (x >= AST_MAX_FDS) {
13852+std: for (x=0;x<AST_MAX_FDS;x++) {
13853+ /* Keep this one for next one */
13854+ if (pu->chan->fds[x] > -1) {
13855+ FD_SET(pu->chan->fds[x], &nrfds);
13856+ FD_SET(pu->chan->fds[x], &nefds);
13857+ if (pu->chan->fds[x] > max)
13858+ max = pu->chan->fds[x];
13859+ }
13860+ }
13861+ /* Keep track of our longest wait */
13862+ if ((tms < ms) || (ms < 0))
13863+ ms = tms;
13864+ pl = pu;
13865+ pu = pu->next;
13866+ }
13867+ }
13868+ ast_mutex_unlock(&autoanswer_lock);
13869+ rfds = nrfds;
13870+ efds = nefds;
13871+ tv.tv_sec = ms / 1000;
13872+ tv.tv_usec = (ms % 1000) * 1000;
13873+ /* Wait for something to happen */
13874+ ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
13875+ pthread_testcancel();
13876+ }
13877+ return NULL; /* Never reached */
13878+}
13879+
13880+static int autoanswer_exec(struct ast_channel *chan, void *data)
13881+{
13882+ int res=0;
13883+ struct localuser *u;
13884+ struct ast_channel *peer=NULL;
13885+ struct aauser *pu, *pl=NULL;
13886+ struct ast_bridge_config config;
13887+ char *s, *stringp, *aacontext, *aaexten = NULL;
13888+ char datastring[80];
13889+
13890+ if (!data) {
13891+ ast_log(LOG_WARNING, "Autoanswer requires an argument (extension number)\n");
13892+ return -1;
13893+ }
13894+ s = ast_strdupa((void *) data);
13895+ stringp=s;
13896+ aacontext = strsep(&stringp, "|");
13897+ aaexten = strsep(&stringp, "|");
13898+ if (!aaexten) {
13899+ aaexten = aacontext;
13900+ aacontext = NULL;
13901+ }
13902+ if (!aaexten) {
13903+ ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
13904+ return -1;
13905+ } else {
13906+ if (!aacontext) {
13907+ aacontext = "default";
13908+ }
13909+ }
13910+
13911+ LOCAL_USER_ADD(u);
13912+ ast_mutex_lock(&autoanswer_lock);
13913+ pu = aalot;
13914+ while(pu) {
13915+ if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
13916+ if (pl)
13917+ pl->next = pu->next;
13918+ else
13919+ aalot = pu->next;
13920+ break;
13921+ }
13922+ pl = pu;
13923+ pu = pu->next;
13924+ }
13925+ ast_mutex_unlock(&autoanswer_lock);
13926+ if (pu) {
13927+ peer = pu->chan;
13928+ free(pu);
13929+ pu = NULL;
13930+ }
13931+ /* JK02: it helps to answer the channel if not already up */
13932+ if (chan->_state != AST_STATE_UP) {
13933+ ast_answer(chan);
13934+ }
13935+
13936+ if (peer) {
13937+ ast_moh_stop(peer);
13938+ /* Play a courtesy beep in the callED channel to prefix the bridge connecting */
13939+ if (!ast_strlen_zero(courtesytone)) {
13940+ if (!ast_streamfile(peer, courtesytone, peer->language)) {
13941+ if (ast_waitstream(peer, "") < 0) {
13942+ ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
13943+ ast_hangup(peer);
13944+ return -1;
13945+ }
13946+ }
13947+ }
13948+
13949+ res = ast_channel_make_compatible(chan, peer);
13950+ if (res < 0) {
13951+ ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
13952+ ast_hangup(peer);
13953+ return -1;
13954+ }
13955+ /* This runs sorta backwards, since we give the incoming channel control, as if it
13956+ were the person called. */
13957+ if (option_verbose > 2)
13958+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s autoanswered %s\n", peer->name, chan->name);
13959+ manager_event(EVENT_FLAG_CALL, "Autoanswer",
13960+ "Channel: %s\r\n"
13961+ "Uniqueid: %s\r\n"
13962+ "Channel2: %s\r\n"
13963+ "Uniqueid2: %s\r\n"
13964+ "Context: %s\r\n"
13965+ "Exten: %s\r\n"
13966+ ,chan->name, chan->uniqueid, peer->name, peer->uniqueid, aacontext, aaexten);
13967+
13968+
13969+ memset(&config,0,sizeof(struct ast_bridge_config));
13970+ ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
13971+ ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
13972+ config.timelimit = 0;
13973+ config.play_warning = 0;
13974+ config.warning_freq = 0;
13975+ config.warning_sound=NULL;
13976+ res = ast_bridge_call(chan,peer,&config);
13977+
13978+ if (option_verbose > 2)
13979+ ast_verbose(VERBOSE_PREFIX_3 "returning from bridge %s\n", peer->name);
13980+ /* relogin */
13981+ snprintf(datastring, sizeof(datastring) - 1, "%s|%s", aacontext, aaexten);
13982+ ast_autoanswer_login(peer, datastring);
13983+ return res;
13984+ } else {
13985+ if (option_verbose > 2)
13986+ ast_verbose(VERBOSE_PREFIX_3 "Nobody logged in for autoanswer %s@%s\n", aaexten, aacontext);
13987+ res = -1;
13988+ }
13989+ LOCAL_USER_REMOVE(u);
13990+ return res;
13991+}
13992+
13993
13994 int ast_pickup_call(struct ast_channel *chan)
13995 {
b684b13b 13996@@ -2076,7 +2812,7 @@
5e69ef1a
MT
13997 }
13998
13999 {
14000- struct ast_call_feature *feature=find_feature(var->name);
14001+ struct ast_call_feature *feature = ast_find_feature(var->name);
14002 int mallocd=0;
14003
14004 if (!feature) {
b684b13b 14005@@ -2151,14 +2887,22 @@
5e69ef1a
MT
14006 if ((res = load_config()))
14007 return res;
14008 ast_cli_register(&showparked);
14009+ ast_cli_register(&showautoanswer);
14010 ast_cli_register(&showfeatures);
14011 ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
14012+ ast_pthread_create(&holding_thread, NULL, do_holding_thread, NULL);
14013 res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
14014 if (!res)
14015 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
14016 if (!res) {
14017 ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" );
14018 }
14019+ res = ast_register_application(holdedcall, retrieve_call_exec, synopsis, descrip);
14020+ ast_pthread_create(&autoanswer_thread, NULL, do_autoanswer_thread, NULL);
14021+ if (!res)
14022+ res = ast_register_application(autoanswerlogin, autoanswer_login_exec, synopsis3, descrip3);
14023+ if (!res)
14024+ res = ast_register_application(autoanswer, autoanswer_exec, synopsis4, descrip4);
14025 return res;
14026 }
14027
b684b13b 14028@@ -2169,7 +2913,11 @@
5e69ef1a
MT
14029
14030 ast_manager_unregister("ParkedCalls");
14031 ast_cli_unregister(&showfeatures);
14032+ ast_cli_unregister(&showautoanswer);
14033 ast_cli_unregister(&showparked);
14034+ ast_unregister_application(autoanswer);
14035+ ast_unregister_application(autoanswerlogin);
14036+ ast_unregister_application(holdedcall);
14037 ast_unregister_application(parkcall);
14038 return ast_unregister_application(parkedcall);
14039 }
b684b13b
MT
14040diff -urN asterisk-1.2.9.1.orig/res/res_monitor.c asterisk-1.2.9.1/res/res_monitor.c
14041--- asterisk-1.2.9.1.orig/res/res_monitor.c 2006-03-02 20:05:40.000000000 +0100
14042+++ asterisk-1.2.9.1/res/res_monitor.c 2006-06-09 10:25:04.000000000 +0200
14043@@ -90,7 +90,7 @@
14044
14045 /* Start monitoring a channel */
14046 int ast_monitor_start( struct ast_channel *chan, const char *format_spec,
14047- const char *fname_base, int need_lock)
14048+ const char *fname_base, const char *target_url, const char *target_script, int need_lock)
14049 {
14050 int res = 0;
14051 char tmp[256];
14052@@ -122,6 +122,11 @@
14053 }
14054 memset(monitor, 0, sizeof(struct ast_channel_monitor));
14055
14056+ if (target_url)
14057+ ast_copy_string(monitor->target_url, target_url, sizeof(monitor->target_url));
14058+ if (target_script)
14059+ ast_copy_string(monitor->target_script, target_script, sizeof(monitor->target_script));
14060+
14061 /* Determine file names */
14062 if (!ast_strlen_zero(fname_base)) {
14063 int directory = strchr(fname_base, '/') ? 1 : 0;
14064@@ -257,6 +262,8 @@
14065 if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) {
14066 char tmp[1024];
14067 char tmp2[1024];
14068+ char tmp3[1024];
14069+ int result;
14070 char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format;
14071 char *name = chan->monitor->filename_base;
14072 int directory = strchr(name, '/') ? 1 : 0;
14073@@ -278,9 +285,19 @@
14074 snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s/%s-\"* ) &",tmp, dir ,name); /* remove legs when done mixing */
14075 ast_copy_string(tmp, tmp2, sizeof(tmp));
14076 }
14077- ast_log(LOG_DEBUG,"monitor executing %s\n",tmp);
14078- if (ast_safe_system(tmp) == -1)
14079+ if (!ast_strlen_zero(chan->monitor->target_script) && !ast_strlen_zero(chan->monitor->target_url)) {
14080+ snprintf(tmp3,sizeof(tmp3), "( %s& nice -19 %s \"%s/%s.%s\" \"%s\" ) &",tmp, chan->monitor->target_script , dir, name, format, chan->monitor->target_url);
14081+ ast_copy_string(tmp, tmp3, sizeof(tmp));
14082+ }
14083+ ast_log(LOG_NOTICE,"monitor executing %s\n",tmp);
14084+ result = ast_safe_system(tmp);
14085+ if (result == -1)
14086 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
14087+ manager_event(EVENT_FLAG_CALL, "MonitorStopped",
14088+ "Channel: %s\r\n"
14089+ "Uniqueid: %s\r\n"
14090+ "Result: %d\r\n"
14091+ ,chan->name, chan->uniqueid, result);
14092 }
14093
14094 free(chan->monitor->format);
14095@@ -392,7 +409,7 @@
14096 return 0;
14097 }
14098
14099- res = ast_monitor_start(chan, format, fname_base, 1);
14100+ res = ast_monitor_start(chan, format, fname_base, NULL, NULL, 1);
14101 if (res < 0)
14102 res = ast_monitor_change_fname(chan, fname_base, 1);
14103 ast_monitor_setjoinfiles(chan, joinfiles);
14104@@ -428,19 +445,30 @@
14105 {
14106 struct ast_channel *c = NULL;
14107 char *name = astman_get_header(m, "Channel");
14108+ char *uniqueid = astman_get_header(m, "Uniqueid");
14109 char *fname = astman_get_header(m, "File");
14110 char *format = astman_get_header(m, "Format");
14111 char *mix = astman_get_header(m, "Mix");
14112+ char *target_url = astman_get_header(m, "TargetURL");
14113+ char *target_script = astman_get_header(m, "TargetScript");
14114 char *d;
14115
14116- if (ast_strlen_zero(name)) {
14117- astman_send_error(s, m, "No channel specified");
14118+ if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
14119+ astman_send_error(s, m, "No channel/uniqueid specified");
14120 return 0;
14121 }
14122- c = ast_get_channel_by_name_locked(name);
14123- if (!c) {
14124+ if (!ast_strlen_zero(uniqueid)) {
14125+ c = ast_get_channel_by_uniqueid_locked(uniqueid);
14126+ if (!c) {
14127+ astman_send_error(s, m, "No such uniqueid");
14128+ return 0;
14129+ }
14130+ } else {
14131+ c = ast_get_channel_by_name_locked(name);
14132+ if (!c) {
14133 astman_send_error(s, m, "No such channel");
14134 return 0;
14135+ }
14136 }
14137
14138 if (ast_strlen_zero(fname)) {
14139@@ -457,7 +485,7 @@
14140 if ((d=strchr(fname, '/'))) *d='-';
14141 }
14142
14143- if (ast_monitor_start(c, format, fname, 1)) {
14144+ if (ast_monitor_start(c, format, fname, target_url, target_script, 1)) {
14145 if (ast_monitor_change_fname(c, fname, 1)) {
14146 astman_send_error(s, m, "Could not start monitoring channel");
14147 ast_mutex_unlock(&c->lock);
14148@@ -483,16 +511,26 @@
14149 {
14150 struct ast_channel *c = NULL;
14151 char *name = astman_get_header(m, "Channel");
14152+ char *uniqueid = astman_get_header(m, "Uniqueid");
14153 int res;
14154- if (ast_strlen_zero(name)) {
14155- astman_send_error(s, m, "No channel specified");
14156+ if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
14157+ astman_send_error(s, m, "No channel/uniqueid specified");
14158 return 0;
14159 }
14160- c = ast_get_channel_by_name_locked(name);
14161- if (!c) {
14162+ if (!ast_strlen_zero(uniqueid)) {
14163+ c = ast_get_channel_by_uniqueid_locked(uniqueid);
14164+ if (!c) {
14165+ astman_send_error(s, m, "No such uniqueid");
14166+ return 0;
14167+ }
14168+ } else {
14169+ c = ast_get_channel_by_name_locked(name);
14170+ if (!c) {
14171 astman_send_error(s, m, "No such channel");
14172 return 0;
14173+ }
14174 }
14175+
14176 res = ast_monitor_stop(c, 1);
14177 ast_mutex_unlock(&c->lock);
14178 if (res) {
14179diff -urN asterisk-1.2.9.1.orig/res/res_watchdog.c asterisk-1.2.9.1/res/res_watchdog.c
14180--- asterisk-1.2.9.1.orig/res/res_watchdog.c 1970-01-01 01:00:00.000000000 +0100
14181+++ asterisk-1.2.9.1/res/res_watchdog.c 2006-06-09 10:25:04.000000000 +0200
5f892677 14182@@ -0,0 +1,149 @@
5e69ef1a
MT
14183+/*
14184+ * Asterisk -- A telephony toolkit for Linux.
14185+ *
14186+ * Resource to make watchdogs happy
14187+ *
14188+ * Copyright (C) 2005, Junghanns.NET GmbH
14189+ *
14190+ * Klaus-Peter Junghanns <kpj@junghanns.net>
14191+ *
14192+ * This program is free software, distributed under the terms of
14193+ * the GNU General Public License
14194+ */
14195+
14196+#include <stdlib.h>
14197+#include <errno.h>
14198+#include <unistd.h>
14199+#include <string.h>
14200+#include <stdlib.h>
14201+#include <stdio.h>
14202+#include <sys/time.h>
14203+#include <sys/signal.h>
14204+#include <netinet/in.h>
14205+#include <asterisk/lock.h>
14206+#include <asterisk/file.h>
14207+#include <asterisk/logger.h>
14208+#include <asterisk/channel.h>
14209+#include <asterisk/pbx.h>
14210+#include <asterisk/options.h>
14211+#include <asterisk/module.h>
14212+#include <asterisk/translate.h>
14213+#include <asterisk/say.h>
14214+#include <asterisk/features.h>
14215+#include <asterisk/musiconhold.h>
14216+#include <asterisk/config.h>
14217+#include <asterisk/cli.h>
14218+#include <asterisk/manager.h>
14219+#include <asterisk/utils.h>
14220+#include <asterisk/adsi.h>
14221+
14222+static struct watchdog_pvt *watchdogs = NULL;
14223+
14224+STANDARD_LOCAL_USER;
14225+
14226+LOCAL_USER_DECL;
14227+
14228+typedef struct watchdog_pvt {
14229+ char device[80];
14230+ int fd;
14231+ int type;
14232+ int interval;
14233+ pthread_t watchdog_thread;
14234+ struct watchdog_pvt *next;
14235+} watchdog_pvt;
14236+
14237+static void *do_watchdog_thread(void *data) {
14238+ struct watchdog_pvt *woof = (struct watchdog_pvt *)data;
14239+ for (;;) {
14240+ if (woof->fd) {
14241+ write(woof->fd, "PING\n", 1);
14242+ }
14243+ usleep(woof->interval * 1000);
14244+ }
14245+ return NULL;
14246+}
14247+
14248+
14249+int load_module(void)
14250+{
14251+ int res = 0;
14252+ char *cat, *utype, *udevice, *uinterval;
14253+ struct ast_config *cfg;
14254+ struct watchdog_pvt *woof = NULL;
14255+
14256+ cfg = ast_config_load("watchdog.conf");
14257+ if (cfg) {
14258+ cat = ast_category_browse(cfg, NULL);
14259+ while(cat) {
14260+ cat = ast_category_browse(cfg, cat);
14261+ utype = ast_variable_retrieve(cfg, cat, "type");
14262+ if (utype) {
14263+ ast_log(LOG_NOTICE, "type = %s\n", utype);
14264+ }
14265+ udevice = ast_variable_retrieve(cfg, cat, "device");
14266+ if (udevice) {
14267+ ast_log(LOG_NOTICE, "device = %s\n", udevice);
14268+ }
14269+ uinterval = ast_variable_retrieve(cfg, cat, "interval");
14270+ if (uinterval) {
14271+ ast_log(LOG_NOTICE, "interval = %s\n", uinterval);
14272+ }
14273+ if (uinterval && udevice && utype) {
14274+ woof = malloc(sizeof(struct watchdog_pvt));
14275+ if (!woof) {
14276+ ast_log(LOG_ERROR, "unable to malloc!\n");
14277+ return -1;
14278+ }
14279+ memset(woof, 0x0, sizeof(struct watchdog_pvt));
14280+ strncpy(woof->device, udevice, sizeof(woof->device) - 1);
14281+
14282+ woof->interval = atoi(uinterval);;
14283+ woof->next = watchdogs;
14284+ watchdogs = woof;
14285+ woof->fd = open(woof->device, O_WRONLY | O_SYNC);
14286+ if (woof->fd) {
14287+ if (!strncmp(utype, "isdnguard", sizeof(utype))) {
14288+ woof->type = 1;
14289+ write(woof->fd, "START\n", 6);
14290+ }
14291+ ast_pthread_create(&woof->watchdog_thread, NULL, do_watchdog_thread, woof);
14292+ } else {
14293+ ast_log(LOG_WARNING, "error opening watchdog device %s !\n", woof->device);
14294+ }
14295+ }
14296+ }
14297+ ast_config_destroy(cfg);
14298+ }
14299+ return res;
14300+}
14301+
14302+
14303+int unload_module(void)
14304+{
14305+ struct watchdog_pvt *dogs, *woof;
14306+ STANDARD_HANGUP_LOCALUSERS;
14307+ dogs = watchdogs;
14308+ while (dogs) {
14309+ pthread_cancel(dogs->watchdog_thread);
5f892677 14310+ close(dogs->fd);
5e69ef1a
MT
14311+ woof = dogs->next;
14312+ free(dogs);
14313+ dogs = woof;
14314+ }
14315+ return 0;
14316+}
14317+
14318+char *description(void)
14319+{
14320+ return "Watchdog Resource";
14321+}
14322+
14323+int usecount(void)
14324+{
14325+ return 1;
14326+}
14327+
14328+char *key()
14329+{
14330+ return ASTERISK_GPL_KEY;
14331+}
b684b13b
MT
14332diff -urN asterisk-1.2.9.1.orig/rtp.c asterisk-1.2.9.1/rtp.c
14333--- asterisk-1.2.9.1.orig/rtp.c 2006-06-01 00:26:38.000000000 +0200
14334+++ asterisk-1.2.9.1/rtp.c 2006-06-09 10:25:04.000000000 +0200
14335@@ -444,6 +444,11 @@
5e69ef1a
MT
14336 struct rtpPayloadType rtpPT;
14337
14338 len = sizeof(sin);
14339+
14340+ /* XXX SYMPTON CURE, DIRTY FIX, CHECK, BEGIN */
14341+ if (!rtp)
14342+ return &null_frame;
14343+ /* XXX SYMPTON CURE, DIRTY FIX, CHECK, END */
14344
14345 /* Cache where the header will go */
14346 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,