]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/asterisk.patch
HinzugefĆ¼gt:
[ipfire-2.x.git] / src / patches / asterisk.patch
1 diff -urN asterisk-1.2.7.1.orig/.version asterisk-1.2.7.1/.version
2 --- asterisk-1.2.7.1.orig/.version 2006-04-13 19:50:06.000000000 +0200
3 +++ asterisk-1.2.7.1/.version 2006-04-18 14:39:46.000000000 +0200
4 @@ -1 +1 @@
5 -1.2.7.1
6 +1.2.7.1-BRIstuffed-0.3.0-PRE-1o-with-florz-patch-for-ipfire
7 diff -urN asterisk-1.2.7.1.orig/HARDWARE asterisk-1.2.7.1/HARDWARE
8 --- asterisk-1.2.7.1.orig/HARDWARE 2005-11-29 19:24:39.000000000 +0100
9 +++ asterisk-1.2.7.1/HARDWARE 2006-04-18 14:39:28.000000000 +0200
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 +
25 + * uno/duo/quad GSM PCI - 1/2/4 channel GSM interface cards
26 +
27 Non-zaptel compatible hardware
28 ==============================
29
30 diff -urN asterisk-1.2.7.1.orig/LICENSE asterisk-1.2.7.1/LICENSE
31 --- asterisk-1.2.7.1.orig/LICENSE 2005-11-29 19:24:39.000000000 +0100
32 +++ asterisk-1.2.7.1/LICENSE 2006-04-18 14:39:28.000000000 +0200
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
45 diff -urN asterisk-1.2.7.1.orig/Makefile asterisk-1.2.7.1/Makefile
46 --- asterisk-1.2.7.1.orig/Makefile 2006-04-11 23:58:47.000000000 +0200
47 +++ asterisk-1.2.7.1/Makefile 2006-04-18 14:39:28.000000000 +0200
48 @@ -760,6 +760,9 @@
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"; \
58 diff -urN asterisk-1.2.7.1.orig/README asterisk-1.2.7.1/README
59 --- asterisk-1.2.7.1.orig/README 2006-03-03 09:12:33.000000000 +0100
60 +++ asterisk-1.2.7.1/README 2006-04-18 14:39:28.000000000 +0200
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
70 diff -urN asterisk-1.2.7.1.orig/README.chan_capi asterisk-1.2.7.1/README.chan_capi
71 --- asterisk-1.2.7.1.orig/README.chan_capi 1970-01-01 01:00:00.000000000 +0100
72 +++ asterisk-1.2.7.1/README.chan_capi 2006-04-18 14:39:28.000000000 +0200
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 +
220 diff -urN asterisk-1.2.7.1.orig/agi/Makefile asterisk-1.2.7.1/agi/Makefile
221 --- asterisk-1.2.7.1.orig/agi/Makefile 2006-03-28 22:22:05.000000000 +0200
222 +++ asterisk-1.2.7.1/agi/Makefile 2006-04-18 14:39:28.000000000 +0200
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
230 CFLAGS+=-DNO_AST_MM
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 $@ $<
241 diff -urN asterisk-1.2.7.1.orig/agi/xagi-test.c asterisk-1.2.7.1/agi/xagi-test.c
242 --- asterisk-1.2.7.1.orig/agi/xagi-test.c 1970-01-01 01:00:00.000000000 +0100
243 +++ asterisk-1.2.7.1/agi/xagi-test.c 2006-04-24 09:55:45.000000000 +0200
244 @@ -0,0 +1,175 @@
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)) {
324 + return;
325 + }
326 + astresp[strlen(astresp) - 1] = '\0';
327 + fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
328 + return;
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;
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 +}
420 diff -urN asterisk-1.2.7.1.orig/apps/Makefile asterisk-1.2.7.1/apps/Makefile
421 --- asterisk-1.2.7.1.orig/apps/Makefile 2006-02-09 03:31:21.000000000 +0100
422 +++ asterisk-1.2.7.1/apps/Makefile 2006-04-18 14:39:28.000000000 +0200
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...
440 diff -urN asterisk-1.2.7.1.orig/apps/app_callingpres.c asterisk-1.2.7.1/apps/app_callingpres.c
441 --- asterisk-1.2.7.1.orig/apps/app_callingpres.c 1970-01-01 01:00:00.000000000 +0100
442 +++ asterisk-1.2.7.1/apps/app_callingpres.c 2006-04-18 14:39:28.000000000 +0200
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 +}
514 diff -urN asterisk-1.2.7.1.orig/apps/app_capiCD.c asterisk-1.2.7.1/apps/app_capiCD.c
515 --- asterisk-1.2.7.1.orig/apps/app_capiCD.c 1970-01-01 01:00:00.000000000 +0100
516 +++ asterisk-1.2.7.1/apps/app_capiCD.c 2006-04-18 14:39:28.000000000 +0200
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 +}
690 diff -urN asterisk-1.2.7.1.orig/apps/app_capiECT.c asterisk-1.2.7.1/apps/app_capiECT.c
691 --- asterisk-1.2.7.1.orig/apps/app_capiECT.c 1970-01-01 01:00:00.000000000 +0100
692 +++ asterisk-1.2.7.1/apps/app_capiECT.c 2006-04-18 14:39:28.000000000 +0200
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 +}
904 diff -urN asterisk-1.2.7.1.orig/apps/app_capiNoES.c asterisk-1.2.7.1/apps/app_capiNoES.c
905 --- asterisk-1.2.7.1.orig/apps/app_capiNoES.c 1970-01-01 01:00:00.000000000 +0100
906 +++ asterisk-1.2.7.1/apps/app_capiNoES.c 2006-04-18 14:39:28.000000000 +0200
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 +}
1004 diff -urN asterisk-1.2.7.1.orig/apps/app_chanisavail.c asterisk-1.2.7.1/apps/app_chanisavail.c
1005 --- asterisk-1.2.7.1.orig/apps/app_chanisavail.c 2005-11-29 19:24:39.000000000 +0100
1006 +++ asterisk-1.2.7.1/apps/app_chanisavail.c 2006-04-18 14:39:28.000000000 +0200
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);
1016 diff -urN asterisk-1.2.7.1.orig/apps/app_devstate.c asterisk-1.2.7.1/apps/app_devstate.c
1017 --- asterisk-1.2.7.1.orig/apps/app_devstate.c 1970-01-01 01:00:00.000000000 +0100
1018 +++ asterisk-1.2.7.1/apps/app_devstate.c 2006-04-18 14:39:28.000000000 +0200
1019 @@ -0,0 +1,219 @@
1020 +/*
1021 + * Devstate application
1022 + *
1023 + * Since we like the snom leds so much, a little app to
1024 + * light the lights on the snom on demand ....
1025 + *
1026 + * Copyright (C) 2005, Druid Software
1027 + *
1028 + * This program is free software, distributed under the terms of
1029 + * the GNU General Public License
1030 + */
1031 +
1032 +#include <stdlib.h>
1033 +#include <unistd.h>
1034 +#include <string.h>
1035 +#include <stdio.h>
1036 +#include <asterisk/lock.h>
1037 +#include <asterisk/file.h>
1038 +#include <asterisk/logger.h>
1039 +#include <asterisk/channel.h>
1040 +#include <asterisk/pbx.h>
1041 +#include <asterisk/module.h>
1042 +#include <asterisk/astdb.h>
1043 +#include <asterisk/utils.h>
1044 +#include <asterisk/cli.h>
1045 +#include <asterisk/manager.h>
1046 +#include <asterisk/devicestate.h>
1047 +
1048 +
1049 +static char type[] = "DS";
1050 +static char tdesc[] = "Application for sending device state messages";
1051 +
1052 +static char app[] = "Devstate";
1053 +
1054 +static char synopsis[] = "Generate a device state change event given the input parameters";
1055 +
1056 +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";
1057 +
1058 +static char devstate_cli_usage[] =
1059 +"Usage: devstate device state\n"
1060 +" Generate a device state change event given the input parameters.\n Mainly used for lighting the LEDs on the snoms.\n";
1061 +
1062 +static int devstate_cli(int fd, int argc, char *argv[]);
1063 +static struct ast_cli_entry cli_dev_state =
1064 + { { "devstate", NULL }, devstate_cli, "Set the device state on one of the \"pseudo devices\".", devstate_cli_usage };
1065 +
1066 +STANDARD_LOCAL_USER;
1067 +
1068 +LOCAL_USER_DECL;
1069 +
1070 +
1071 +static int devstate_cli(int fd, int argc, char *argv[])
1072 +{
1073 + char devName[128];
1074 + if ((argc != 3) && (argc != 4))
1075 + return RESULT_SHOWUSAGE;
1076 +
1077 + if (ast_db_put("DEVSTATES", argv[1], argv[2]))
1078 + {
1079 + ast_log(LOG_DEBUG, "ast_db_put failed\n");
1080 + }
1081 + snprintf(devName, sizeof(devName), "DS/%s", argv[1]);
1082 + if (argc == 4) {
1083 + ast_log(LOG_NOTICE, "devname %s cid %s\n", devName, argv[3]);
1084 + ast_device_state_changed_literal(devName, argv[3], NULL);
1085 + } else {
1086 + ast_device_state_changed_literal(devName, NULL, NULL);
1087 + }
1088 + return RESULT_SUCCESS;
1089 +}
1090 +
1091 +static int devstate_exec(struct ast_channel *chan, void *data)
1092 +{
1093 + struct localuser *u;
1094 + char *device, *state, *info;
1095 + char devName[128];
1096 + if (!(info = ast_strdupa(data))) {
1097 + ast_log(LOG_WARNING, "Unable to dupe data :(\n");
1098 + return -1;
1099 + }
1100 + LOCAL_USER_ADD(u);
1101 +
1102 + device = info;
1103 + state = strchr(info, '|');
1104 + if (state) {
1105 + *state = '\0';
1106 + state++;
1107 + }
1108 + else
1109 + {
1110 + ast_log(LOG_DEBUG, "No state argument supplied\n");
1111 + return -1;
1112 + }
1113 +
1114 + if (ast_db_put("DEVSTATES", device, state))
1115 + {
1116 + ast_log(LOG_DEBUG, "ast_db_put failed\n");
1117 + }
1118 +
1119 + snprintf(devName, sizeof(devName), "DS/%s", device);
1120 + ast_device_state_changed_literal(devName, NULL, NULL);
1121 +
1122 + LOCAL_USER_REMOVE(u);
1123 + return 0;
1124 +}
1125 +
1126 +
1127 +static int ds_devicestate(void *data)
1128 +{
1129 + char *dest = data;
1130 + char stateStr[16];
1131 + if (ast_db_get("DEVSTATES", dest, stateStr, sizeof(stateStr)))
1132 + {
1133 + ast_log(LOG_DEBUG, "ds_devicestate couldnt get state in astdb\n");
1134 + return 0;
1135 + }
1136 + else
1137 + {
1138 + ast_log(LOG_DEBUG, "ds_devicestate dev=%s returning state %d\n",
1139 + dest, atoi(stateStr));
1140 + return (atoi(stateStr));
1141 + }
1142 +}
1143 +
1144 +static struct ast_channel_tech devstate_tech = {
1145 + .type = type,
1146 + .description = tdesc,
1147 + .capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
1148 + .devicestate = ds_devicestate,
1149 + .requester = NULL,
1150 + .send_digit = NULL,
1151 + .send_text = NULL,
1152 + .call = NULL,
1153 + .hangup = NULL,
1154 + .answer = NULL,
1155 + .read = NULL,
1156 + .write = NULL,
1157 + .bridge = NULL,
1158 + .exception = NULL,
1159 + .indicate = NULL,
1160 + .fixup = NULL,
1161 + .setoption = NULL,
1162 +};
1163 +
1164 +static char mandescr_devstate[] =
1165 +"Description: Put a value into astdb\n"
1166 +"Variables: \n"
1167 +" Family: ...\n"
1168 +" Key: ...\n"
1169 +" Value: ...\n";
1170 +
1171 +static int action_devstate(struct mansession *s, struct message *m)
1172 +{
1173 + char *devstate = astman_get_header(m, "Devstate");
1174 + char *value = astman_get_header(m, "Value");
1175 + char *id = astman_get_header(m,"ActionID");
1176 + char devName[128];
1177 +
1178 + if (!strlen(devstate)) {
1179 + astman_send_error(s, m, "No Devstate specified");
1180 + return 0;
1181 + }
1182 + if (!strlen(value)) {
1183 + astman_send_error(s, m, "No Value specified");
1184 + return 0;
1185 + }
1186 +
1187 + if (!ast_db_put("DEVSTATES", devstate, value)) {
1188 + snprintf(devName, sizeof(devName), "DS/%s", devstate);
1189 + ast_device_state_changed(devName);
1190 + ast_cli(s->fd, "Response: Success\r\n");
1191 + } else {
1192 + ast_log(LOG_DEBUG, "ast_db_put failed\n");
1193 + ast_cli(s->fd, "Response: Failed\r\n");
1194 + }
1195 + if (id && !ast_strlen_zero(id))
1196 + ast_cli(s->fd, "ActionID: %s\r\n",id);
1197 + ast_cli(s->fd, "\r\n");
1198 + return 0;
1199 +}
1200 +
1201 +int load_module(void)
1202 +{
1203 + if (ast_channel_register(&devstate_tech)) {
1204 + ast_log(LOG_DEBUG, "Unable to register channel class %s\n", type);
1205 + return -1;
1206 + }
1207 + ast_cli_register(&cli_dev_state);
1208 + ast_manager_register2( "Devstate", EVENT_FLAG_CALL, action_devstate, "Change a device state", mandescr_devstate );
1209 + return ast_register_application(app, devstate_exec, synopsis, descrip);
1210 +}
1211 +
1212 +int unload_module(void)
1213 +{
1214 + int res = 0;
1215 + STANDARD_HANGUP_LOCALUSERS;
1216 + ast_manager_unregister( "Devstate");
1217 + ast_cli_unregister(&cli_dev_state);
1218 + res = ast_unregister_application(app);
1219 + ast_channel_unregister(&devstate_tech);
1220 + return res;
1221 +}
1222 +
1223 +char *description(void)
1224 +{
1225 + return tdesc;
1226 +}
1227 +
1228 +int usecount(void)
1229 +{
1230 + int res;
1231 + STANDARD_USECOUNT(res);
1232 + return res;
1233 +}
1234 +
1235 +char *key()
1236 +{
1237 + return ASTERISK_GPL_KEY;
1238 +}
1239 diff -urN asterisk-1.2.7.1.orig/apps/app_dial.c asterisk-1.2.7.1/apps/app_dial.c
1240 --- asterisk-1.2.7.1.orig/apps/app_dial.c 2006-04-12 00:39:59.000000000 +0200
1241 +++ asterisk-1.2.7.1/apps/app_dial.c 2006-04-18 14:40:13.000000000 +0200
1242 @@ -11,6 +11,10 @@
1243 * the project provides a web site, mailing lists and IRC
1244 * channels for your use.
1245 *
1246 + * Copyright (C) 2004, Junghanns.NET GmbH
1247 + *
1248 + * Klaus-Peter Junghanns <kpj@junghanns.net>
1249 + *
1250 * This program is free software, distributed under the terms of
1251 * the GNU General Public License Version 2. See the LICENSE file
1252 * at the top of the source tree.
1253 @@ -114,7 +118,8 @@
1254 " Otherwise, the current extension is used.\n"
1255 " h - Allow the called party to hang up by sending the '*' DTMF digit.\n"
1256 " H - Allow the calling party to hang up by hitting the '*' DTMF digit.\n"
1257 -" j - Jump to priority n+101 if all of the requested channels were busy.\n"
1258 +" j - Jump to priority n+101 if the called party was busy.\n"
1259 +" Jump to priority n+201 if all of the requested channels were busy.\n"
1260 " L(x[:y][:z]) - Limit the call to 'x' ms. Play a warning when 'y' ms are\n"
1261 " left. Repeat the warning every 'z' ms. The following special\n"
1262 " variables can be used with this option:\n"
1263 @@ -159,8 +164,11 @@
1264 " family/key is not specified.\n"
1265 " r - Indicate ringing to the calling party. Pass no audio to the calling\n"
1266 " party until the called channel has answered.\n"
1267 +" R - indicate ringing to the calling party when the called party indicates\n"
1268 +" ringing, pass no audio until answered.\n"
1269 " S(x) - Hang up the call after 'x' seconds *after* the called party has\n"
1270 -" answered the call.\n"
1271 +" answered the call.\n"
1272 +" c - callback initiation, ring once and hangup.\n"
1273 " t - Allow the called party to transfer the calling party by sending the\n"
1274 " DTMF sequence defined in features.conf.\n"
1275 " T - Allow the calling party to transfer the called party by sending the\n"
1276 @@ -211,6 +219,8 @@
1277 OPT_CALLEE_MONITOR = (1 << 21),
1278 OPT_CALLER_MONITOR = (1 << 22),
1279 OPT_GOTO = (1 << 23),
1280 + OPT_NOINBAND = (1 << 24),
1281 + OPT_CALLBACK_INIT = (1 << 25),
1282 } dial_exec_option_flags;
1283
1284 #define DIAL_STILLGOING (1 << 30)
1285 @@ -249,6 +259,8 @@
1286 AST_APP_OPTION('p', OPT_SCREENING),
1287 AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
1288 AST_APP_OPTION('r', OPT_RINGBACK),
1289 + AST_APP_OPTION('R', OPT_NOINBAND),
1290 + AST_APP_OPTION('c', OPT_CALLBACK_INIT),
1291 AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
1292 AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
1293 AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
1294 @@ -386,7 +398,7 @@
1295 char *context = NULL;
1296 char cidname[AST_MAX_EXTENSION];
1297
1298 - single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK));
1299 + single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK | OPT_NOINBAND));
1300
1301 if (single) {
1302 /* Turn off hold music, etc */
1303 @@ -465,7 +477,7 @@
1304 if (option_verbose > 2)
1305 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
1306 /* Setup parameters */
1307 - o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
1308 + o->chan = ast_request(tech, in->nativeformats, stuff, &cause, NULL);
1309 if (!o->chan)
1310 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
1311 } else {
1312 @@ -581,12 +593,18 @@
1313 HANDLE_CAUSE(AST_CAUSE_CONGESTION, in);
1314 break;
1315 case AST_CONTROL_RINGING:
1316 - if (option_verbose > 2)
1317 - ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
1318 - if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) {
1319 - ast_indicate(in, AST_CONTROL_RINGING);
1320 - (*sentringing)++;
1321 - }
1322 + if (ast_test_flag(peerflags, OPT_CALLBACK_INIT)) {
1323 + if (option_verbose > 2)
1324 + ast_verbose( VERBOSE_PREFIX_3 "%s is ringing, hanging up.\n", o->chan->name);
1325 + return NULL;
1326 + } else {
1327 + if (option_verbose > 2)
1328 + ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
1329 + if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) {
1330 + ast_indicate(in, AST_CONTROL_RINGING);
1331 + (*sentringing)++;
1332 + }
1333 + }
1334 break;
1335 case AST_CONTROL_PROGRESS:
1336 if (option_verbose > 2)
1337 @@ -761,6 +779,7 @@
1338 int digit = 0, result = 0;
1339 time_t start_time, answer_time, end_time;
1340 struct ast_app *app = NULL;
1341 + char *aoceunits;
1342
1343 char *parse;
1344 AST_DECLARE_APP_ARGS(args,
1345 @@ -934,17 +953,24 @@
1346 }
1347
1348 if( privdb_val == AST_PRIVACY_DENY ) {
1349 + ast_copy_string(status, "NOANSWER", sizeof(status));
1350 ast_verbose( VERBOSE_PREFIX_3 "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
1351 res=0;
1352 goto out;
1353 }
1354 else if( privdb_val == AST_PRIVACY_KILL ) {
1355 - ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
1356 + ast_copy_string(status, "DONTCALL", sizeof(status));
1357 + if (option_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
1358 + ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
1359 + }
1360 res = 0;
1361 goto out; /* Is this right? */
1362 }
1363 else if( privdb_val == AST_PRIVACY_TORTURE ) {
1364 - ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 301);
1365 + ast_copy_string(status, "TORTURE", sizeof(status));
1366 + if (option_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
1367 + ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 301);
1368 + }
1369 res = 0;
1370 goto out; /* is this right??? */
1371
1372 @@ -981,7 +1007,7 @@
1373 /* If a channel group has been specified, get it for use when we create peer channels */
1374 outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
1375
1376 - ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP);
1377 + ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP| OPT_CALLBACK_INIT | OPT_NOINBAND);
1378 cur = args.peers;
1379 do {
1380 /* Remember where to start next time */
1381 @@ -1023,7 +1049,7 @@
1382 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
1383 }
1384 /* Request the peer */
1385 - tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
1386 + tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause, NULL);
1387 if (!tmp->chan) {
1388 /* If we can't, just go on to the next call */
1389 ast_log(LOG_NOTICE, "Unable to create channel of type '%s' (cause %d - %s)\n", tech, cause, ast_cause2str(cause));
1390 @@ -1054,7 +1080,7 @@
1391 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
1392 ast_hangup(tmp->chan);
1393 /* Setup parameters */
1394 - tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
1395 + tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause, NULL);
1396 if (!tmp->chan)
1397 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
1398 } else {
1399 @@ -1173,8 +1199,11 @@
1400 ast_indicate(chan, AST_CONTROL_RINGING);
1401 sentringing++;
1402 }
1403 - } else
1404 + } else {
1405 strcpy(status, "CHANUNAVAIL");
1406 + /* See if there is a special message */
1407 + ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
1408 + }
1409
1410 time(&start_time);
1411 peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, ast_test_flag(&opts, OPT_PRIORITY_JUMP), &result);
1412 @@ -1303,6 +1332,8 @@
1413 opt_args[OPT_ARG_PRIVACY], privcid);
1414 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_DENY);
1415 }
1416 + ast_copy_string(status, "NOANSWER", sizeof(status));
1417 +
1418 if (ast_test_flag(&opts, OPT_MUSICBACK)) {
1419 ast_moh_stop(chan);
1420 } else if (ast_test_flag(&opts, OPT_RINGBACK)) {
1421 @@ -1585,7 +1616,16 @@
1422 }
1423 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
1424 pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
1425 -
1426 +
1427 + /* forward AOC-E units from peer, if possible */
1428 + aoceunits = pbx_builtin_getvar_helper(peer, "AOCEUNITS");
1429 +
1430 + if (aoceunits) {
1431 + snprintf(toast, sizeof(toast), "%d", atoi(aoceunits));
1432 + // ast_log(LOG_NOTICE, "AOCEUNITS %s\n" , toast);
1433 + pbx_builtin_setvar_helper(chan, "AOCEUNITS", toast);
1434 + }
1435 +
1436 if (res != AST_PBX_NO_HANGUP_PEER) {
1437 if (!chan->_softhangup)
1438 chan->hangupcause = peer->hangupcause;
1439 diff -urN asterisk-1.2.7.1.orig/apps/app_directed_pickup.c asterisk-1.2.7.1/apps/app_directed_pickup.c
1440 --- asterisk-1.2.7.1.orig/apps/app_directed_pickup.c 2006-04-06 19:00:10.000000000 +0200
1441 +++ asterisk-1.2.7.1/apps/app_directed_pickup.c 2006-04-18 14:39:28.000000000 +0200
1442 @@ -41,7 +41,7 @@
1443 #include "asterisk/app.h"
1444
1445 static const char *tdesc = "Directed Call Pickup Application";
1446 -static const char *app = "Pickup";
1447 +static const char *app = "DPickup";
1448 static const char *synopsis = "Directed Call Pickup";
1449 static const char *descrip =
1450 " Pickup(extension[@context]): This application can pickup any ringing channel\n"
1451 diff -urN asterisk-1.2.7.1.orig/apps/app_meetme.c asterisk-1.2.7.1/apps/app_meetme.c
1452 --- asterisk-1.2.7.1.orig/apps/app_meetme.c 2006-04-07 00:15:20.000000000 +0200
1453 +++ asterisk-1.2.7.1/apps/app_meetme.c 2006-04-18 14:39:28.000000000 +0200
1454 @@ -455,7 +455,7 @@
1455 ast_copy_string(cnf->pin, pin, sizeof(cnf->pin));
1456 ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin));
1457 cnf->markedusers = 0;
1458 - cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo", NULL);
1459 + cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo", NULL, NULL);
1460 if (cnf->chan) {
1461 cnf->fd = cnf->chan->fds[0]; /* for use by conf_play() */
1462 } else {
1463 @@ -825,8 +825,9 @@
1464 char exitcontext[AST_MAX_CONTEXT] = "";
1465 char recordingtmp[AST_MAX_EXTENSION] = "";
1466 int dtmf;
1467 + int dyna_buff = CONF_SIZE;
1468 ZT_BUFFERINFO bi;
1469 - char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
1470 + char __buf[ZT_MAX_BUF_SPACE / ZT_DEFAULT_NUM_BUFS + AST_FRIENDLY_OFFSET];
1471 char *buf = __buf + AST_FRIENDLY_OFFSET;
1472
1473 if (!user) {
1474 @@ -992,7 +993,7 @@
1475 }
1476 /* Setup buffering information */
1477 memset(&bi, 0, sizeof(bi));
1478 - bi.bufsize = CONF_SIZE/2;
1479 + bi.bufsize = dyna_buff / 2;
1480 bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
1481 bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
1482 bi.numbufs = audio_buffers;
1483 @@ -1277,6 +1278,14 @@
1484 f = ast_read(c);
1485 if (!f)
1486 break;
1487 + if (f->datalen && f->datalen != dyna_buff) {
1488 + ast_log(LOG_NOTICE, "Audio bytes: %d Buffer size: %d\n", f->datalen, dyna_buff);
1489 + if (f->datalen < ZT_MAX_BUF_SPACE/audio_buffers) { /* skip too large frame to avoid overflow */
1490 + dyna_buff = f->datalen;
1491 + close(fd);
1492 + goto zapretry;
1493 + }
1494 + }
1495 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) {
1496 if (user->talk.actual)
1497 ast_frame_adjust_volume(f, user->talk.actual);
1498 @@ -1508,7 +1517,7 @@
1499 }
1500 ast_frfree(f);
1501 } else if (outfd > -1) {
1502 - res = read(outfd, buf, CONF_SIZE);
1503 + res = read(outfd, buf, dyna_buff);
1504 if (res > 0) {
1505 memset(&fr, 0, sizeof(fr));
1506 fr.frametype = AST_FRAME_VOICE;
1507 diff -urN asterisk-1.2.7.1.orig/apps/app_milliwatt.c asterisk-1.2.7.1/apps/app_milliwatt.c
1508 --- asterisk-1.2.7.1.orig/apps/app_milliwatt.c 2006-01-19 05:17:45.000000000 +0100
1509 +++ asterisk-1.2.7.1/apps/app_milliwatt.c 2006-04-18 14:39:28.000000000 +0200
1510 @@ -74,20 +74,28 @@
1511 {
1512 struct ast_frame wf;
1513 unsigned char buf[AST_FRIENDLY_OFFSET + 640];
1514 + const int maxsamples = (sizeof (buf) - AST_FRIENDLY_OFFSET) / sizeof (buf[0]);
1515 int i,*indexp = (int *) data;
1516
1517 - if (len + AST_FRIENDLY_OFFSET > sizeof(buf))
1518 - {
1519 - ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",(int)(sizeof(buf) - AST_FRIENDLY_OFFSET),len);
1520 - len = sizeof(buf) - AST_FRIENDLY_OFFSET;
1521 - }
1522 + /* Instead of len, use samples, because channel.c generator_force
1523 + * generate(chan, tmp, 0, 160) ignores len. In any case, len is
1524 + * a multiple of samples, given by number of samples times bytes per
1525 + * sample. In the case of ulaw, len = samples. for signed linear
1526 + * len = 2 * samples */
1527 +
1528 + if (samples > maxsamples)
1529 + {
1530 + ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n", maxsamples, samples);
1531 + samples = maxsamples;
1532 + }
1533 + len = samples * sizeof (buf[0]);
1534 wf.frametype = AST_FRAME_VOICE;
1535 wf.subclass = AST_FORMAT_ULAW;
1536 wf.offset = AST_FRIENDLY_OFFSET;
1537 wf.mallocd = 0;
1538 wf.data = buf + AST_FRIENDLY_OFFSET;
1539 wf.datalen = len;
1540 - wf.samples = wf.datalen;
1541 + wf.samples = samples;
1542 wf.src = "app_milliwatt";
1543 wf.delivery.tv_sec = 0;
1544 wf.delivery.tv_usec = 0;
1545 diff -urN asterisk-1.2.7.1.orig/apps/app_page.c asterisk-1.2.7.1/apps/app_page.c
1546 --- asterisk-1.2.7.1.orig/apps/app_page.c 2006-04-13 19:40:21.000000000 +0200
1547 +++ asterisk-1.2.7.1/apps/app_page.c 2006-04-18 14:39:28.000000000 +0200
1548 @@ -85,7 +85,7 @@
1549 {
1550 struct calloutdata *cd = data;
1551 ast_pbx_outgoing_app(cd->tech, AST_FORMAT_SLINEAR, cd->resource, 30000,
1552 - "MeetMe", cd->meetmeopts, NULL, 0, cd->cidnum, cd->cidname, cd->variables, NULL, NULL);
1553 + "MeetMe", cd->meetmeopts, NULL, 0, 0, cd->cidnum, cd->cidname, cd->variables, NULL, NULL, NULL);
1554 free(cd);
1555 return NULL;
1556 }
1557 diff -urN asterisk-1.2.7.1.orig/apps/app_parkandannounce.c asterisk-1.2.7.1/apps/app_parkandannounce.c
1558 --- asterisk-1.2.7.1.orig/apps/app_parkandannounce.c 2005-11-29 19:24:39.000000000 +0100
1559 +++ asterisk-1.2.7.1/apps/app_parkandannounce.c 2006-04-18 14:39:28.000000000 +0200
1560 @@ -183,7 +183,7 @@
1561
1562 memset(&oh, 0, sizeof(oh));
1563 oh.parent_channel = chan;
1564 - dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->cid.cid_num, chan->cid.cid_name, &oh);
1565 + dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, 0, chan->cid.cid_num, chan->cid.cid_name, &oh, NULL);
1566
1567 if(dchan) {
1568 if(dchan->_state == AST_STATE_UP) {
1569 diff -urN asterisk-1.2.7.1.orig/apps/app_pickup.c asterisk-1.2.7.1/apps/app_pickup.c
1570 --- asterisk-1.2.7.1.orig/apps/app_pickup.c 1970-01-01 01:00:00.000000000 +0100
1571 +++ asterisk-1.2.7.1/apps/app_pickup.c 2006-04-18 14:39:28.000000000 +0200
1572 @@ -0,0 +1,319 @@
1573 +/*
1574 + * Asterisk -- A telephony toolkit for Linux.
1575 + *
1576 + * Pickup, channel independent call pickup
1577 + *
1578 + * Copyright (C) 2004, Junghanns.NET GmbH
1579 + *
1580 + * Klaus-Peter Junghanns <kpj@junghanns.net>
1581 + *
1582 + * Copyright (C) 2004, Florian Overkamp <florian@obsimref.com>
1583 + *
1584 + * This program is free software, distributed under the terms of
1585 + * the GNU General Public License
1586 + */
1587 +
1588 +#include <stdlib.h>
1589 +#include <unistd.h>
1590 +#include <string.h>
1591 +#include <stdio.h>
1592 +#include <signal.h>
1593 +#include <pthread.h>
1594 +#include <asterisk/lock.h>
1595 +#include <asterisk/file.h>
1596 +#include <asterisk/logger.h>
1597 +#include <asterisk/channel.h>
1598 +#include <asterisk/pbx.h>
1599 +#include <asterisk/module.h>
1600 +#include <asterisk/features.h>
1601 +#include <asterisk/options.h>
1602 +
1603 +
1604 +static char *tdesc = "PickUp/PickDown/Steal/PickupChan/StealChan";
1605 +
1606 +static char *app = "PickUp";
1607 +
1608 +static char *synopsis = "Channel independent call pickup.";
1609 +
1610 +static char *descrip =
1611 +" PickDown([group]): Tries to pickup the first ringing channel with callgroup == group.\n"
1612 +" If called without the group argument, the pickupgroup of the channel will be used.\n";
1613 +
1614 +static char *app2 = "Steal";
1615 +
1616 +static char *synopsis2 = "Channel independent call stealing. Just like pickup but for answered channels.";
1617 +
1618 +static char *descrip2 =
1619 +" Steal([group]): Tries to steal the first bridged channel with callgroup == group.\n"
1620 +" If called without the group argument, the pickupgroup of the channel will be used.\n";
1621 +
1622 +static char *app3 = "PickDown";
1623 +
1624 +static char *synopsis3 = "Channel independent call pickdown.";
1625 +
1626 +static char *descrip3 =
1627 +" PickDown([group]): Tries to hangup the first ringing channel with callgroup == group.\n"
1628 +" If called without the group argument, the pickupgroup of the channel will be used.\n";
1629 +
1630 +static char *app4 = "PickupChan";
1631 +
1632 +static char *synopsis4 = "Channel independent call pickup.";
1633 +
1634 +static char *descrip4 =
1635 +" PickupChan(Technology/resource[&Technology2/resource2...]): Tries to pickup the first ringing channel in the parameter list.\n";
1636 +
1637 +static char *app5 = "StealChan";
1638 +
1639 +static char *synopsis5 = "Channel independent call stealing. Just like pickup but for answered channels.";
1640 +
1641 +static char *descrip5 =
1642 +" StealChan(Technology/resource[&Technology2/resource2...]): Tries to steal the first ringing channel in the parameter list.\n";
1643 +
1644 +STANDARD_LOCAL_USER;
1645 +
1646 +LOCAL_USER_DECL;
1647 +
1648 +static int my_pickup_call(struct ast_channel *chan, unsigned int pickupgroup, int chanstate, int bridge) {
1649 + struct ast_channel *cur;
1650 + int res = -1;
1651 + cur = ast_channel_walk_locked(NULL);
1652 + while(cur) {
1653 + if ((cur != chan) &&
1654 + (pickupgroup & cur->callgroup) &&
1655 + (cur->_state == chanstate)) {
1656 + break;
1657 + }
1658 + ast_mutex_unlock(&cur->lock);
1659 + cur = ast_channel_walk_locked(cur);
1660 + }
1661 + if (cur) {
1662 + if(option_verbose > 2) {
1663 + if (chanstate == AST_STATE_RINGING) {
1664 + if (bridge == 1) {
1665 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
1666 + } else {
1667 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
1668 + }
1669 + } else {
1670 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
1671 + }
1672 + }
1673 + if (bridge == 1) {
1674 + if (chan->_state != AST_STATE_UP) {
1675 + ast_answer(chan);
1676 + }
1677 + if (ast_channel_masquerade(cur, chan)) {
1678 + ast_log(LOG_ERROR, "unable to masquerade\n");
1679 + }
1680 + ast_mutex_unlock(&cur->lock);
1681 + ast_mutex_unlock(&chan->lock);
1682 + } else {
1683 + cur->_softhangup = AST_SOFTHANGUP_DEV;
1684 + ast_mutex_unlock(&cur->lock);
1685 + }
1686 + } else {
1687 + if(option_verbose > 2) {
1688 + ast_verbose(VERBOSE_PREFIX_3 "No channel found %d.\n",pickupgroup);
1689 + }
1690 + }
1691 + return res;
1692 +}
1693 +
1694 +static int my_pickup_channel(struct ast_channel *chan, void *data, int chanstate, int bridge) {
1695 + struct ast_channel *cur;
1696 + char channels[256];
1697 + char evalchan[256];
1698 + char *endptr;
1699 + int res = -1;
1700 + cur = ast_channel_walk_locked(NULL);
1701 + strncpy(channels, (char *)data, sizeof(channels) - 1);
1702 + while(cur) {
1703 + if ((cur != chan) &&
1704 + (cur->_state == chanstate)) {
1705 + /* This call is a candidate (correct ringstate and not ourselves), now check if the channel is in our list */
1706 + strncpy(evalchan, (char *)cur->name, sizeof(evalchan) - 1);
1707 + /* strip the subchannel tag */
1708 + endptr = strrchr(evalchan, '-');
1709 + if(endptr) {
1710 + *endptr = '\0';
1711 + }
1712 + endptr = strrchr(evalchan, '/');
1713 + if(endptr) {
1714 + *endptr = '\0';
1715 + }
1716 + /* check for each of the members if they match (probably a stristr will do ?) */
1717 + /* if we match the code, break */
1718 + if(strstr(channels, evalchan) != NULL) {
1719 + ast_verbose(VERBOSE_PREFIX_1 "Nice channel, I'll take it: %s\n",evalchan);
1720 + break;
1721 + }
1722 + }
1723 + ast_mutex_unlock(&cur->lock);
1724 + cur = ast_channel_walk_locked(cur);
1725 + }
1726 + if (cur) {
1727 + if(option_verbose > 2) {
1728 + if (chanstate == AST_STATE_RINGING) {
1729 + if (bridge == 1) {
1730 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
1731 + } else {
1732 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
1733 + }
1734 + } else {
1735 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
1736 + }
1737 + }
1738 + if (bridge == 1) {
1739 + if (chan->_state != AST_STATE_UP) {
1740 + ast_answer(chan);
1741 + }
1742 + if (ast_channel_masquerade(cur, chan)) {
1743 + ast_log(LOG_ERROR, "unable to masquerade\n");
1744 + }
1745 + ast_mutex_unlock(&cur->lock);
1746 + ast_mutex_unlock(&chan->lock);
1747 + } else {
1748 + cur->_softhangup = AST_SOFTHANGUP_DEV;
1749 + ast_mutex_unlock(&cur->lock);
1750 + }
1751 + } else {
1752 + if(option_verbose > 2) {
1753 + ast_verbose(VERBOSE_PREFIX_3 "No channel found %s.\n",channels);
1754 + }
1755 + }
1756 + return res;
1757 +}
1758 +
1759 +
1760 +static int pickup_exec(struct ast_channel *chan, void *data)
1761 +{
1762 + int res=0;
1763 + unsigned int pickupgroup=0;
1764 + struct localuser *u;
1765 + if (!data || !strlen(data)) {
1766 + pickupgroup = chan->pickupgroup;
1767 + } else {
1768 + pickupgroup = ast_get_group(data);
1769 + }
1770 + LOCAL_USER_ADD(u);
1771 + if (!res) {
1772 + res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 1);
1773 + }
1774 + if (res > 0)
1775 + res = 0;
1776 + LOCAL_USER_REMOVE(u);
1777 + return res;
1778 +}
1779 +
1780 +static int steal_exec(struct ast_channel *chan, void *data)
1781 +{
1782 + int res=0;
1783 + unsigned int pickupgroup=0;
1784 + struct localuser *u;
1785 + if (!data || !strlen(data)) {
1786 + pickupgroup = chan->pickupgroup;
1787 + } else {
1788 + pickupgroup = ast_get_group(data);
1789 + }
1790 + LOCAL_USER_ADD(u);
1791 + if (!res) {
1792 + res = my_pickup_call(chan, pickupgroup, AST_STATE_UP, 1);
1793 + }
1794 + if (res > 0)
1795 + res = 0;
1796 + LOCAL_USER_REMOVE(u);
1797 + return res;
1798 +}
1799 +
1800 +static int pickdown_exec(struct ast_channel *chan, void *data)
1801 +{
1802 + int res=0;
1803 + unsigned int pickupgroup=0;
1804 + struct localuser *u;
1805 + if (!data || !strlen(data)) {
1806 + pickupgroup = chan->pickupgroup;
1807 + } else {
1808 + pickupgroup = ast_get_group(data);
1809 + }
1810 + LOCAL_USER_ADD(u);
1811 + if (!res) {
1812 + res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 0);
1813 + }
1814 + if (res > 0)
1815 + res = 0;
1816 + LOCAL_USER_REMOVE(u);
1817 + return res;
1818 +}
1819 +
1820 +static int pickupchan_exec(struct ast_channel *chan, void *data) {
1821 + int res=0;
1822 + struct localuser *u;
1823 + if (!data) {
1824 + ast_log(LOG_WARNING, "PickupChan requires an argument (technology1/number1&technology2/number2...)\n");
1825 + return -1;
1826 + }
1827 + LOCAL_USER_ADD(u);
1828 + if (!res) {
1829 + res = my_pickup_channel(chan, data, AST_STATE_RINGING, 1);
1830 + }
1831 + if (res > 0)
1832 + res = 0;
1833 + LOCAL_USER_REMOVE(u);
1834 + return res;
1835 +}
1836 +
1837 +static int stealchan_exec(struct ast_channel *chan, void *data)
1838 +{
1839 + int res=0;
1840 + struct localuser *u;
1841 + if (!data) {
1842 + ast_log(LOG_WARNING, "StealChan requires an argument (technology1/number1&technology2/number2...)\n");
1843 + return -1;
1844 + }
1845 +
1846 + LOCAL_USER_ADD(u);
1847 + if (!res) {
1848 + res = my_pickup_channel(chan, data, AST_STATE_UP, 1);
1849 + }
1850 + if (res > 0)
1851 + res = 0;
1852 + LOCAL_USER_REMOVE(u);
1853 + return res;
1854 +}
1855 +
1856 +
1857 +int unload_module(void)
1858 +{
1859 + STANDARD_HANGUP_LOCALUSERS;
1860 + ast_unregister_application(app5);
1861 + ast_unregister_application(app4);
1862 + ast_unregister_application(app3);
1863 + ast_unregister_application(app2);
1864 + return ast_unregister_application(app);
1865 +}
1866 +
1867 +int load_module(void)
1868 +{
1869 + ast_register_application(app5, stealchan_exec, synopsis5, descrip5);
1870 + ast_register_application(app4, pickupchan_exec, synopsis4, descrip4);
1871 + ast_register_application(app3, pickdown_exec, synopsis3, descrip3);
1872 + ast_register_application(app2, steal_exec, synopsis2, descrip2);
1873 + return ast_register_application(app, pickup_exec, synopsis, descrip);
1874 +}
1875 +
1876 +char *description(void)
1877 +{
1878 + return tdesc;
1879 +}
1880 +
1881 +int usecount(void)
1882 +{
1883 + int res;
1884 + STANDARD_USECOUNT(res);
1885 + return res;
1886 +}
1887 +
1888 +char *key()
1889 +{
1890 + return ASTERISK_GPL_KEY;
1891 +}
1892 diff -urN asterisk-1.2.7.1.orig/apps/app_queue.c asterisk-1.2.7.1/apps/app_queue.c
1893 --- asterisk-1.2.7.1.orig/apps/app_queue.c 2006-04-04 19:59:18.000000000 +0200
1894 +++ asterisk-1.2.7.1/apps/app_queue.c 2006-04-18 14:39:28.000000000 +0200
1895 @@ -501,7 +501,7 @@
1896 return NULL;
1897 }
1898
1899 -static int statechange_queue(const char *dev, int state, void *ign)
1900 +static int statechange_queue(const char *dev, int state, void *ign, char *cid_num, char *cid_name)
1901 {
1902 /* Avoid potential for deadlocks by spawning a new thread to handle
1903 the event */
1904 @@ -1386,7 +1386,7 @@
1905 location = "";
1906
1907 /* Request the peer */
1908 - tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status);
1909 + tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status, NULL);
1910 if (!tmp->chan) { /* If we can't, just go on to the next call */
1911 #if 0
1912 ast_log(LOG_NOTICE, "Unable to create channel of type '%s' for Queue\n", cur->tech);
1913 @@ -1692,7 +1692,7 @@
1914 if (option_verbose > 2)
1915 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
1916 /* Setup parameters */
1917 - o->chan = ast_request(tech, in->nativeformats, stuff, &status);
1918 + o->chan = ast_request(tech, in->nativeformats, stuff, &status, NULL);
1919 if (status != o->oldstatus)
1920 update_dial_status(qe->parent, o->member, status);
1921 if (!o->chan) {
1922 diff -urN asterisk-1.2.7.1.orig/apps/app_readfile.c asterisk-1.2.7.1/apps/app_readfile.c
1923 --- asterisk-1.2.7.1.orig/apps/app_readfile.c 2006-03-23 21:13:48.000000000 +0100
1924 +++ asterisk-1.2.7.1/apps/app_readfile.c 2006-04-18 14:39:28.000000000 +0200
1925 @@ -40,7 +40,7 @@
1926 #include "asterisk/app.h"
1927 #include "asterisk/module.h"
1928
1929 -static char *tdesc = "Stores output of file into a variable";
1930 +static char *tdesc = "Stores content of file into a variable";
1931
1932 static char *app_readfile = "ReadFile";
1933
1934 diff -urN asterisk-1.2.7.1.orig/apps/app_segfault.c asterisk-1.2.7.1/apps/app_segfault.c
1935 --- asterisk-1.2.7.1.orig/apps/app_segfault.c 1970-01-01 01:00:00.000000000 +0100
1936 +++ asterisk-1.2.7.1/apps/app_segfault.c 2006-04-18 14:39:28.000000000 +0200
1937 @@ -0,0 +1,75 @@
1938 +/*
1939 + * Segfault application
1940 + *
1941 + * An application to provoke a segmentation fault from the dialplan.
1942 + * (I know what you are thinking now...., but since Asterisk is too stable...
1943 + * I needed something to test my failover switches.)
1944 + *
1945 + * Copyright (C) 2005 Junghanns.NET GmbH
1946 + * Klaus-Peter Junghanns <kpj@junghanns.net>
1947 + *
1948 + * This program is free software, distributed under the terms of
1949 + * the GNU General Public License. THIS APPLICATION _WILL_ CRASH YOUR
1950 + * ASTERISK SERVER SO OF COURSE THERE IS NOT LIABILITY FOR NOTHING!
1951 + */
1952 +
1953 +#include <stdlib.h>
1954 +#include <unistd.h>
1955 +#include <string.h>
1956 +#include <stdio.h>
1957 +#include <asterisk/lock.h>
1958 +#include <asterisk/file.h>
1959 +#include <asterisk/logger.h>
1960 +#include <asterisk/channel.h>
1961 +#include <asterisk/pbx.h>
1962 +#include <asterisk/module.h>
1963 +
1964 +static char *tdesc = "Application for crashing Asterisk with a segmentation fault";
1965 +
1966 +static char *app = "Segfault";
1967 +
1968 +static char *synopsis = "This application will crash Asterisk with a segmentation fault.";
1969 +
1970 +static char *descrip =
1971 +" Segfault(): Crash with a segfault. Never returns nufin.\n";
1972 +
1973 +STANDARD_LOCAL_USER;
1974 +
1975 +LOCAL_USER_DECL;
1976 +
1977 +static int segfault_exec(struct ast_channel *chan, void *data)
1978 +{
1979 + struct localuser *u;
1980 + LOCAL_USER_ADD(u);
1981 + ((char *)0)[0] = 0;
1982 + LOCAL_USER_REMOVE(u);
1983 + return 0;
1984 +}
1985 +
1986 +int unload_module(void)
1987 +{
1988 + STANDARD_HANGUP_LOCALUSERS;
1989 + return ast_unregister_application(app);
1990 +}
1991 +
1992 +int load_module(void)
1993 +{
1994 + return ast_register_application(app, segfault_exec, synopsis, descrip);
1995 +}
1996 +
1997 +char *description(void)
1998 +{
1999 + return tdesc;
2000 +}
2001 +
2002 +int usecount(void)
2003 +{
2004 + int res;
2005 + STANDARD_USECOUNT(res);
2006 + return res;
2007 +}
2008 +
2009 +char *key()
2010 +{
2011 + return ASTERISK_GPL_KEY;
2012 +}
2013 diff -urN asterisk-1.2.7.1.orig/apps/app_sms.c asterisk-1.2.7.1/apps/app_sms.c
2014 --- asterisk-1.2.7.1.orig/apps/app_sms.c 2005-12-26 19:19:12.000000000 +0100
2015 +++ asterisk-1.2.7.1/apps/app_sms.c 2006-04-18 14:39:28.000000000 +0200
2016 @@ -1179,32 +1179,31 @@
2017 {
2018 struct ast_frame f = { 0 };
2019 unsigned char waste[AST_FRIENDLY_OFFSET];
2020 +#define MAXSAMPLES (800)
2021 #ifdef OUTALAW
2022 - unsigned char buf[800];
2023 + unsigned char buf[MAXSAMPLES];
2024 #else
2025 - signed short buf[800];
2026 + signed short buf[MAXSAMPLES];
2027 #endif
2028 +#define SAMPLE2LEN (sizeof (buf[0]))
2029 sms_t *h = data;
2030 int i;
2031
2032 - if (len > sizeof (buf)) {
2033 - ast_log (LOG_WARNING, "Only doing %d bytes (%d bytes requested)\n", (int)(sizeof (buf) / sizeof (signed short)), len);
2034 - len = sizeof (buf);
2035 -#ifdef OUTALAW
2036 - samples = len;
2037 -#else
2038 - samples = len / 2;
2039 -#endif
2040 + if (samples > MAXSAMPLES) {
2041 + ast_log (LOG_WARNING, "Only doing %d samples (%d requested)\n",
2042 + MAXSAMPLES, samples);
2043 + samples = MAXSAMPLES;
2044 }
2045 - waste[0] = 0; /* make compiler happy */
2046 + len = samples * SAMPLE2LEN;
2047 +
2048 + waste[0] = 0; /* make compiler happy */
2049 f.frametype = AST_FRAME_VOICE;
2050 #ifdef OUTALAW
2051 f.subclass = AST_FORMAT_ALAW;
2052 - f.datalen = samples;
2053 #else
2054 f.subclass = AST_FORMAT_SLINEAR;
2055 - f.datalen = samples * 2;
2056 #endif
2057 + f.datalen = len;
2058 f.offset = AST_FRIENDLY_OFFSET;
2059 f.mallocd = 0;
2060 f.data = buf;
2061 @@ -1256,6 +1255,8 @@
2062 return -1;
2063 }
2064 return 0;
2065 +#undef SAMPLE2LEN
2066 +#undef MAXSAMPLES
2067 }
2068
2069 static void sms_process (sms_t * h, int samples, signed short *data)
2070 diff -urN asterisk-1.2.7.1.orig/apps/app_zapras.c asterisk-1.2.7.1/apps/app_zapras.c
2071 --- asterisk-1.2.7.1.orig/apps/app_zapras.c 2005-11-29 19:24:39.000000000 +0100
2072 +++ asterisk-1.2.7.1/apps/app_zapras.c 2006-04-18 14:39:28.000000000 +0200
2073 @@ -182,7 +182,7 @@
2074 }
2075 }
2076 /* Throw back into audio mode */
2077 - x = 1;
2078 + x = 0;
2079 ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
2080
2081 /* Restore saved values */
2082 diff -urN asterisk-1.2.7.1.orig/asterisk.c asterisk-1.2.7.1/asterisk.c
2083 --- asterisk-1.2.7.1.orig/asterisk.c 2006-04-11 23:55:51.000000000 +0200
2084 +++ asterisk-1.2.7.1/asterisk.c 2006-04-18 14:39:28.000000000 +0200
2085 @@ -228,6 +228,7 @@
2086 char ast_config_AST_CTL_OWNER[AST_CONFIG_MAX_PATH] = "\0";
2087 char ast_config_AST_CTL_GROUP[AST_CONFIG_MAX_PATH] = "\0";
2088 char ast_config_AST_CTL[AST_CONFIG_MAX_PATH] = "asterisk.ctl";
2089 +char ast_config_AST_SYMBOLIC_NAME[20];
2090
2091 static char *_argv[256];
2092 static int shuttingdown = 0;
2093 @@ -1887,6 +1888,7 @@
2094 ast_copy_string(ast_config_AST_PID, AST_PID, sizeof(ast_config_AST_PID));
2095 ast_copy_string(ast_config_AST_SOCKET, AST_SOCKET, sizeof(ast_config_AST_SOCKET));
2096 ast_copy_string(ast_config_AST_RUN_DIR, AST_RUN_DIR, sizeof(ast_config_AST_RUN_DIR));
2097 + ast_copy_string(ast_config_AST_SYMBOLIC_NAME, AST_SYMBOLIC_NAME, sizeof(ast_config_AST_SYMBOLIC_NAME));
2098
2099 /* no asterisk.conf? no problem, use buildtime config! */
2100 if (!cfg) {
2101 @@ -1926,6 +1928,8 @@
2102 ast_copy_string(ast_config_AST_RUN_DIR, v->value, sizeof(ast_config_AST_RUN_DIR));
2103 } else if (!strcasecmp(v->name, "astmoddir")) {
2104 ast_copy_string(ast_config_AST_MODULE_DIR, v->value, sizeof(ast_config_AST_MODULE_DIR));
2105 + } else if (!strcasecmp(v->name, "uniquename")) {
2106 + strncpy(ast_config_AST_SYMBOLIC_NAME,v->value,sizeof(ast_config_AST_SYMBOLIC_NAME));
2107 }
2108 v = v->next;
2109 }
2110 diff -urN asterisk-1.2.7.1.orig/build_tools/make_defaults_h asterisk-1.2.7.1/build_tools/make_defaults_h
2111 --- asterisk-1.2.7.1.orig/build_tools/make_defaults_h 2005-06-20 19:26:08.000000000 +0200
2112 +++ asterisk-1.2.7.1/build_tools/make_defaults_h 2006-04-18 14:39:28.000000000 +0200
2113 @@ -16,6 +16,7 @@
2114 #define AST_KEY_DIR "${INSTALL_PATH}${ASTVARLIBDIR}/keys"
2115 #define AST_DB "${INSTALL_PATH}${ASTVARLIBDIR}/astdb"
2116 #define AST_TMP_DIR "${INSTALL_PATH}${ASTSPOOLDIR}/tmp"
2117 +#define AST_SYMBOLIC_NAME "asterisk"
2118
2119 #define AST_CONFIG_FILE "${INSTALL_PATH}${ASTCONFPATH}"
2120
2121 diff -urN asterisk-1.2.7.1.orig/channel.c asterisk-1.2.7.1/channel.c
2122 --- asterisk-1.2.7.1.orig/channel.c 2006-04-11 23:35:52.000000000 +0200
2123 +++ asterisk-1.2.7.1/channel.c 2006-04-18 14:39:28.000000000 +0200
2124 @@ -94,8 +94,8 @@
2125 */
2126 static int shutting_down = 0;
2127
2128 -AST_MUTEX_DEFINE_STATIC(uniquelock);
2129 static int uniqueint = 0;
2130 +AST_MUTEX_DEFINE_EXPORTED(uniquelock);
2131
2132 unsigned long global_fin = 0, global_fout = 0;
2133
2134 @@ -512,6 +512,17 @@
2135 .description = "Null channel (should not see this)",
2136 };
2137
2138 +char *ast_alloc_uniqueid(void) {
2139 + char *uniqueid;
2140 + uniqueid = malloc(64);
2141 + if (!uniqueid) return NULL;
2142 + ast_mutex_lock(&uniquelock);
2143 + snprintf(uniqueid, 63, "%s-%d-%li.%d", ast_config_AST_SYMBOLIC_NAME, ast_mainpid, (long)time(NULL), uniqueint++);
2144 + ast_mutex_unlock(&uniquelock);
2145 + return uniqueid;
2146 +}
2147 +
2148 +
2149 /*--- ast_channel_alloc: Create a new channel structure */
2150 struct ast_channel *ast_channel_alloc(int needqueue)
2151 {
2152 @@ -519,6 +530,7 @@
2153 int x;
2154 int flags;
2155 struct varshead *headp;
2156 + char *tmpuniqueid;
2157
2158
2159 /* If shutting down, don't allocate any new channels */
2160 @@ -584,9 +596,12 @@
2161 tmp->data = NULL;
2162 tmp->fin = global_fin;
2163 tmp->fout = global_fout;
2164 - ast_mutex_lock(&uniquelock);
2165 - snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), "%li.%d", (long) time(NULL), uniqueint++);
2166 - ast_mutex_unlock(&uniquelock);
2167 + tmpuniqueid = ast_alloc_uniqueid();
2168 + snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), tmpuniqueid);
2169 + if (tmpuniqueid) {
2170 + free(tmpuniqueid);
2171 + tmpuniqueid = NULL;
2172 + }
2173 headp = &tmp->varshead;
2174 ast_mutex_init(&tmp->lock);
2175 AST_LIST_HEAD_INIT_NOLOCK(headp);
2176 @@ -729,7 +744,7 @@
2177 */
2178 static struct ast_channel *channel_find_locked(const struct ast_channel *prev,
2179 const char *name, const int namelen,
2180 - const char *context, const char *exten)
2181 + const char *context, const char *exten, const char *uniqueid)
2182 {
2183 const char *msg = prev ? "deadlock" : "initial deadlock";
2184 int retries, done;
2185 @@ -740,9 +755,14 @@
2186 for (c = channels; c; c = c->next) {
2187 if (!prev) {
2188 /* want head of list */
2189 - if (!name && !exten)
2190 + if (!name && !exten && !uniqueid)
2191 break;
2192 - if (name) {
2193 + if (uniqueid) {
2194 + if (!strcasecmp(c->uniqueid, uniqueid))
2195 + break;
2196 + else
2197 + continue;
2198 + } else if (name) {
2199 /* want match by full name */
2200 if (!namelen) {
2201 if (!strcasecmp(c->name, name))
2202 @@ -793,33 +813,39 @@
2203 /*--- ast_channel_walk_locked: Browse channels in use */
2204 struct ast_channel *ast_channel_walk_locked(const struct ast_channel *prev)
2205 {
2206 - return channel_find_locked(prev, NULL, 0, NULL, NULL);
2207 + return channel_find_locked(prev, NULL, 0, NULL, NULL, NULL);
2208 }
2209
2210 /*--- ast_get_channel_by_name_locked: Get channel by name and lock it */
2211 struct ast_channel *ast_get_channel_by_name_locked(const char *name)
2212 {
2213 - return channel_find_locked(NULL, name, 0, NULL, NULL);
2214 + return channel_find_locked(NULL, name, 0, NULL, NULL, NULL);
2215 }
2216
2217 /*--- ast_get_channel_by_name_prefix_locked: Get channel by name prefix and lock it */
2218 struct ast_channel *ast_get_channel_by_name_prefix_locked(const char *name, const int namelen)
2219 {
2220 - return channel_find_locked(NULL, name, namelen, NULL, NULL);
2221 + return channel_find_locked(NULL, name, namelen, NULL, NULL, NULL);
2222 }
2223
2224 /*--- ast_walk_channel_by_name_prefix_locked: Get next channel by name prefix and lock it */
2225 struct ast_channel *ast_walk_channel_by_name_prefix_locked(struct ast_channel *chan, const char *name, const int namelen)
2226 {
2227 - return channel_find_locked(chan, name, namelen, NULL, NULL);
2228 + return channel_find_locked(chan, name, namelen, NULL, NULL, NULL);
2229 }
2230
2231 /*--- ast_get_channel_by_exten_locked: Get channel by exten (and optionally context) and lock it */
2232 struct ast_channel *ast_get_channel_by_exten_locked(const char *exten, const char *context)
2233 {
2234 - return channel_find_locked(NULL, NULL, 0, context, exten);
2235 + return channel_find_locked(NULL, NULL, 0, context, exten, NULL);
2236 }
2237
2238 +struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid)
2239 +{
2240 + return channel_find_locked(NULL, NULL, 0, NULL, NULL, uniqueid);
2241 +}
2242 +
2243 +
2244 /*--- ast_safe_sleep_conditional: Wait, look for hangups and condition arg */
2245 int ast_safe_sleep_conditional( struct ast_channel *chan, int ms,
2246 int (*cond)(void*), void *data )
2247 @@ -912,8 +938,10 @@
2248 free(chan->tech_pvt);
2249 }
2250
2251 - if (chan->sched)
2252 - sched_context_destroy(chan->sched);
2253 + if (chan->sched) {
2254 + sched_context_destroy(chan->sched);
2255 + chan->sched = NULL;
2256 + }
2257
2258 ast_copy_string(name, chan->name, sizeof(name));
2259
2260 @@ -956,10 +984,11 @@
2261 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries)))
2262 ast_var_delete(vardata);
2263
2264 +
2265 free(chan);
2266 ast_mutex_unlock(&chlock);
2267
2268 - ast_device_state_changed_literal(name);
2269 + ast_device_state_changed_literal(name, NULL, NULL);
2270 }
2271
2272 int ast_channel_spy_add(struct ast_channel *chan, struct ast_channel_spy *spy)
2273 @@ -2362,7 +2391,7 @@
2274 &chan->writetrans, 1);
2275 }
2276
2277 -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)
2278 +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)
2279 {
2280 int state = 0;
2281 int cause = 0;
2282 @@ -2370,7 +2399,7 @@
2283 struct ast_frame *f;
2284 int res = 0;
2285
2286 - chan = ast_request(type, format, data, &cause);
2287 + chan = ast_request(type, format, data, &cause, uniqueid);
2288 if (chan) {
2289 if (oh) {
2290 if (oh->vars)
2291 @@ -2384,6 +2413,7 @@
2292 }
2293 ast_set_callerid(chan, cid_num, cid_name, cid_num);
2294
2295 + chan->cid.cid_pres = callingpres;
2296 if (!ast_call(chan, data, 0)) {
2297 res = 1; /* in case chan->_state is already AST_STATE_UP */
2298 while (timeout && (chan->_state != AST_STATE_UP)) {
2299 @@ -2407,6 +2437,7 @@
2300 if (f->subclass == AST_CONTROL_RINGING)
2301 state = AST_CONTROL_RINGING;
2302 else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
2303 + res = 0;
2304 state = f->subclass;
2305 ast_frfree(f);
2306 break;
2307 @@ -2476,12 +2507,12 @@
2308 return chan;
2309 }
2310
2311 -struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, const char *cidnum, const char *cidname)
2312 +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)
2313 {
2314 - return __ast_request_and_dial(type, format, data, timeout, outstate, cidnum, cidname, NULL);
2315 + return __ast_request_and_dial(type, format, data, timeout, outstate, 0, cidnum, cidname, NULL, uniqueid);
2316 }
2317
2318 -struct ast_channel *ast_request(const char *type, int format, void *data, int *cause)
2319 +struct ast_channel *ast_request(const char *type, int format, void *data, int *cause, char *uniqueid)
2320 {
2321 struct chanlist *chan;
2322 struct ast_channel *c;
2323 @@ -2518,6 +2549,7 @@
2324 if (!(c = chan->tech->requester(type, capabilities, data, cause)))
2325 return NULL;
2326
2327 + if (uniqueid) strncpy(c->uniqueid, uniqueid, sizeof(c->uniqueid));
2328 if (c->_state == AST_STATE_DOWN) {
2329 manager_event(EVENT_FLAG_CALL, "Newchannel",
2330 "Channel: %s\r\n"
2331 @@ -2765,6 +2797,29 @@
2332 return res;
2333 }
2334
2335 +int ast_channel_masquerade_locked(struct ast_channel *original, struct ast_channel *clone)
2336 +{
2337 + struct ast_frame null = { AST_FRAME_NULL, };
2338 + int res = -1;
2339 + ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n",
2340 + clone->name, original->name);
2341 + if (original->masq) {
2342 + ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n",
2343 + original->masq->name, original->name);
2344 + } else if (clone->masqr) {
2345 + ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n",
2346 + clone->name, clone->masqr->name);
2347 + } else {
2348 + original->masq = clone;
2349 + clone->masqr = original;
2350 + ast_queue_frame(original, &null);
2351 + ast_queue_frame(clone, &null);
2352 + ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name);
2353 + res = 0;
2354 + }
2355 + return res;
2356 +}
2357 +
2358 void ast_change_name(struct ast_channel *chan, char *newname)
2359 {
2360 char tmp[256];
2361 @@ -3131,15 +3186,14 @@
2362 );
2363 }
2364
2365 -int ast_setstate(struct ast_channel *chan, int state)
2366 -{
2367 +int ast_setstate_and_cid(struct ast_channel *chan, int state, char *cid_num, char *cid_name) {
2368 int oldstate = chan->_state;
2369
2370 if (oldstate == state)
2371 return 0;
2372
2373 chan->_state = state;
2374 - ast_device_state_changed_literal(chan->name);
2375 + ast_device_state_changed_literal(chan->name, cid_num, cid_name);
2376 manager_event(EVENT_FLAG_CALL,
2377 (oldstate == AST_STATE_DOWN) ? "Newchannel" : "Newstate",
2378 "Channel: %s\r\n"
2379 @@ -3155,6 +3209,10 @@
2380 return 0;
2381 }
2382
2383 +int ast_setstate(struct ast_channel *chan, int state) {
2384 + return ast_setstate_and_cid(chan, state, NULL, NULL);
2385 +}
2386 +
2387 /*--- Find bridged channel */
2388 struct ast_channel *ast_bridged_channel(struct ast_channel *chan)
2389 {
2390 @@ -3332,6 +3390,7 @@
2391 char callee_warning = 0;
2392 int to;
2393
2394 +
2395 if (c0->_bridge) {
2396 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n",
2397 c0->name, c0->_bridge->name);
2398 @@ -3342,6 +3401,10 @@
2399 c1->name, c1->_bridge->name);
2400 return -1;
2401 }
2402 +
2403 + if (IS_DIGITAL(c0->transfercapability) || IS_DIGITAL(c1->transfercapability)) {
2404 + config->flags = 0;
2405 + }
2406
2407 /* Stop if we're a zombie or need a soft hangup */
2408 if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) ||
2409 diff -urN asterisk-1.2.7.1.orig/channels/Makefile asterisk-1.2.7.1/channels/Makefile
2410 --- asterisk-1.2.7.1.orig/channels/Makefile 2005-12-15 11:52:30.000000000 +0100
2411 +++ asterisk-1.2.7.1/channels/Makefile 2006-04-18 14:39:28.000000000 +0200
2412 @@ -102,6 +102,11 @@
2413 ZAPR2=-lmfcr2
2414 endif
2415
2416 +ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/lib/libgsmat.so.1)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/lib/libgsmat.so.1),)
2417 + CFLAGS+=-DZAPATA_GSM
2418 + ZAPGSM=-lgsmat
2419 +endif
2420 +
2421 ALSA_SRC=chan_alsa.c
2422
2423 ifneq ($(wildcard alsa-monitor.h),)
2424 @@ -122,6 +127,35 @@
2425 endif
2426 endif # WITHOUT_ZAPTEL
2427
2428 +ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/capi20.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/capi20.h),)
2429 + CHANNEL_LIBS+=chan_capi.so
2430 +# uncomment the following line if you really never ever want early b3 connects,
2431 +# you can also configure it in the dialstring, this is just for performance
2432 +# NOTE: this is probably obsolete by using the "R" dial option
2433 +#CFLAGS+=-DCAPI_NEVER_EVER_EARLY_B3_CONNECTS
2434 +
2435 +# uncommnet next line to force dtmf software detection/generation, can also be configured
2436 +# in capi.conf on a perdevice basis (softdtmf=1)
2437 +#CFLAGS+=-DCAPI_FORCE_SOFTWARE_DTMF
2438 +
2439 +# uncomment the next line if you are in the ulaw world
2440 +#CFLAGS+=-DCAPI_ULAW
2441 +
2442 +# very experimental echo squelching
2443 +CFLAGS+=-DCAPI_ES
2444 +
2445 +#gains
2446 +CFLAGS+=-DCAPI_GAIN
2447 +
2448 +# what do to with call waiting connect indications?
2449 +# uncomment the next line for call deflection in that case
2450 +CFLAGS+=-DCAPI_DEFLECT_ON_CIRCUITBUSY
2451 +
2452 +# audio sync
2453 +CFLAGS+=-DCAPI_SYNC
2454 +
2455 +endif
2456 +
2457 ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/vpbapi.h),)
2458 CHANNEL_LIBS+=chan_vpb.so
2459 CFLAGS+=-DLINUX
2460 @@ -204,7 +238,7 @@
2461 $(CC) -c $(CFLAGS) -o chan_zap.o chan_zap.c
2462
2463 chan_zap.so: chan_zap.o
2464 - $(CC) $(SOLINK) -o $@ $< $(ZAPPRI) $(ZAPR2) -ltonezone
2465 + $(CC) $(SOLINK) -o $@ $< $(ZAPPRI) $(ZAPGSM) $(ZAPR2) -ltonezone
2466
2467 chan_sip.so: chan_sip.o
2468 $(CC) $(SOLINK) -o $@ ${CYGSOLINK} chan_sip.o ${CYGSOLIB}
2469 @@ -220,6 +254,9 @@
2470 chan_nbs.so: chan_nbs.o
2471 $(CC) $(SOLINK) -o $@ $< -lnbs
2472
2473 +chan_capi.so: chan_capi.o
2474 + $(CC) $(SOLINK) -o $@ $< -lcapi20
2475 +
2476 chan_vpb.o: chan_vpb.c
2477 $(CXX) -c $(CFLAGS) -o $@ chan_vpb.c
2478
2479 diff -urN asterisk-1.2.7.1.orig/channels/chan_agent.c asterisk-1.2.7.1/channels/chan_agent.c
2480 --- asterisk-1.2.7.1.orig/channels/chan_agent.c 2006-02-15 02:21:33.000000000 +0100
2481 +++ asterisk-1.2.7.1/channels/chan_agent.c 2006-04-18 14:39:28.000000000 +0200
2482 @@ -1331,7 +1331,7 @@
2483 chan = agent_new(p, AST_STATE_DOWN);
2484 } else if (!p->owner && !ast_strlen_zero(p->loginchan)) {
2485 /* Adjustable agent */
2486 - p->chan = ast_request("Local", format, p->loginchan, cause);
2487 + p->chan = ast_request("Local", format, p->loginchan, cause, NULL);
2488 if (p->chan)
2489 chan = agent_new(p, AST_STATE_DOWN);
2490 }
2491 diff -urN asterisk-1.2.7.1.orig/channels/chan_capi.c asterisk-1.2.7.1/channels/chan_capi.c
2492 --- asterisk-1.2.7.1.orig/channels/chan_capi.c 1970-01-01 01:00:00.000000000 +0100
2493 +++ asterisk-1.2.7.1/channels/chan_capi.c 2006-04-18 14:39:28.000000000 +0200
2494 @@ -0,0 +1,2888 @@
2495 +/*
2496 + * (CAPI*)
2497 + *
2498 + * An implementation of Common ISDN API 2.0 for Asterisk
2499 + *
2500 + * Copyright (C) 2002, 2003, 2004, 2005 Junghanns.NET GmbH
2501 + *
2502 + * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
2503 + *
2504 + * This program is free software and may be modified and
2505 + * distributed under the terms of the GNU Public License.
2506 + */
2507 +
2508 +#include <sys/time.h>
2509 +#include <sys/signal.h>
2510 +#include <stdlib.h>
2511 +#include <stdio.h>
2512 +#include <string.h>
2513 +#include <errno.h>
2514 +#include <unistd.h>
2515 +#include <fcntl.h>
2516 +#include <sys/types.h>
2517 +#include <asterisk/lock.h>
2518 +#include <asterisk/frame.h>
2519 +#include <asterisk/channel.h>
2520 +#include <asterisk/logger.h>
2521 +#include <asterisk/module.h>
2522 +#include <asterisk/pbx.h>
2523 +#include <asterisk/config.h>
2524 +#include <asterisk/options.h>
2525 +#include <asterisk/features.h>
2526 +#include <asterisk/utils.h>
2527 +#include <asterisk/cli.h>
2528 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
2529 +#include <capi_bsd.h>
2530 +#else
2531 +#include <linux/capi.h>
2532 +#endif
2533 +#include <capi20.h>
2534 +#include <asterisk/dsp.h>
2535 +#include <asterisk/xlaw.h>
2536 +#include <asterisk/chan_capi.h>
2537 +
2538 +unsigned ast_capi_ApplID;
2539 +_cword ast_capi_MessageNumber=1;
2540 +static char desc[] = "Common ISDN API for Asterisk";
2541 +#ifdef CAPI_ULAW
2542 +static char tdesc[] = "Common ISDN API Driver (0.4.0) muLaw";
2543 +#else
2544 +static char tdesc[] = "Common ISDN API Driver (0.4.0) aLaw ";
2545 +#endif
2546 +static char type[] = "CAPI";
2547 +
2548 +
2549 +static int usecnt;
2550 +AST_MUTEX_DEFINE_STATIC(usecnt_lock);
2551 +AST_MUTEX_DEFINE_STATIC(iflock);
2552 +AST_MUTEX_DEFINE_STATIC(pipelock);
2553 +AST_MUTEX_DEFINE_STATIC(monlock);
2554 +AST_MUTEX_DEFINE_STATIC(contrlock);
2555 +AST_MUTEX_DEFINE_STATIC(capi_send_buffer_lock);
2556 +AST_MUTEX_DEFINE_STATIC(capi_put_lock);
2557 +
2558 +#ifdef CAPI_ULAW
2559 +static int capi_capability = AST_FORMAT_ULAW;
2560 +#else
2561 +static int capi_capability = AST_FORMAT_ALAW;
2562 +#endif
2563 +
2564 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
2565 +static CAPIProfileBuffer_t profile;
2566 +#else
2567 +static struct ast_capi_profile profile;
2568 +#endif
2569 +static pthread_t monitor_thread = -1;
2570 +
2571 +static struct ast_capi_pvt *iflist = NULL;
2572 +static struct capi_pipe *pipelist = NULL;
2573 +static int capi_last_plci = 0;
2574 +static struct ast_capi_controller *capi_controllers[AST_CAPI_MAX_CONTROLLERS];
2575 +static int capi_num_controllers = 0;
2576 +static int capi_counter = 0;
2577 +static unsigned long capi_used_controllers=0;
2578 +
2579 +static char capi_send_buffer[AST_CAPI_MAX_B3_BLOCKS * AST_CAPI_MAX_B3_BLOCK_SIZE];
2580 +static int capi_send_buffer_handle = 0;
2581 +
2582 +char capi_national_prefix[AST_MAX_EXTENSION];
2583 +char capi_international_prefix[AST_MAX_EXTENSION];
2584 +
2585 +int capidebug = 0;
2586 +
2587 +static const struct ast_channel_tech capi_tech;
2588 +
2589 +MESSAGE_EXCHANGE_ERROR _capi_put_cmsg(_cmsg *CMSG) {
2590 + MESSAGE_EXCHANGE_ERROR error;
2591 + if (ast_mutex_lock(&capi_put_lock)) {
2592 + ast_log(LOG_WARNING,"Unable to lock capi put!\n");
2593 + return -1;
2594 + }
2595 + error = capi20_put_cmsg(CMSG);
2596 + if (ast_mutex_unlock(&capi_put_lock)) {
2597 + ast_log(LOG_WARNING,"Unable to unlock capi put!\n");
2598 + return -1;
2599 + }
2600 + return error;
2601 +}
2602 +
2603 +
2604 +MESSAGE_EXCHANGE_ERROR check_wait_get_cmsg(_cmsg *CMSG) {
2605 + MESSAGE_EXCHANGE_ERROR Info;
2606 + struct timeval tv;
2607 + tv.tv_sec = 0;
2608 + tv.tv_usec = 10000;
2609 + Info = capi20_waitformessage(ast_capi_ApplID,&tv);
2610 + if ((Info != 0x0000) && (Info != 0x1104)) {
2611 + if (capidebug) {
2612 + ast_log(LOG_DEBUG, "Error waiting for cmsg... INFO = %#x\n", Info);
2613 + }
2614 + return Info;
2615 + }
2616 +
2617 + if (Info == 0x0000) {
2618 + Info = capi_get_cmsg(CMSG,ast_capi_ApplID);
2619 + }
2620 + return Info;
2621 +}
2622 +
2623 +
2624 +unsigned ListenOnController(unsigned long CIPmask,unsigned controller) {
2625 + MESSAGE_EXCHANGE_ERROR error;
2626 + _cmsg CMSG,CMSG2;
2627 +
2628 + LISTEN_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, controller);
2629 +#ifdef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
2630 + LISTEN_REQ_INFOMASK(&CMSG) = 0x00ff; // lots of info ;)
2631 +#else
2632 + LISTEN_REQ_INFOMASK(&CMSG) = 0x03ff; // lots of info ;) + early B3 connect
2633 +#endif
2634 + LISTEN_REQ_CIPMASK(&CMSG) = CIPmask;
2635 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2636 + return error;
2637 + }
2638 + while (!IS_LISTEN_CONF(&CMSG2)) {
2639 + error = check_wait_get_cmsg(&CMSG2);
2640 + }
2641 + return 0;
2642 +}
2643 +
2644 +// Echo cancellation is for cards w/ integrated echo cancellation only
2645 +// (i.e. Eicon active cards support it)
2646 +
2647 +#define EC_FUNCTION_ENABLE 1
2648 +#define EC_FUNCTION_DISABLE 2
2649 +#define EC_FUNCTION_FREEZE 3
2650 +#define EC_FUNCTION_RESUME 4
2651 +#define EC_FUNCTION_RESET 5
2652 +#define EC_OPTION_DISABLE_NEVER 0
2653 +#define EC_OPTION_DISABLE_G165 (1<<1)
2654 +#define EC_OPTION_DISABLE_G164_OR_G165 (1<<1 | 1<<2)
2655 +#define EC_DEFAULT_TAIL 64
2656 +
2657 +static int capi_echo_canceller(struct ast_channel *c, int function) {
2658 + struct ast_capi_pvt *i = c->tech_pvt;
2659 + MESSAGE_EXCHANGE_ERROR error;
2660 + _cmsg CMSG;
2661 + unsigned char buf[7];
2662 +
2663 + /* If echo cancellation is not requested or supported, don't attempt to enable it */
2664 + ast_mutex_lock(&contrlock);
2665 + if (!capi_controllers[i->controller]->echocancel || !i->doEC) {
2666 + ast_mutex_unlock(&contrlock);
2667 + return 0;
2668 + }
2669 + ast_mutex_unlock(&contrlock);
2670 +
2671 + if (option_verbose > 2)
2672 + 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);
2673 +
2674 + FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
2675 + FACILITY_REQ_NCCI(&CMSG) = i->NCCI;
2676 + FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 6; /* Echo canceller */
2677 +
2678 + buf[0]=6; /* msg size */
2679 + buf[1]=function;
2680 + if (function == EC_FUNCTION_ENABLE) {
2681 + buf[3]=i->ecOption; /* bit field - ignore echo canceller disable tone */
2682 + buf[5]=i->ecTail; /* Tail length, ms */
2683 + }
2684 + else {
2685 + buf[3]=0;
2686 + buf[5]=0;
2687 + }
2688 +
2689 + // Always null:
2690 + buf[2]=0;
2691 + buf[4]=0;
2692 + buf[6]=0;
2693 +
2694 + FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = buf;
2695 +
2696 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2697 + ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
2698 + return error;
2699 + }
2700 +
2701 + if (option_verbose > 5)
2702 + ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_REQ (PLCI=%#x)\n",i->PLCI);
2703 +
2704 + return 0;
2705 +}
2706 +
2707 +int capi_detect_dtmf(struct ast_channel *c, int flag) {
2708 + struct ast_capi_pvt *i = c->tech_pvt;
2709 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
2710 + MESSAGE_EXCHANGE_ERROR error;
2711 + _cmsg CMSG;
2712 + unsigned char buf[9];
2713 + // does the controller support dtmf? and do we want to use it?
2714 + ast_mutex_lock(&contrlock);
2715 + if ((capi_controllers[i->controller]->dtmf == 1) && (i->doDTMF == 0)) {
2716 + ast_mutex_unlock(&contrlock);
2717 + FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
2718 + FACILITY_REQ_PLCI(&CMSG) = i->PLCI;
2719 + FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 1;
2720 + buf[0] = 8;
2721 + if (flag == 1) {
2722 + buf[1] = 1;
2723 + } else {
2724 + buf[1] = 2;
2725 + }
2726 + buf[2] = 0;
2727 + buf[3] = AST_CAPI_DTMF_DURATION;
2728 + buf[4] = 0;
2729 + buf[5] = AST_CAPI_DTMF_DURATION;
2730 + buf[6] = 0;
2731 + buf[7] = 0;
2732 + buf[8] = 0;
2733 + FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = buf;
2734 +
2735 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2736 + ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
2737 + return error;
2738 + } else {
2739 + if (option_verbose > 5) {
2740 + ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_REQ (PLCI=%#x)\n",i->PLCI);
2741 + }
2742 + }
2743 + } else {
2744 + ast_mutex_unlock(&contrlock);
2745 +
2746 +#endif
2747 + // do software dtmf detection
2748 + i->doDTMF = 1; // just being paranoid again...
2749 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
2750 + }
2751 +#endif
2752 + return 0;
2753 +}
2754 +static int capi_send_digit(struct ast_channel *c,char digit) {
2755 + struct ast_capi_pvt *i = c->tech_pvt;
2756 + MESSAGE_EXCHANGE_ERROR error;
2757 + _cmsg CMSG;
2758 + unsigned char buf[10];
2759 +
2760 + if (i->state != CAPI_STATE_BCONNECTED) {
2761 + return 0;
2762 + }
2763 +
2764 +
2765 +#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
2766 + if(i->earlyB3 == 1)
2767 + /* we should really test for the network saying the number is incomplete
2768 + since i'm only doing a test and this is true at the right time
2769 + i'm going with this */
2770 + {
2771 +
2772 + INFO_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
2773 + INFO_REQ_PLCI(&CMSG) = i->PLCI;
2774 + buf[0] = 2;
2775 + buf[1] = 0x80;
2776 + buf[2] = digit;
2777 + INFO_REQ_CALLEDPARTYNUMBER(&CMSG) = buf;
2778 +
2779 +
2780 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2781 + ast_log(LOG_ERROR,"error sending CALLEDPARTYNUMBER INFO (error=%#x)\n",error);
2782 + return error;
2783 + } else {
2784 + if (option_verbose > 5) {
2785 + ast_verbose(VERBOSE_PREFIX_4 "sent CALLEDPARTYNUMBER INFO digit = %c (PLCI=%#x)\n", digit, i->PLCI);
2786 + }
2787 + }
2788 +
2789 + } else {
2790 +#endif
2791 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
2792 + ast_mutex_lock(&contrlock);
2793 + if ((capi_controllers[i->controller]->dtmf == 0) || (i->doDTMF == 1)) {
2794 +#endif
2795 + // let * fake it
2796 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
2797 + ast_mutex_unlock(&contrlock);
2798 +#endif
2799 + return -1;
2800 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
2801 + }
2802 + ast_mutex_unlock(&contrlock);
2803 +
2804 + FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
2805 + FACILITY_REQ_PLCI(&CMSG) = i->NCCI;
2806 + FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 1;
2807 + buf[0] = 8;
2808 +
2809 + buf[1] = 3;
2810 + buf[2] = 0;
2811 +
2812 + buf[3] = AST_CAPI_DTMF_DURATION;
2813 + buf[4] = 0;
2814 +
2815 + buf[5] = AST_CAPI_DTMF_DURATION;
2816 + buf[6] = 0;
2817 +
2818 + buf[7] = 1;
2819 + buf[8] = digit;
2820 + buf[9] = 0;
2821 + FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = buf;
2822 +
2823 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2824 + ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
2825 + return error;
2826 + } else {
2827 + if (option_verbose > 4) {
2828 + ast_verbose(VERBOSE_PREFIX_3 "sent dtmf '%c'\n",digit);
2829 + }
2830 + }
2831 +#endif
2832 +#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
2833 + }
2834 +#endif
2835 + return 0;
2836 +}
2837 +
2838 +static int capi_alert(struct ast_channel *c) {
2839 + struct ast_capi_pvt *i = c->tech_pvt;
2840 + MESSAGE_EXCHANGE_ERROR error;
2841 + _cmsg CMSG;
2842 +
2843 + ALERT_REQ_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
2844 + ALERT_REQ_PLCI(&CMSG) = i->PLCI;
2845 +
2846 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2847 + ast_log(LOG_ERROR,"error sending ALERT_REQ PLCI = %#x\n",i->PLCI);
2848 + return -1;
2849 + } else {
2850 + if (option_verbose > 5) {
2851 + ast_verbose(VERBOSE_PREFIX_4 "sent ALERT_REQ PLCI = %#x\n",i->PLCI);
2852 + }
2853 + }
2854 +
2855 + i->state = CAPI_STATE_ALERTING;
2856 + return 0;
2857 +}
2858 +
2859 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
2860 +static int capi_deflect(struct ast_channel *chan, void *data)
2861 +{
2862 + struct ast_capi_pvt *i = chan->tech_pvt;
2863 + MESSAGE_EXCHANGE_ERROR Info;
2864 + _cmsg CMSG;
2865 + char bchaninfo[1];
2866 + char fac[60];
2867 + int res=0;
2868 + int ms=3000;
2869 +
2870 + if (!data) {
2871 + ast_log(LOG_WARNING, "cd requires an argument (destination phone number)\n");
2872 + return -1;
2873 + }
2874 +
2875 + if ((i->state == CAPI_STATE_CONNECTED) || (i->state == CAPI_STATE_BCONNECTED)) {
2876 + ast_log(LOG_ERROR, "call deflection does not work with calls that are already connected!\n");
2877 + return -1;
2878 + }
2879 + // wait until the channel is alerting, so we dont drop the call and interfer with msgs
2880 + while ((ms > 0) && (i->state != CAPI_STATE_ALERTING)) {
2881 + sleep(100);
2882 + ms -= 100;
2883 + }
2884 +
2885 + // make sure we hang up correctly
2886 + i->state = CAPI_STATE_CONNECTPENDING;
2887 +
2888 + fac[0]=0; // len
2889 + fac[1]=0; //len
2890 + fac[2]=0x01; // Use D-Chan
2891 + fac[3]=0; // Keypad len
2892 + fac[4]=31; // user user data? len = 31 = 29 + 2
2893 + fac[5]=0x1c; // magic?
2894 + fac[6]=0x1d; // strlen destination + 18 = 29
2895 + fac[7]=0x91; // ..
2896 + fac[8]=0xA1;
2897 + fac[9]=0x1A; // strlen destination + 15 = 26
2898 + fac[10]=0x02;
2899 + fac[11]=0x01;
2900 + fac[12]=0x70;
2901 + fac[13]=0x02;
2902 + fac[14]=0x01;
2903 + fac[15]=0x0d;
2904 + fac[16]=0x30;
2905 + fac[17]=0x12; // strlen destination + 7 = 18
2906 + fac[18]=0x30; // ...hm 0x30
2907 + fac[19]=0x0d; // strlen destination + 2
2908 + fac[20]=0x80; // CLIP
2909 + fac[21]=0x0b; // strlen destination
2910 + fac[22]=0x01; // destination start
2911 + fac[23]=0x01; //
2912 + fac[24]=0x01; //
2913 + fac[25]=0x01; //
2914 + fac[26]=0x01; //
2915 + fac[27]=0x01; //
2916 + fac[28]=0x01; //
2917 + fac[29]=0x01; //
2918 + fac[30]=0x01; //
2919 + fac[31]=0x01; //
2920 + fac[32]=0x01; //
2921 + fac[33]=0x01; // 0x1 = sending complete
2922 + fac[34]=0x01;
2923 + fac[35]=0x01;
2924 +
2925 + memcpy((unsigned char *)fac+22,data,strlen(data));
2926 + fac[22+strlen(data)]=0x01; // fill with 0x01 if number is only 6 numbers (local call)
2927 + fac[23+strlen(data)]=0x01;
2928 + fac[24+strlen(data)]=0x01;
2929 + fac[25+strlen(data)]=0x01;
2930 + fac[26+strlen(data)]=0x01;
2931 +
2932 + fac[6]=18+strlen(data);
2933 + fac[9]=15+strlen(data);
2934 + fac[17]=7+strlen(data);
2935 + fac[19]=2+strlen(data);
2936 + fac[21]=strlen(data);
2937 +
2938 + bchaninfo[0] = 0x1;
2939 + INFO_REQ_HEADER(&CMSG,ast_capi_ApplID,ast_capi_MessageNumber++,0);
2940 + INFO_REQ_CONTROLLER(&CMSG) = i->controller;
2941 + INFO_REQ_PLCI(&CMSG) = i->PLCI;
2942 + INFO_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char*)bchaninfo; // use D-Channel
2943 + INFO_REQ_KEYPADFACILITY(&CMSG) = 0;
2944 + INFO_REQ_USERUSERDATA(&CMSG) = 0;
2945 + INFO_REQ_FACILITYDATAARRAY(&CMSG) = (unsigned char*) fac + 4;
2946 +
2947 + if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
2948 + ast_log(LOG_ERROR,"Error sending INFO_REQ\n");
2949 + return Info;
2950 + } else {
2951 + if (capidebug) {
2952 + // ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(&CMSG));
2953 + ast_log(LOG_NOTICE,"sent INFO_REQ PLCI = %#x\n",i->PLCI);
2954 + }
2955 + }
2956 +
2957 + return res;
2958 +}
2959 +#endif
2960 +
2961 +void remove_pipe(int PLCI) {
2962 + struct capi_pipe *p,*ptmp;
2963 +
2964 + ast_mutex_lock(&pipelock);
2965 + p = pipelist;
2966 + ptmp = NULL;
2967 + while (p) {
2968 + if (p->PLCI == PLCI) {
2969 + if (ptmp == NULL) {
2970 + // mypipe == head of pipelist
2971 + pipelist = p->next;
2972 + if(p->fd > -1) close(p->fd);
2973 + if(p->i != NULL && p->i->fd > -1) close(p->i->fd);
2974 + free(p);
2975 + if (option_verbose > 4) {
2976 + ast_verbose(VERBOSE_PREFIX_3 "removed pipe for PLCI = %#x\n",PLCI);
2977 + }
2978 + break;
2979 + } else {
2980 + // somehwere inbetween or at the end
2981 + ptmp->next = p->next;
2982 + if (p->next == NULL) {
2983 + capi_last_plci = p->PLCI;
2984 + }
2985 + if(p->fd > -1) close(p->fd);
2986 + if(p->i != NULL && p->i->fd > -1) close(p->i->fd);
2987 + free(p);
2988 + if (option_verbose > 4) {
2989 + ast_verbose(VERBOSE_PREFIX_3 "removed pipe for PLCI = %#x\n",PLCI);
2990 + }
2991 + break;
2992 + }
2993 + }
2994 + ptmp = p;
2995 + p = p->next;
2996 + }
2997 + ast_mutex_unlock(&pipelock);
2998 +}
2999 +
3000 +static int capi_activehangup(struct ast_channel *c) {
3001 + struct ast_capi_pvt *i = c->tech_pvt;
3002 + MESSAGE_EXCHANGE_ERROR error;
3003 + _cmsg CMSG;
3004 +
3005 + if (option_verbose > 2) {
3006 + if (capidebug)
3007 + ast_verbose(VERBOSE_PREFIX_4 "activehangingup\n");
3008 + }
3009 +
3010 + if (i == NULL) {
3011 + return 0;
3012 + }
3013 +
3014 + if (c->_state == AST_STATE_RING) {
3015 + CONNECT_RESP_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
3016 + CONNECT_RESP_PLCI(&CMSG) = i->PLCI;
3017 + CONNECT_RESP_REJECT(&CMSG) = 2;
3018 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3019 + ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",i->PLCI);
3020 + } else {
3021 + if (option_verbose > 5) {
3022 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",i->PLCI);
3023 + }
3024 + }
3025 + return 0;
3026 + }
3027 +
3028 + // active disconnect
3029 + if (i->state == CAPI_STATE_BCONNECTED) {
3030 + DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
3031 + DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
3032 +
3033 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3034 + ast_log(LOG_ERROR, "error sending DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
3035 + } else {
3036 + if (option_verbose > 5) {
3037 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
3038 + }
3039 + }
3040 + // wait for the B3 layer to go down
3041 + while (i->state != CAPI_STATE_CONNECTED) {
3042 + usleep(10000);
3043 + }
3044 + }
3045 + if ((i->state == CAPI_STATE_CONNECTED) || (i->state == CAPI_STATE_CONNECTPENDING)){
3046 + DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
3047 + DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
3048 +
3049 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3050 + ast_log(LOG_ERROR, "error sending DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
3051 + } else {
3052 + if (option_verbose > 5) {
3053 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
3054 + }
3055 + }
3056 + // wait for the B1 layer to go down
3057 + while (i->state != CAPI_STATE_DISCONNECTED) {
3058 + usleep(10000);
3059 + }
3060 + }
3061 + return 0;
3062 +}
3063 +
3064 +static int capi_hangup(struct ast_channel *c) {
3065 + struct ast_capi_pvt *i = c->tech_pvt;
3066 +
3067 + // hmm....ok...this is called to free the capi interface (passive disconnect)
3068 + // or to bring down the channel (active disconnect)
3069 +
3070 + if (option_verbose > 3)
3071 + ast_verbose(VERBOSE_PREFIX_3 "CAPI Hangingup\n");
3072 +
3073 + if (i == NULL) {
3074 + ast_log(LOG_ERROR,"channel has no interface!\n");
3075 + return -1;
3076 + }
3077 +
3078 + // are we down, yet?
3079 + if (i->state != CAPI_STATE_DISCONNECTED) {
3080 + // no
3081 + capi_activehangup(c);
3082 + }
3083 +
3084 + remove_pipe(i->PLCI);
3085 + i->PLCI = 0;
3086 + i->NCCI = 0;
3087 + if ((i->doDTMF == 1) && (i->vad != NULL)) {
3088 + ast_dsp_free(i->vad);
3089 + }
3090 + ast_smoother_free(i->smoother); // discard any frames left hanging
3091 + i->smoother=ast_smoother_new(AST_CAPI_MAX_B3_BLOCK_SIZE * 2);
3092 + memset(i->cid,0,sizeof(i->cid));
3093 + i->owner=NULL;
3094 + ast_mutex_lock(&usecnt_lock);
3095 + usecnt--;
3096 + ast_mutex_unlock(&usecnt_lock);
3097 + ast_update_use_count();
3098 + i->mypipe = NULL;
3099 + i = NULL;
3100 + c->tech_pvt = NULL;
3101 + ast_setstate(c,AST_STATE_DOWN);
3102 + return 0;
3103 +}
3104 +
3105 +static char *capi_number(char *data,int strip) {
3106 + unsigned len = *data;
3107 + // XXX fix me
3108 + // convert a capi struct to a \0 terminated string
3109 + if (!len || len < (unsigned int) strip) return NULL;
3110 + len = len - strip;
3111 + data = (char *)(data + 1 + strip);
3112 + return strndup((char *)data,len);
3113 +}
3114 +
3115 +int capi_call(struct ast_channel *c, char *idest, int timeout)
3116 +{
3117 + struct ast_capi_pvt *i;
3118 + struct capi_pipe *p = NULL;
3119 + int fds[2];
3120 + char *dest,*interface;
3121 + char buffer[AST_MAX_EXTENSION];
3122 + char called[AST_MAX_EXTENSION],calling[AST_MAX_EXTENSION];
3123 + char bchaninfo[3];
3124 + long flags;
3125 +
3126 + _cmsg CMSG;
3127 + MESSAGE_EXCHANGE_ERROR error;
3128 +
3129 + strncpy(buffer,idest,sizeof(buffer)-1);
3130 + interface = strtok(buffer, "/");
3131 + dest = strtok(NULL, "/");
3132 +
3133 +
3134 + if (!dest) {
3135 + ast_log(LOG_WARNING, "Destination %s requires a real destination\n", idest);
3136 + return -1;
3137 + }
3138 + i = c->tech_pvt;
3139 + i->doB3 = AST_CAPI_B3_DONT; // <homer>DOH</homer>
3140 +
3141 + // always B3
3142 + if (((char *)dest)[0] == 'b') {
3143 + i->doB3 = AST_CAPI_B3_ALWAYS;
3144 + }
3145 + // only do B3 on successfull calls
3146 + if (((char *)dest)[0] == 'B') {
3147 + i->doB3 = AST_CAPI_B3_ON_SUCCESS;
3148 + }
3149 +
3150 + if (i->doB3 != AST_CAPI_B3_DONT) {
3151 + dest++;
3152 + }
3153 +
3154 + if (option_verbose > 1) {
3155 + if (capidebug)
3156 + ast_verbose(VERBOSE_PREFIX_2 "CAPI Call %s %s", c->name, i->doB3?"with B3":"");
3157 + }
3158 + switch (c->cid.cid_pres) {
3159 + case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
3160 + case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
3161 + case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
3162 + case PRES_ALLOWED_NETWORK_NUMBER:
3163 + case PRES_NUMBER_NOT_AVAILABLE:
3164 + i->CLIR = 0;
3165 + break;
3166 + case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
3167 + case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
3168 + case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
3169 + case PRES_PROHIB_NETWORK_NUMBER:
3170 + i->CLIR = 1;
3171 + break;
3172 + default:
3173 + i->CLIR = 0;
3174 + }
3175 +
3176 + if (pipe(fds) == 0) {
3177 + ast_mutex_lock(&pipelock);
3178 + i->fd = fds[0];
3179 + flags = fcntl(i->fd,F_GETFL);
3180 + fcntl(i->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
3181 + p = malloc(sizeof(struct capi_pipe));
3182 + memset(p, 0, sizeof(struct capi_pipe));
3183 + p->fd = fds[1];
3184 + flags = fcntl(i->fd,F_GETFL);
3185 + fcntl(p->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
3186 + c->fds[0] = i->fd;
3187 + p->PLCI = -1;
3188 + p->i = i;
3189 + p->c = c;
3190 + i->mypipe = p;
3191 + p->next = pipelist;
3192 + pipelist = p;
3193 + if (option_verbose > 4) {
3194 + ast_verbose(VERBOSE_PREFIX_3 "creating pipe for PLCI=-1\n");
3195 + }
3196 + ast_mutex_unlock(&pipelock);
3197 + }
3198 + i->outgoing = 1;
3199 +
3200 + i->MessageNumber = ast_capi_MessageNumber++;
3201 + CONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, i->controller);
3202 + CONNECT_REQ_CONTROLLER(&CMSG) = i->controller;
3203 + CONNECT_REQ_CIPVALUE(&CMSG) = 0x10; // Telephony, could also use 0x04 (3.1Khz audio)
3204 + called[0] = strlen(dest)+1;
3205 + called[1] = 0x80;
3206 + strncpy(&called[2],dest,sizeof(called)-2);
3207 + CONNECT_REQ_CALLEDPARTYNUMBER(&CMSG) = (unsigned char *)called;
3208 + CONNECT_REQ_CALLEDPARTYSUBADDRESS(&CMSG) = NULL;
3209 +
3210 + if (c->cid.cid_num) {
3211 + calling[0] = strlen(c->cid.cid_num)+2;
3212 + calling[1] = 0x0;
3213 + } else {
3214 + calling[0] = 0x0;
3215 + calling[1] = 0x0;
3216 + }
3217 +
3218 + if (i->CLIR == 1) {
3219 + calling[2] = 0xA0; // CLIR
3220 + } else {
3221 + calling[2] = 0x80; // CLIP
3222 + }
3223 +
3224 + if (c->cid.cid_num) {
3225 + strncpy(&calling[3],c->cid.cid_num,sizeof(calling)-3);
3226 + }
3227 + CONNECT_REQ_CALLINGPARTYNUMBER(&CMSG) = (unsigned char *)calling;
3228 + CONNECT_REQ_CALLINGPARTYSUBADDRESS(&CMSG) = NULL;
3229 +
3230 + CONNECT_REQ_B1PROTOCOL(&CMSG) = 1;
3231 + CONNECT_REQ_B2PROTOCOL(&CMSG) = 1; // 1
3232 + CONNECT_REQ_B3PROTOCOL(&CMSG) = 0;
3233 +
3234 + bchaninfo[0] = 2;
3235 + bchaninfo[1] = 0x0;
3236 + bchaninfo[2] = 0x0;
3237 + CONNECT_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char *)bchaninfo; // 0
3238 +
3239 + if ((error = _capi_put_cmsg(&CMSG))) {
3240 + ast_log(LOG_ERROR,"error sending CONNECT_REQ (error=%#x)\n",error);
3241 + return error;
3242 + } else {
3243 + if (option_verbose > 5) {
3244 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_REQ MN =%#x\n",CMSG.Messagenumber);
3245 + }
3246 + }
3247 +
3248 + i->state = CAPI_STATE_CONNECTPENDING;
3249 +
3250 + ast_setstate(c, AST_STATE_DIALING);
3251 +
3252 + // XXX fixme, not nice:
3253 +/* if (i->controller > 0) {
3254 + capi_controllers[i->controller]->nfreebchannels--;
3255 + } */
3256 +
3257 + // now we shall return .... the rest has to be done by handle_msg
3258 + return 0;
3259 +}
3260 +
3261 +
3262 +static int capi_answer(struct ast_channel *c) {
3263 + struct ast_capi_pvt *i = c->tech_pvt;
3264 + MESSAGE_EXCHANGE_ERROR error;
3265 + _cmsg CMSG;
3266 + char buf[AST_MAX_EXTENSION];
3267 + char *dnid;
3268 +
3269 + if (i->isdnmode && (strlen(i->incomingmsn)<strlen(i->dnid)))
3270 + dnid = i->dnid + strlen(i->incomingmsn);
3271 + else
3272 + dnid = i->dnid;
3273 +
3274 + CONNECT_RESP_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
3275 + CONNECT_RESP_PLCI(&CMSG) = i->PLCI;
3276 + CONNECT_RESP_REJECT(&CMSG) = 0;
3277 + buf[0] = strlen(dnid)+2;
3278 + buf[1] = 0x0;
3279 + buf[2] = 0x80;
3280 + strncpy(&buf[3],dnid,sizeof(buf)-4);
3281 + CONNECT_RESP_CONNECTEDNUMBER(&CMSG) = (unsigned char *)buf;
3282 + CONNECT_RESP_CONNECTEDSUBADDRESS(&CMSG) = NULL;
3283 + CONNECT_RESP_LLC(&CMSG) = NULL;
3284 + CONNECT_RESP_B1PROTOCOL(&CMSG) = 1;
3285 + CONNECT_RESP_B2PROTOCOL(&CMSG) = 1;
3286 + CONNECT_RESP_B3PROTOCOL(&CMSG) = 0;
3287 +
3288 + if (option_verbose > 3)
3289 + ast_verbose(VERBOSE_PREFIX_3 "CAPI Answering for MSN %s\n", dnid);
3290 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3291 + return -1;
3292 + } else {
3293 + if (option_verbose > 5) {
3294 + if (capidebug)
3295 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP PLCI = %#x DNID = %s\n",i->PLCI,i->dnid);
3296 + }
3297 + }
3298 +
3299 + i->state = CAPI_STATE_ANSWERING;
3300 + i->doB3 = AST_CAPI_B3_DONT;
3301 + i->outgoing = 0;
3302 + i->earlyB3 = -1;
3303 +
3304 + return 0;
3305 +}
3306 +
3307 +struct ast_frame *capi_read(struct ast_channel *c) {
3308 + struct ast_capi_pvt *i = c->tech_pvt;
3309 + int readsize = 0;
3310 +
3311 + if ((i->state == CAPI_STATE_REMOTE_HANGUP)) {
3312 + ast_log(LOG_ERROR,"this channel is not connected\n");
3313 + return NULL;
3314 + }
3315 + if (i->state == CAPI_STATE_ONHOLD) {
3316 + i->fr.frametype = AST_FRAME_NULL;
3317 + return &i->fr;
3318 + }
3319 +
3320 + if (i == NULL) {
3321 + ast_log(LOG_ERROR,"channel has no interface\n");
3322 + return NULL;
3323 + }
3324 + i->fr.frametype = AST_FRAME_NULL;
3325 + i->fr.subclass = 0;
3326 + i->fr.delivery.tv_sec = 0;
3327 + i->fr.delivery.tv_usec = 0;
3328 + readsize = read(i->fd,&i->fr,sizeof(struct ast_frame));
3329 + if (readsize != sizeof(struct ast_frame)) {
3330 + ast_log(LOG_ERROR,"did not read a whole frame\n");
3331 + }
3332 + if (i->fr.frametype == AST_FRAME_VOICE) {
3333 + readsize = read(i->fd,i->fr.data,i->fr.datalen);
3334 + if (readsize != i->fr.datalen) {
3335 + ast_log(LOG_ERROR,"did not read whole frame data\n");
3336 + }
3337 + }
3338 + i->fr.mallocd = 0;
3339 + if (i->fr.frametype == AST_FRAME_NULL) {
3340 + return NULL;
3341 + }
3342 + if ((i->fr.frametype == AST_FRAME_DTMF) && (i->fr.subclass == 'f')) {
3343 + if (strcmp(c->exten, "fax")) {
3344 + if (ast_exists_extension(c, ast_strlen_zero(c->macrocontext) ? c->context : c->macrocontext, "fax", 1, c->cid.cid_num)) {
3345 + if (option_verbose > 2)
3346 + ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", c->name);
3347 + /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
3348 + pbx_builtin_setvar_helper(c,"FAXEXTEN",c->exten);
3349 + if (ast_async_goto(c, c->context, "fax", 1))
3350 + ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", c->name, c->context);
3351 + } else {
3352 + ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
3353 + }
3354 + } else {
3355 + ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
3356 + }
3357 + }
3358 + return &i->fr;
3359 +}
3360 +
3361 +int capi_write(struct ast_channel *c, struct ast_frame *f) {
3362 + struct ast_capi_pvt *i = c->tech_pvt;
3363 + _cmsg CMSG;
3364 + MESSAGE_EXCHANGE_ERROR error;
3365 + int j=0;
3366 + char buf[1000];
3367 + struct ast_frame *fsmooth;
3368 +#ifdef CAPI_ES
3369 + int txavg=0;
3370 +#endif
3371 +
3372 +#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
3373 + // dont send audio to the local exchange!
3374 + if (i->earlyB3 == 1 || !i->NCCI) {
3375 + return 0;
3376 + }
3377 +#endif
3378 +
3379 + if (!i) {
3380 + ast_log(LOG_ERROR,"channel has no interface\n");
3381 + return -1;
3382 + }
3383 +
3384 + if (f->frametype == AST_FRAME_NULL) {
3385 + return 0;
3386 + }
3387 + if (f->frametype == AST_FRAME_DTMF) {
3388 + ast_log(LOG_ERROR,"dtmf frame should be written\n");
3389 + return 0;
3390 + }
3391 + if (f->frametype != AST_FRAME_VOICE) {
3392 + ast_log(LOG_ERROR,"not a voice frame\n");
3393 + return -1;
3394 + }
3395 + if (f->subclass != capi_capability) {
3396 + ast_log(LOG_ERROR,"dont know how to write subclass %d\n",f->subclass);
3397 + return -1;
3398 + }
3399 +// ast_log(LOG_NOTICE,"writing frame %d %d\n",f->frametype,f->subclass);
3400 +
3401 + if (ast_smoother_feed(i->smoother, f)!=0) {
3402 + ast_log(LOG_ERROR,"failed to fill smoother\n");
3403 + return -1;
3404 + }
3405 +
3406 + fsmooth=ast_smoother_read(i->smoother);
3407 + while(fsmooth != NULL) {
3408 + DATA_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
3409 + DATA_B3_REQ_NCCI(&CMSG) = i->NCCI;
3410 + DATA_B3_REQ_DATALENGTH(&CMSG) = fsmooth->datalen;
3411 + DATA_B3_REQ_FLAGS(&CMSG) = 0;
3412 +
3413 + if (ast_mutex_lock(&capi_send_buffer_lock)) {
3414 + ast_log(LOG_WARNING,"Unable to lock B3 send buffer!\n");
3415 + return -1;
3416 + }
3417 +#ifndef CAPI_ES
3418 +#ifdef CAPI_GAIN
3419 + for (j=0;j<fsmooth->datalen;j++) {
3420 + buf[j] = i->g.txgains[reversebits[((unsigned char *)fsmooth->data)[j]]];
3421 + }
3422 +#else
3423 + for (j=0;j<fsmooth->datalen;j++) {
3424 + buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ];
3425 + }
3426 +#endif
3427 +#else
3428 + if ((i->doES == 1)) {
3429 + for (j=0;j<fsmooth->datalen;j++) {
3430 + buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ];
3431 + txavg += abs( capiXLAW2INT(reversebits[ ((unsigned char*)fsmooth->data)[j]]) );
3432 + }
3433 + txavg = txavg/j;
3434 + for(j=0;j<ECHO_TX_COUNT-1;j++) {
3435 + i->txavg[j] = i->txavg[j+1];
3436 + }
3437 + i->txavg[ECHO_TX_COUNT-1] = txavg;
3438 +
3439 +// ast_log(LOG_NOTICE,"txavg = %d\n",txavg);
3440 + } else {
3441 +#ifdef CAPI_GAIN
3442 + for (j=0;j<fsmooth->datalen;j++) {
3443 + buf[j] = i->g.txgains[reversebits[((unsigned char *)fsmooth->data)[j]]];
3444 + }
3445 +#else
3446 + for (j=0;j<fsmooth->datalen;j++) {
3447 + buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ];
3448 + }
3449 +#endif
3450 + }
3451 +#endif
3452 +
3453 + DATA_B3_REQ_DATAHANDLE(&CMSG) = capi_send_buffer_handle;
3454 + memcpy((char *)&capi_send_buffer[(capi_send_buffer_handle % AST_CAPI_MAX_B3_BLOCKS) * AST_CAPI_MAX_B3_BLOCK_SIZE],&buf,fsmooth->datalen);
3455 + 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];
3456 + capi_send_buffer_handle++;
3457 +
3458 + if (ast_mutex_unlock(&capi_send_buffer_lock)) {
3459 + ast_log(LOG_WARNING,"Unable to unlock B3 send buffer!\n");
3460 + return -1;
3461 + }
3462 +
3463 +
3464 +#ifdef CAPI_SYNC
3465 + ast_mutex_lock(&i->lockB3in);
3466 + if ((i->B3in >= 1) && (i->B3in <= AST_CAPI_MAX_B3_BLOCKS)) {
3467 + i->B3in--;
3468 + ast_mutex_unlock(&i->lockB3in);
3469 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3470 + ast_log(LOG_ERROR,"error sending DATA_B3_REQ (error=%#x, datalen=%d) B3in=%d\n",error,fsmooth->datalen,i->B3in);
3471 +// ast_log(LOG_NOTICE,"f: timelen %d b = %d MN = %d \n",fsmooth->timelen,b,CMSG.Messagenumber);
3472 + } else {
3473 + if (option_verbose > 5) {
3474 + if (capidebug)
3475 + ast_verbose(VERBOSE_PREFIX_4 "sent DATA_B3_REQ (NCCI=%#x) (%d bytes)\n",i->NCCI,fsmooth->datalen);
3476 + }
3477 + }
3478 + } else {
3479 + if (i->B3in > 0) i->B3in--;
3480 + ast_mutex_unlock(&i->lockB3in);
3481 + }
3482 +#else
3483 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3484 + ast_log(LOG_ERROR,"error sending DATA_B3_REQ (error=%#x, datalen=%d)\n",error,fsmooth->datalen);
3485 +// ast_log(LOG_NOTICE,"f: timelen %d b = %d MN = %d \n",fsmooth->timelen,b,CMSG.Messagenumber);
3486 + } else {
3487 + if (option_verbose > 5) {
3488 + if (capidebug)
3489 + ast_verbose(VERBOSE_PREFIX_4 "sent DATA_B3_REQ (NCCI=%#x) (%d bytes)\n",i->NCCI,fsmooth->datalen);
3490 + }
3491 + }
3492 +#endif
3493 +
3494 +// ast_frfree(fsmooth);
3495 +
3496 + fsmooth=ast_smoother_read(i->smoother);
3497 + }
3498 + return 0;
3499 +}
3500 +
3501 +static int capi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan) {
3502 + struct ast_capi_pvt *p = newchan->tech_pvt;
3503 + p->owner = newchan;
3504 + return 0;
3505 +}
3506 +
3507 +int capi_indicate(struct ast_channel *c,int condition) {
3508 + return -1;
3509 +}
3510 +
3511 +int capi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc) {
3512 + return -1;
3513 +}
3514 +
3515 +
3516 +struct ast_channel *capi_new(struct ast_capi_pvt *i,int state) {
3517 + struct ast_channel *tmp;
3518 + int fmt;
3519 +
3520 + tmp = ast_channel_alloc(1);
3521 + if (tmp != NULL) {
3522 + snprintf(tmp->name,sizeof(tmp->name),"CAPI/contr%d/%s-%d",i->controller,i->dnid,capi_counter++);
3523 + tmp->type = type;
3524 + tmp->tech = &capi_tech;
3525 + tmp->nativeformats = capi_capability;
3526 + ast_setstate(tmp,state);
3527 + tmp->fds[0] = i->fd;
3528 + i->smoother = ast_smoother_new(AST_CAPI_MAX_B3_BLOCK_SIZE);
3529 + if (i->smoother == NULL) {
3530 + ast_log(LOG_ERROR, "smoother NULL!\n");
3531 + }
3532 + i->fr.frametype = 0;
3533 + i->fr.subclass = 0;
3534 + i->fr.delivery.tv_sec = 0;
3535 + i->fr.delivery.tv_usec = 0;
3536 + i->state = CAPI_STATE_DISCONNECTED;
3537 + i->CLIR = 0;
3538 + i->calledPartyIsISDN = 0; // let's be pessimistic
3539 + i->earlyB3 = -1;
3540 + i->doB3 = AST_CAPI_B3_DONT;
3541 + i->outgoing = 0;
3542 + i->onholdPLCI = 0;
3543 +#ifdef CAPI_SYNC
3544 + i->B3in = 0;
3545 + ast_mutex_init(&i->lockB3in);
3546 +#endif
3547 +#ifdef CAPI_ES
3548 + memset(i->txavg,0,ECHO_TX_COUNT);
3549 +#endif
3550 +
3551 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
3552 + if (i->doDTMF == 1) {
3553 +#endif
3554 + i->vad = ast_dsp_new();
3555 + ast_dsp_set_features(i->vad, DSP_FEATURE_DTMF_DETECT);
3556 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
3557 + }
3558 +#endif
3559 +
3560 + tmp->tech_pvt = i;
3561 + tmp->callgroup = i->callgroup;
3562 + tmp->nativeformats = capi_capability;
3563 + fmt = ast_best_codec(tmp->nativeformats);
3564 +// fmt = capi_capability;
3565 + tmp->readformat = fmt;
3566 + tmp->writeformat = fmt;
3567 + tmp->rawreadformat = fmt;
3568 + tmp->rawwriteformat = fmt;
3569 + strncpy(tmp->context,i->context,sizeof(tmp->context)-1);
3570 + tmp->cid.cid_num = strdup(i->cid);
3571 + tmp->cid.cid_dnid = strdup(i->dnid);
3572 + strncpy(tmp->exten,i->dnid,sizeof(tmp->exten)-1);
3573 + strncpy(tmp->accountcode,i->accountcode,sizeof(tmp->accountcode)-1);
3574 + i->owner = tmp;
3575 + ast_mutex_lock(&usecnt_lock);
3576 + usecnt++;
3577 + ast_mutex_unlock(&usecnt_lock);
3578 + ast_update_use_count();
3579 + if (state != AST_STATE_DOWN) {
3580 + // we are alerting (phones ringing)
3581 + if (state == AST_STATE_RING)
3582 + capi_alert(tmp);
3583 + if (ast_pbx_start(tmp)) {
3584 + ast_log(LOG_ERROR,"Unable to start pbx on channel!\n");
3585 + ast_hangup(tmp);
3586 + tmp = NULL;
3587 + } else {
3588 + if (option_verbose > 2) {
3589 + ast_verbose(VERBOSE_PREFIX_3 "started pbx on channel (callgroup=%d)!\n",tmp->callgroup);
3590 + }
3591 + }
3592 + }
3593 + } else {
3594 + ast_log(LOG_ERROR,"Unable to allocate channel!\n");
3595 + }
3596 + return tmp;
3597 +}
3598 +
3599 +
3600 +struct ast_channel *capi_request(const char *type, int format, void *data, int *cause)
3601 +{
3602 + struct ast_capi_pvt *i;
3603 + struct ast_channel *tmp = NULL;
3604 + char *dest,*interface;
3605 + char buffer[AST_MAX_EXTENSION];
3606 + unsigned int capigroup=0, controller=0;
3607 + int notfound = 1;
3608 +
3609 + if (option_verbose > 1) {
3610 + if (capidebug)
3611 + ast_verbose(VERBOSE_PREFIX_3 "data = %s\n",(char *)data);
3612 + }
3613 + strncpy(buffer,(char *)data,sizeof(buffer)-1);
3614 +
3615 + interface = strtok(buffer, "/");
3616 + dest = strtok(NULL, "/");
3617 +
3618 +
3619 + if (((char *)interface)[0] == 'g') {
3620 + interface++;
3621 + capigroup = atoi(interface);
3622 + if (option_verbose > 1) {
3623 + if (capidebug)
3624 + ast_verbose(VERBOSE_PREFIX_3 "capi request group = %d\n",capigroup);
3625 + }
3626 + } else if (!strncmp(interface,"contr",5)) {
3627 + interface += 5;
3628 + controller = atoi(interface);
3629 + if (option_verbose > 1) {
3630 + if (capidebug)
3631 + ast_verbose(VERBOSE_PREFIX_3 "capi request controller = %d\n",controller);
3632 + }
3633 + } else {
3634 + ast_log(LOG_ERROR,"Syntax error in dialstring. read the docs!\n");
3635 + }
3636 +
3637 + ast_mutex_lock(&iflock);
3638 + i = iflist;
3639 + while (i && notfound) {
3640 + // unused channel
3641 + if (!i->owner) {
3642 + if (controller && (i->controllers & (1 << controller))) {
3643 + // DIAL(CAPI/contrX/...)
3644 + ast_mutex_lock(&contrlock);
3645 + if (capi_controllers[controller]->nfreebchannels > 0) {
3646 + strncpy(i->dnid,dest,sizeof(i->dnid)-1);
3647 + i->controller = controller;
3648 + tmp = capi_new(i, AST_STATE_DOWN);
3649 + i->PLCI = -1;
3650 + i->datahandle = 0;
3651 + i->outgoing = 1; // this is an outgoing line
3652 + i->earlyB3 = -1;
3653 + // capi_detect_dtmf(tmp,1);
3654 + ast_mutex_unlock(&contrlock);
3655 + ast_mutex_unlock(&iflock);
3656 + return tmp;
3657 + } else {
3658 + // keep on running!
3659 + ast_mutex_unlock(&contrlock);
3660 + }
3661 + } else if (capigroup && (i->group & (1 << capigroup))) {
3662 + int c;
3663 + // DIAL(CAPI/gX/...)
3664 + ast_mutex_lock(&contrlock);
3665 + for (c=1;c<=capi_num_controllers;c++) {
3666 + if (i->controllers & (1 << c)) {
3667 + if (capi_controllers[c]->nfreebchannels > 0) {
3668 + strncpy(i->dnid,dest,sizeof(i->dnid)-1);
3669 + i->controller = c;
3670 + tmp = capi_new(i, AST_STATE_DOWN);
3671 + i->PLCI = -1;
3672 + i->datahandle = 0;
3673 + i->outgoing = 1; // this is an outgoing line
3674 + i->earlyB3 = -1;
3675 + // capi_detect_dtmf(tmp,1);
3676 + ast_mutex_unlock(&contrlock);
3677 + ast_mutex_unlock(&iflock);
3678 + return tmp;
3679 + } else {
3680 + // keep on running!
3681 + }
3682 + }
3683 + }
3684 + ast_mutex_unlock(&contrlock);
3685 + }
3686 + }
3687 +// ast_log(LOG_NOTICE,"not contr %d group %d\n",i->controllers, i->group);
3688 + i = i->next;
3689 + }
3690 + ast_mutex_unlock(&iflock);
3691 + ast_log(LOG_NOTICE,"didn't find capi device with controller = %d or group = %d.\n",controller, capigroup);
3692 + return NULL;
3693 +}
3694 +
3695 +
3696 +struct capi_pipe *find_pipe(int PLCI,int MN) {
3697 + struct capi_pipe *p;
3698 + // find a pipe by PLCI or by MessageNumber (in case this is a CONNECT_CONF)
3699 + ast_mutex_lock(&pipelock);
3700 + p = pipelist;
3701 + if ((p == NULL) && (capi_last_plci != PLCI)){
3702 + if (capidebug) {
3703 + ast_log(LOG_NOTICE,"PLCI doesnt match last pipe (PLCI = %#x)\n",PLCI);
3704 + }
3705 + ast_mutex_unlock(&pipelock);
3706 + return NULL;
3707 + }
3708 + while(p != NULL) {
3709 + if ((p->PLCI == PLCI) || ( (p->PLCI == -1) && (p->i->MessageNumber == MN) ) ){
3710 + ast_mutex_unlock(&pipelock);
3711 + return p;
3712 + }
3713 + p = p->next;
3714 + }
3715 + if (capidebug) {
3716 + ast_log(LOG_ERROR,"unable to find a pipe for PLCI = %#x MN = %#x\n",PLCI,MN);
3717 + }
3718 + ast_mutex_unlock(&pipelock);
3719 + return NULL;
3720 +}
3721 +
3722 +int pipe_frame(struct capi_pipe *p,struct ast_frame *f) {
3723 + fd_set wfds;
3724 + int written=0;
3725 + struct timeval tv;
3726 + FD_ZERO(&wfds);
3727 + FD_SET(p->fd,&wfds);
3728 + tv.tv_sec = 0;
3729 + tv.tv_usec = 10;
3730 + if ((f->frametype == AST_FRAME_VOICE) && (p->i->doDTMF == 1) && (p->i->vad != NULL)) {
3731 + f = ast_dsp_process(p->c,p->i->vad,f);
3732 + if (f->frametype == AST_FRAME_NULL) {
3733 + return 0;
3734 + }
3735 + }
3736 + // we dont want the monitor thread to block
3737 + if (select(p->fd + 1,NULL,&wfds,NULL,&tv) == 1) {
3738 + written = write(p->fd,f,sizeof(struct ast_frame));
3739 + if (written < (signed int) sizeof(struct ast_frame)) {
3740 + ast_log(LOG_ERROR,"wrote %d bytes instead of %d\n", written, (int)sizeof(struct ast_frame));
3741 + return -1;
3742 + }
3743 + if (f->frametype == AST_FRAME_VOICE) {
3744 + written = write(p->fd,f->data,f->datalen);
3745 + if (written < f->datalen) {
3746 + ast_log(LOG_ERROR,"wrote %d bytes instead of %d\n",written,f->datalen);
3747 + return -1;
3748 + }
3749 + }
3750 + } else {
3751 + return 0;
3752 + }
3753 + return -1;
3754 +}
3755 +
3756 +static int search_did(struct ast_channel *c)
3757 +{
3758 + // Returns
3759 + // -1 = Failure
3760 + // 0 = Match
3761 + // 1 = possible match
3762 + struct ast_capi_pvt *i = c->tech_pvt;
3763 + char *exten;
3764 +
3765 + if (strlen(i->dnid)<strlen(i->incomingmsn))
3766 + return -1;
3767 +
3768 +// exten = i->dnid + strlen(i->incomingmsn);
3769 + exten = i->dnid;
3770 +
3771 + if (ast_exists_extension(NULL, c->context, exten, 1, NULL)) {
3772 + c->priority = 1;
3773 + strncpy(c->exten, exten, sizeof(c->exten) - 1);
3774 + return 0;
3775 + }
3776 +
3777 + if (ast_canmatch_extension(NULL, c->context, exten, 1, NULL)) {
3778 + return 1;
3779 + }
3780 +
3781 +
3782 + return -1;
3783 +}
3784 +
3785 +int pipe_msg(int PLCI,_cmsg *CMSG) {
3786 + struct capi_pipe *p;
3787 + _cmsg CMSG2;
3788 + MESSAGE_EXCHANGE_ERROR error;
3789 + struct ast_frame fr;
3790 + char b3buf[1024];
3791 + int j;
3792 + int b3len=0;
3793 + char dtmf;
3794 + unsigned dtmflen;
3795 +#ifdef CAPI_ES
3796 + int rxavg = 0;
3797 + int txavg = 0;
3798 +#endif
3799 +
3800 + p = find_pipe(PLCI,CMSG->Messagenumber);
3801 + if (p == NULL) {
3802 + if (IS_DISCONNECT_IND(CMSG)) {
3803 + DISCONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber , 0);
3804 + DISCONNECT_RESP_PLCI(&CMSG2) = PLCI;
3805 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
3806 + ast_log(LOG_NOTICE, "error sending DISCONNECT_RESP PLCI=%#x\n",PLCI);
3807 + } else {
3808 + if (option_verbose > 5) {
3809 + if (capidebug)
3810 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_RESP PLCI=%#x\n",PLCI);
3811 + }
3812 + }
3813 + return 0;
3814 + }
3815 + if (capidebug) {
3816 + ast_log(LOG_NOTICE,"%s",capi_cmsg2str(CMSG));
3817 + }
3818 + return -1;
3819 + }
3820 +
3821 + if (CMSG != NULL) {
3822 + switch (CMSG->Subcommand) {
3823 + case CAPI_IND:
3824 + switch (CMSG->Command) {
3825 + case CAPI_DISCONNECT_B3:
3826 +// ast_log(LOG_NOTICE,"DISCONNECT_B3_IND\n");
3827 +
3828 + DISCONNECT_B3_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
3829 + DISCONNECT_B3_RESP_NCCI(&CMSG2) = DISCONNECT_B3_IND_NCCI(CMSG);
3830 +
3831 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
3832 + ast_log(LOG_NOTICE, "error sending DISCONNECT_B3_RESP NCCI=%#x\n",(int)DISCONNECT_B3_IND_NCCI(CMSG));
3833 + } else {
3834 + if (option_verbose > 5) {
3835 + if (capidebug)
3836 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_B3_RESP NCCI=%#x\n",(int)DISCONNECT_B3_IND_NCCI(CMSG));
3837 + }
3838 + }
3839 + if (p->i->state == CAPI_STATE_BCONNECTED) {
3840 + // passive disconnect
3841 + p->i->state = CAPI_STATE_CONNECTED;
3842 + } else
3843 + if (p->i->state == CAPI_STATE_DISCONNECTING) {
3844 + // active disconnect
3845 + memset(&CMSG2,0,sizeof(_cmsg));
3846 + DISCONNECT_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
3847 + DISCONNECT_REQ_PLCI(&CMSG2) = PLCI;
3848 +
3849 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
3850 + ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",PLCI);
3851 + } else {
3852 + if (option_verbose > 5) {
3853 + if (capidebug)
3854 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_REQ PLCI=%#x\n",PLCI);
3855 + }
3856 + }
3857 + } else
3858 + if (p->i->state == CAPI_STATE_ONHOLD) {
3859 + // no hangup
3860 + }
3861 + ast_mutex_lock(&contrlock);
3862 + if (p->i->controller > 0) {
3863 + capi_controllers[p->i->controller]->nfreebchannels++;
3864 + }
3865 + ast_mutex_unlock(&contrlock);
3866 + break;
3867 + case CAPI_DISCONNECT:
3868 +// ast_log(LOG_NOTICE,"DISCONNECT_IND\n");
3869 + DISCONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber , 0);
3870 + DISCONNECT_RESP_PLCI(&CMSG2) = PLCI;
3871 +/* if (p->i->controller > 0) {
3872 + capi_controllers[p->i->controller]->nfreebchannels++;
3873 + } */
3874 +
3875 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
3876 + ast_log(LOG_NOTICE, "error sending DISCONNECT_RESP PLCI=%#x\n",PLCI);
3877 + } else {
3878 + if (option_verbose > 5) {
3879 + if (capidebug)
3880 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_RESP PLCI=%#x\n",PLCI);
3881 + }
3882 + }
3883 + if (p->c) {
3884 + p->c->hangupcause = DISCONNECT_IND_REASON(CMSG) - 0x3480;
3885 + }
3886 +
3887 + if (PLCI == p->i->onholdPLCI) {
3888 + // the caller onhold hung up (or ECTed away)
3889 + p->i->onholdPLCI = 0;
3890 + remove_pipe(PLCI);
3891 + return 0;
3892 + }
3893 +
3894 + if (p->i->state == CAPI_STATE_DID) {
3895 + if ((p->c) != NULL) {
3896 + ast_hangup(p->c);
3897 + } else {
3898 + ast_log(LOG_WARNING, "unable to hangup channel on DID. Channel is NULL.\n");
3899 + }
3900 + return 0;
3901 + }
3902 +
3903 + p->i->state = CAPI_STATE_DISCONNECTED;
3904 +
3905 + fr.frametype = AST_FRAME_CONTROL;
3906 + if (DISCONNECT_IND_REASON(CMSG) == 0x34a2) {
3907 + fr.subclass = AST_CONTROL_BUSY;
3908 + } else {
3909 + fr.frametype = AST_FRAME_NULL;
3910 + }
3911 + fr.datalen = 0;
3912 + if (pipe_frame(p,(struct ast_frame *)&fr) == -1) {
3913 + // printf("STATE = %#x\n",p->i->state);
3914 + // in this case * did not read our hangup control frame
3915 + // so we must hangup the channel!
3916 + if ( (p->i->state != CAPI_STATE_DISCONNECTED) && (ast_check_hangup(p->c) == 0)) {
3917 + if (option_verbose > 1) {
3918 + ast_verbose(VERBOSE_PREFIX_3 "soft hangup by capi\n");
3919 + }
3920 + ast_softhangup(p->c,AST_SOFTHANGUP_DEV);
3921 + } else {
3922 + // dont ever hangup while hanging up!
3923 +// ast_log(LOG_NOTICE,"no soft hangup by capi\n");
3924 + }
3925 + return -1;
3926 + } else {
3927 + return 0;
3928 + }
3929 +
3930 +/* fr.frametype = AST_FRAME_NULL;
3931 + fr.datalen = 0;
3932 + pipe_frame(p,(struct ast_frame *)&fr); */
3933 + break;
3934 + case CAPI_DATA_B3:
3935 +
3936 + memcpy(&b3buf[AST_FRIENDLY_OFFSET],(char *)DATA_B3_IND_DATA(CMSG),DATA_B3_IND_DATALENGTH(CMSG));
3937 + b3len = DATA_B3_IND_DATALENGTH(CMSG);
3938 +
3939 + // send a DATA_B3_RESP very quickly to free the buffer in capi
3940 + DATA_B3_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber,0);
3941 + DATA_B3_RESP_NCCI(&CMSG2) = DATA_B3_IND_NCCI(CMSG);
3942 + DATA_B3_RESP_DATAHANDLE(&CMSG2) = DATA_B3_IND_DATAHANDLE(CMSG);
3943 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
3944 + ast_log(LOG_ERROR,"error sending DATA_B3_RESP (error=%#x)\n",error);
3945 + } else {
3946 + if (option_verbose > 6) {
3947 + if (capidebug)
3948 + ast_verbose(VERBOSE_PREFIX_4 "sent DATA_B3_RESP (NCCI=%#x)\n",(int)DATA_B3_IND_NCCI(CMSG));
3949 + }
3950 + }
3951 +#ifdef CAPI_SYNC
3952 + ast_mutex_lock(&p->i->lockB3in);
3953 + p->i->B3in++;
3954 + if (p->i->B3in > AST_CAPI_MAX_B3_BLOCKS) p->i->B3in = AST_CAPI_MAX_B3_BLOCKS;
3955 + ast_mutex_unlock(&p->i->lockB3in);
3956 +#endif
3957 +#ifdef CAPI_ES
3958 + if ((p->i->doES == 1)) {
3959 + for (j=0;j<b3len;j++) {
3960 + b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]];
3961 + rxavg += abs(capiXLAW2INT( reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]));
3962 + }
3963 + rxavg = rxavg/j;
3964 + for(j=0;j<ECHO_EFFECTIVE_TX_COUNT;j++) {
3965 + txavg += p->i->txavg[j];
3966 + }
3967 + txavg = txavg/j;
3968 +
3969 + if( (txavg/ECHO_TXRX_RATIO) > rxavg) {
3970 +#ifdef CAPI_ULAW
3971 + memset(&b3buf[AST_FRIENDLY_OFFSET],255,b3len);
3972 +#else
3973 + memset(&b3buf[AST_FRIENDLY_OFFSET],84,b3len);
3974 +#endif
3975 + if (capidebug) {
3976 + ast_log(LOG_NOTICE,"SUPPRESSING ECHOrx=%d, tx=%d\n",rxavg,txavg);
3977 + }
3978 + }
3979 + } else {
3980 +#ifdef CAPI_GAIN
3981 + for (j=0;j<b3len;j++) {
3982 + b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[p->i->g.rxgains[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]];
3983 + }
3984 +#else
3985 + for (j=0;j<b3len;j++) {
3986 + b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]];
3987 + }
3988 +#endif
3989 + }
3990 +#else
3991 +
3992 +#ifdef CAPI_GAIN
3993 + for (j=0;j<b3len;j++) {
3994 + b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[p->i->g.rxgains[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]];
3995 + }
3996 +#else
3997 + for (j=0;j<b3len;j++) {
3998 + b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]];
3999 + }
4000 +#endif
4001 +
4002 +#endif
4003 + // just being paranoid ...
4004 + /* if (p->c->_state != AST_STATE_UP) {
4005 + ast_setstate(p->c,AST_STATE_UP);
4006 + } */
4007 +
4008 + fr.frametype = AST_FRAME_VOICE;
4009 + fr.subclass = capi_capability;
4010 + fr.data = (char *)&b3buf[AST_FRIENDLY_OFFSET];
4011 + fr.datalen = b3len;
4012 + fr.samples = b3len;
4013 + fr.offset = AST_FRIENDLY_OFFSET;
4014 + fr.mallocd = 0;
4015 + fr.delivery.tv_sec = 0;
4016 + fr.delivery.tv_usec = 0;
4017 + fr.src = NULL;
4018 + // 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);
4019 + return pipe_frame(p,(struct ast_frame *)&fr);
4020 + break;
4021 + case CAPI_FACILITY:
4022 + if (FACILITY_IND_FACILITYSELECTOR(CMSG) == 0x0001) {
4023 + // DTMF received
4024 + if (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[0] != (0xff)) {
4025 + dtmflen = FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[0];
4026 + FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG) += 1;
4027 + } else {
4028 + dtmflen = ((__u16 *) (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG) + 1))[0];
4029 + FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG) += 3;
4030 + }
4031 + if (dtmflen == 1) {
4032 + dtmf = (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG))[0];
4033 + fr.frametype = AST_FRAME_DTMF;
4034 + fr.subclass = dtmf;
4035 + if (option_verbose > 1) {
4036 + if (capidebug)
4037 + ast_verbose(VERBOSE_PREFIX_3 "c_dtmf = %c\n",dtmf);
4038 + }
4039 + pipe_frame(p,(struct ast_frame *)&fr);
4040 + }
4041 + }
4042 + if (FACILITY_IND_FACILITYSELECTOR(CMSG) == 0x0003) {
4043 + // sservices
4044 + /* ast_log(LOG_NOTICE,"FACILITY_IND PLCI = %#x\n",(int)FACILITY_IND_PLCI(CMSG));
4045 + ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[0]);
4046 + ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[1]);
4047 + ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[2]);
4048 + ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[3]);
4049 + ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4]);
4050 + ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5]); */
4051 + // RETRIEVE
4052 + if ( (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[1] == 0x3) && (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[3] == 0x2)) {
4053 + p->i->state = CAPI_STATE_CONNECTED;
4054 + p->i->PLCI = p->i->onholdPLCI;
4055 + p->i->onholdPLCI = 0;
4056 + }
4057 + if ( (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[1] == 0x2) && (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[3] == 0x2)) {
4058 + if ((FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5] != 0) && (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4] != 0)) {
4059 + // reason != 0x0000 == problem
4060 + p->i->onholdPLCI = 0;
4061 + p->i->state = CAPI_STATE_ONHOLD;
4062 + 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]);
4063 + } else {
4064 + // reason = 0x0000 == call on hold
4065 + p->i->state = CAPI_STATE_ONHOLD;
4066 + if (capidebug)
4067 + ast_log(LOG_NOTICE, "PLCI=%#x put onhold\n",(int)FACILITY_IND_PLCI(CMSG));
4068 + }
4069 + }
4070 + }
4071 +
4072 + error = FACILITY_RESP(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber,FACILITY_IND_PLCI(CMSG),FACILITY_IND_FACILITYSELECTOR(CMSG),FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG));
4073 +
4074 + if (error != 0) {
4075 + ast_log(LOG_ERROR,"error sending FACILITY_RESP (error=%#x)\n",error);
4076 + } else {
4077 + if (option_verbose > 5) {
4078 + if (capidebug)
4079 + ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_RESP (PLCI=%#x)\n",(int)FACILITY_IND_PLCI(CMSG));
4080 + }
4081 + }
4082 + break;
4083 + case CAPI_INFO:
4084 + // ast_log(LOG_ERROR,"INFO_IND PLCI=%#x INFO# = %#x\n",PLCI,INFO_IND_INFONUMBER(CMSG));
4085 +
4086 + memset(&CMSG2,0,sizeof(_cmsg));
4087 + error = INFO_RESP(&CMSG2,ast_capi_ApplID,CMSG->Messagenumber,PLCI);
4088 + if (error != 0) {
4089 + ast_log(LOG_ERROR,"error sending INFO_RESP (error=%#x)\n",error);
4090 + return -1;
4091 + } else {
4092 + if (option_verbose > 5) {
4093 + if (capidebug)
4094 + ast_verbose(VERBOSE_PREFIX_4 "sent INFO_RESP (PLCI=%#x)\n",PLCI);
4095 + }
4096 + }
4097 +/* if ((INFO_IND_INFONUMBER(CMSG) >> 8) == 0x00) {
4098 + ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[0]);
4099 + ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[1]);
4100 + ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[2]);
4101 + ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[3]);
4102 + } */
4103 +#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
4104 + if ((INFO_IND_INFONUMBER(CMSG) == 0x001e) && (p->i->doB3 != AST_CAPI_B3_DONT) && (p->i->earlyB3 == -1) && (p->i->state != CAPI_STATE_BCONNECTED)){
4105 + // ETSI 300 102-1 Progress Indicator
4106 + // we do early B3 Connect
4107 + if(INFO_IND_INFOELEMENT(CMSG)[0] >= 2) {
4108 + if(INFO_IND_INFOELEMENT(CMSG)[2] & 0x2) {
4109 + p->i->calledPartyIsISDN = 0;
4110 + // ast_log(LOG_NOTICE,"A N A L O G \n");
4111 + } else {
4112 + p->i->calledPartyIsISDN = 1;
4113 + // ast_log(LOG_NOTICE,"I S D N\n");
4114 + }
4115 + if(INFO_IND_INFOELEMENT(CMSG)[2] & 0x88) {
4116 + // in-band info available
4117 + p->i->earlyB3 = 1;
4118 + memset(&CMSG2,0,sizeof(_cmsg));
4119 + CONNECT_B3_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++,0);
4120 + CONNECT_B3_REQ_PLCI(&CMSG2) = PLCI;
4121 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4122 + ast_log(LOG_ERROR,"error sending early CONNECT_B3_REQ (error=%#x)\n",error);
4123 + return -1;
4124 + } else {
4125 + if (option_verbose > 1) {
4126 + if (capidebug)
4127 + ast_verbose(VERBOSE_PREFIX_4 "sent early CONNECT_B3_REQ (PLCI=%#x)\n",PLCI);
4128 + }
4129 + }
4130 + }
4131 + }
4132 + }
4133 + // DISCONNECT
4134 + if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (PLCI == p->i->onholdPLCI)) {
4135 + // the caller onhold hung up (or ECTed away)
4136 + // send a disconnect_req , we cannot hangup the channel here!!!
4137 + memset(&CMSG2,0,sizeof(_cmsg));
4138 + DISCONNECT_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
4139 + DISCONNECT_REQ_PLCI(&CMSG2) = p->i->onholdPLCI;
4140 +
4141 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4142 + ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",PLCI);
4143 + } else {
4144 + if (option_verbose > 1) {
4145 + if (capidebug)
4146 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_REQ for onholdPLCI=%#x\n",PLCI);
4147 + }
4148 + }
4149 + return 0;
4150 + }
4151 +
4152 + // case 1: B3 on success or no B3 at all
4153 + if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->doB3 != AST_CAPI_B3_ALWAYS) && (p->i->outgoing == 1)) {
4154 + p->i->earlyB3 = 0; // !!!
4155 + fr.frametype = AST_FRAME_NULL;
4156 + fr.datalen = 0;
4157 + return pipe_frame(p,(struct ast_frame *)&fr);
4158 + }
4159 + // case 2: we are doing B3, and receive the 0x8045 after a successful call
4160 + if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->doB3 != AST_CAPI_B3_DONT) && (p->i->earlyB3 == 0) && (p->i->outgoing == 1)) {
4161 + fr.frametype = AST_FRAME_NULL;
4162 + fr.datalen = 0;
4163 + return pipe_frame(p,(struct ast_frame *)&fr);
4164 + }
4165 + // case 3: this channel is an incoming channel! the user hung up!
4166 + // it is much better to hangup now instead of waiting for a timeout and
4167 + // network caused DISCONNECT_IND!
4168 + if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->outgoing == 0)) {
4169 + // ast_log(LOG_NOTICE,"case 3\n");
4170 + fr.frametype = AST_FRAME_NULL;
4171 + fr.datalen = 0;
4172 + return pipe_frame(p,(struct ast_frame *)&fr);
4173 + }
4174 + // case 4 (a.k.a. the italian case): B3 always. call is unsuccessful
4175 + if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->doB3 == AST_CAPI_B3_ALWAYS) && (p->i->earlyB3 == -1) && (p->i->outgoing == 1)) {
4176 + // wait for the 0x001e (PROGRESS), play audio and wait for a timeout from the network
4177 + return 0;
4178 + }
4179 +#endif
4180 + // Handle DID digits
4181 + if ((INFO_IND_INFONUMBER(CMSG) == 0x0070) && p->i->isdnmode && (p->c != NULL)) {
4182 + int search = -1;
4183 + char name[AST_CHANNEL_NAME] = "";
4184 + char *did;
4185 +
4186 + did = capi_number((char *)INFO_IND_INFOELEMENT(CMSG),1);
4187 + if (strcasecmp(p->i->dnid, did)) {
4188 + strncat(p->i->dnid, did, sizeof(p->i->dnid)-1);
4189 + }
4190 +
4191 + snprintf(name,sizeof(name),"CAPI/contr%d/%s/-%d",p->i->controller,p->i->dnid,capi_counter++);
4192 + ast_change_name(p->c, name);
4193 +
4194 + search = search_did(p->c);
4195 + if (search != -1) {
4196 + if (!search) {
4197 + ast_setstate(p->c, AST_STATE_RING);
4198 + // we are alerting (phones ringing)
4199 + capi_alert(p->c); // Do this here after pbx_start the Channel can be destroyed
4200 + if (ast_pbx_start(p->c)) {
4201 + ast_log(LOG_ERROR,"Unable to start pbx on channel!\n");
4202 + ast_hangup(p->c);
4203 + } else {
4204 + if (option_verbose > 2) {
4205 + if (capidebug)
4206 + ast_verbose(VERBOSE_PREFIX_3 "started pbx on channel!\n");
4207 + }
4208 + }
4209 + }
4210 + } else {
4211 + ast_log(LOG_ERROR,"did not find device for msn = %s\n",p->i->dnid);
4212 + CONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4213 + CONNECT_RESP_PLCI(&CMSG2) = PLCI;
4214 + CONNECT_RESP_REJECT(&CMSG2) = 1; // ignore
4215 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4216 + ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4217 + } else {
4218 + if (option_verbose > 5) {
4219 + if (capidebug)
4220 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4221 + }
4222 + }
4223 +
4224 + return 0;
4225 + }
4226 + }
4227 + if (INFO_IND_INFONUMBER(CMSG) == 0x8001) {
4228 + fr.frametype = AST_FRAME_CONTROL;
4229 + fr.subclass = AST_CONTROL_RINGING;
4230 + return pipe_frame(p,(struct ast_frame *)&fr);
4231 + }
4232 + if (INFO_IND_INFONUMBER(CMSG) == 0x800d) {
4233 + fr.frametype = AST_FRAME_CONTROL;
4234 + fr.subclass = AST_CONTROL_PROGRESS;
4235 + return pipe_frame(p,(struct ast_frame *)&fr);
4236 + }
4237 + if (INFO_IND_INFONUMBER(CMSG) == 0x74) {
4238 + strncpy(p->i->owner->exten,capi_number((char *)INFO_IND_INFOELEMENT(CMSG),3),sizeof(p->i->owner->exten)-1);
4239 + ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(CMSG));
4240 + }
4241 + if (INFO_IND_INFONUMBER(CMSG) == 0x28) {
4242 + // ast_sendtext(p->i->owner,capi_number(INFO_IND_INFOELEMENT(CMSG),0));
4243 + // struct ast_frame ft = { AST_FRAME_TEXT, capi_number(INFO_IND_INFOELEMENT(CMSG),0), };
4244 + // ast_queue_frame(p->i->owner, &ft);
4245 + // ast_log(LOG_NOTICE,"%s\n",capi_number(INFO_IND_INFOELEMENT(CMSG),0));
4246 + }
4247 + break;
4248 + case CAPI_CONNECT_ACTIVE:
4249 +// ast_log(LOG_NOTICE,"CONNECT_ACTIVE_IND PLCI=%#x\n",(int)CONNECT_ACTIVE_IND_PLCI(CMSG));
4250 + CONNECT_ACTIVE_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber,0);
4251 + CONNECT_ACTIVE_RESP_PLCI(&CMSG2) = PLCI;
4252 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4253 + ast_log(LOG_ERROR,"error sending CONNECT_ACTIVE_RESP (error=%#x)\n",error);
4254 + return -1;
4255 + } else {
4256 + if (option_verbose > 5) {
4257 + if (capidebug)
4258 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_ACTIVE_RESP (PLCI=%#x)\n",PLCI);
4259 + }
4260 + }
4261 + // normal processing
4262 + if (p->i->earlyB3 != 1) {
4263 + p->i->state = CAPI_STATE_CONNECTED;
4264 +
4265 + // send a CONNECT_B3_REQ
4266 + if (p->i->outgoing == 1) {
4267 + // outgoing call
4268 + memset(&CMSG2,0,sizeof(_cmsg));
4269 + CONNECT_B3_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++,0);
4270 + CONNECT_B3_REQ_PLCI(&CMSG2) = PLCI;
4271 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4272 + ast_log(LOG_ERROR,"error sending CONNECT_B3_REQ (error=%#x)\n",error);
4273 + return -1;
4274 + } else {
4275 + if (option_verbose > 1) {
4276 + if (capidebug)
4277 + ast_verbose(VERBOSE_PREFIX_3 "sent CONNECT_B3_REQ (PLCI=%#x)\n",PLCI);
4278 + }
4279 + }
4280 + } else {
4281 + // incoming call
4282 + // RESP already sent ... wait for CONNECT_B3_IND
4283 +// ast_log(LOG_NOTICE,"waiting for CONNECT_B3_IND\n");
4284 + }
4285 + } else {
4286 + // special treatment for early B3 connects
4287 + p->i->state = CAPI_STATE_BCONNECTED;
4288 + if (p->c->_state != AST_STATE_UP) {
4289 + ast_setstate(p->c,AST_STATE_UP);
4290 + }
4291 + p->i->earlyB3 = 0; // not early anymore
4292 + fr.frametype = AST_FRAME_CONTROL;
4293 + fr.subclass = AST_CONTROL_ANSWER;
4294 + fr.datalen = 0;
4295 + return pipe_frame(p,(struct ast_frame *)&fr);
4296 +
4297 + }
4298 + break;
4299 + case CAPI_CONNECT_B3:
4300 + // then send a CONNECT_B3_RESP
4301 + memset(&CMSG2,0,sizeof(_cmsg));
4302 + CONNECT_B3_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4303 + CONNECT_B3_RESP_NCCI(&CMSG2) = CONNECT_B3_IND_NCCI(CMSG);
4304 + p->NCCI = CONNECT_B3_IND_NCCI(CMSG);
4305 + p->i->NCCI = p->NCCI;
4306 + CONNECT_B3_RESP_REJECT(&CMSG2) = 0;
4307 +
4308 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4309 + ast_log(LOG_ERROR,"error sending CONNECT_B3_RESP (error=%#x)\n",error);
4310 + return -1;
4311 + } else {
4312 + if (option_verbose > 5) {
4313 + if (capidebug)
4314 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_B3_RESP (NCCI=%#x)\n",p->i->NCCI);
4315 + }
4316 + }
4317 + /* if (p->i->controller > 0) {
4318 + capi_controllers[p->i->controller]->nfreebchannels--;
4319 + } */
4320 + break;
4321 + case CAPI_CONNECT_B3_ACTIVE:
4322 +// ast_log(LOG_NOTICE,"CONNECT_B3_ACTIVE_IND NCCI=%#x\n",p->i->NCCI);
4323 + // then send a CONNECT_B3__ACTIVERESP
4324 +
4325 + CONNECT_B3_ACTIVE_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4326 + CONNECT_B3_ACTIVE_RESP_NCCI(&CMSG2) = p->i->NCCI;
4327 +
4328 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4329 + ast_log(LOG_ERROR,"error sending CONNECT_B3_ACTIVE_RESP (error=%#x)\n",error);
4330 + return -1;
4331 + } else {
4332 + if (option_verbose > 5) {
4333 + if (capidebug)
4334 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_B3_ACTIVE_RESP (NCCI=%#x)\n",p->i->NCCI);
4335 + }
4336 + }
4337 +
4338 + ast_mutex_lock(&contrlock);
4339 + if (p->i->controller > 0) {
4340 + capi_controllers[p->i->controller]->nfreebchannels--;
4341 + }
4342 + ast_mutex_unlock(&contrlock);
4343 +
4344 + p->i->state = CAPI_STATE_BCONNECTED;
4345 + capi_echo_canceller(p->c,EC_FUNCTION_ENABLE);
4346 + capi_detect_dtmf(p->c,1);
4347 +
4348 + if (p->i->earlyB3 != 1) {
4349 + ast_setstate(p->c,AST_STATE_UP);
4350 + fr.frametype = AST_FRAME_CONTROL;
4351 + fr.subclass = AST_CONTROL_ANSWER;
4352 + fr.datalen = 0;
4353 + return pipe_frame(p,(struct ast_frame *)&fr);
4354 + }
4355 + return 0;
4356 + break;
4357 + }
4358 + break;
4359 +
4360 + case CAPI_CONF:
4361 + switch (CMSG->Command) {
4362 + case CAPI_FACILITY:
4363 + if (FACILITY_CONF_FACILITYSELECTOR(CMSG) == 0x3) {
4364 + if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[1] == 0x2) && (FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[2] == 0x0)) {
4365 + if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[4] == 0x0) && (FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[5] == 0x0)) {
4366 + } else {
4367 + p->i->state = CAPI_STATE_BCONNECTED;
4368 + if (capidebug)
4369 + ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(CMSG));
4370 + }
4371 + }
4372 + }
4373 + break;
4374 + case CAPI_DATA_B3:
4375 +// ast_log(LOG_NOTICE,"DATA_B3_CONF (NCCI %#x) for DATAHANDLE %#x\n",DATA_B3_CONF_NCCI(CMSG),DATA_B3_CONF_DATAHANDLE(CMSG));
4376 + break;
4377 + case CAPI_ALERT:
4378 +// ast_log(LOG_NOTICE,"ALERT_CONF (PLCI=%#x)\n",(int)ALERT_CONF_PLCI(CMSG));
4379 + p->i->state = CAPI_STATE_ALERTING;
4380 + if (p->c->_state == AST_STATE_RING) {
4381 + p->c->rings = 1;
4382 + }
4383 + break;
4384 + case CAPI_CONNECT:
4385 + if (option_verbose > 1) {
4386 + if (capidebug)
4387 + ast_verbose(VERBOSE_PREFIX_2 "received CONNECT_CONF PLCI = %#x INFO = %#x\n",(int)CONNECT_CONF_PLCI(CMSG),CONNECT_CONF_INFO(CMSG));
4388 + }
4389 + if (CONNECT_CONF_INFO(CMSG) == 0) {
4390 + p->i->PLCI = CONNECT_CONF_PLCI(CMSG);
4391 + p->PLCI = p->i->PLCI;
4392 + ast_setstate(p->c,AST_STATE_DIALING);
4393 + } else {
4394 + // here, something has to be done -->
4395 + fr.frametype = AST_FRAME_CONTROL;
4396 + fr.subclass = AST_CONTROL_BUSY;
4397 + fr.datalen = 0;
4398 + return pipe_frame(p,(struct ast_frame *)&fr);
4399 + }
4400 + break;
4401 + case CAPI_CONNECT_B3:
4402 +// ast_log(LOG_NOTICE,"received CONNECT_B3_CONF NCCI = %#x INFO = %#x\n",(int)CONNECT_B3_CONF_NCCI(CMSG),CONNECT_B3_CONF_INFO(CMSG));
4403 + if (CONNECT_B3_CONF_INFO(CMSG) == 0) {
4404 + p->i->NCCI = CONNECT_B3_CONF_NCCI(CMSG);
4405 + } else {
4406 + p->i->earlyB3 = -1;
4407 + p->i->doB3 = AST_CAPI_B3_DONT;
4408 + }
4409 + break;
4410 + }
4411 + break;
4412 + }
4413 + }
4414 +// ast_log(LOG_NOTICE,"returning\n");
4415 + return 0;
4416 +}
4417 +
4418 +static void capi_handle_msg(_cmsg *CMSG) {
4419 + struct ast_capi_pvt *i;
4420 + char *DNID;
4421 + char *CID;
4422 + char *msn;
4423 + _cmsg CMSG2;
4424 + MESSAGE_EXCHANGE_ERROR error;
4425 + int PLCI=0,NCCI;
4426 + int NPLAN=0;
4427 + int fds[2];
4428 + int controller=0;
4429 + char buffer[AST_MAX_EXTENSION];
4430 + struct capi_pipe *p;
4431 + char *magicmsn = "*\0";
4432 + char *emptyid = "\0";
4433 + char *emptydnid = "s\0";
4434 + long flags;
4435 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
4436 + int deflect=0;
4437 +#endif
4438 +
4439 + switch (CMSG->Subcommand) {
4440 + // indication msgs
4441 + case CAPI_IND:
4442 +
4443 + switch (CMSG->Command) {
4444 + case CAPI_CONNECT: // only connect_ind are global (not channel specific)
4445 + if (capidebug)
4446 + ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(CMSG));
4447 + DNID = capi_number((char *)CONNECT_IND_CALLEDPARTYNUMBER(CMSG),1);
4448 + if ((DNID && *DNID == 0) || !DNID) {
4449 + DNID = emptydnid;
4450 + }
4451 + NPLAN = (CONNECT_IND_CALLINGPARTYNUMBER(CMSG)[1] & 0x70);
4452 + CID = capi_number((char *)CONNECT_IND_CALLINGPARTYNUMBER(CMSG),2);
4453 + PLCI = CONNECT_IND_PLCI(CMSG);
4454 + controller = PLCI & 0xff;
4455 + if (option_verbose > 1) {
4456 + if (capidebug)
4457 + 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);
4458 + }
4459 + if(CONNECT_IND_BCHANNELINFORMATION(CMSG))
4460 + if ((CONNECT_IND_BCHANNELINFORMATION(CMSG)[1] == 0x02) && (!capi_controllers[controller]->isdnmode)) {
4461 + // this is a call waiting CONNECT_IND with BChannelinformation[1] == 0x02
4462 + // meaning "no B or D channel for this call", since we can't do anything with call waiting now
4463 + // just reject it with "user busy"
4464 + // however...if we are a p2p BRI then the telco switch will allow us to choose the b channel
4465 + // so it will look like a callwaiting connect_ind to us
4466 +
4467 + ast_log(LOG_ERROR,"received a call waiting CONNECT_IND\n");
4468 +#ifndef CAPI_DEFLECT_ON_CIRCUITBUSY
4469 + CONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4470 + CONNECT_RESP_PLCI(&CMSG2) = CONNECT_IND_PLCI(CMSG);
4471 + CONNECT_RESP_REJECT(&CMSG2) = 3; // user is busy
4472 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4473 + ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4474 + } else {
4475 + if (option_verbose > 5) {
4476 + if (capidebug)
4477 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4478 + }
4479 + }
4480 + // no need to pipe this
4481 + PLCI = 0;
4482 + break;
4483 +#else
4484 + deflect = 1;
4485 +#endif
4486 + }
4487 + // well...somebody is calling us. let's set up a channel
4488 + ast_mutex_lock(&iflock);
4489 + i = iflist;
4490 + while(i) {
4491 + //XXX test this!
4492 + // has no owner
4493 + if ((!i->owner) && (i->incomingmsn != NULL)){
4494 + strncpy(buffer,i->incomingmsn,sizeof(buffer)-1);
4495 + msn = strtok(buffer,",");
4496 + while (msn != NULL) {
4497 +// ast_log(LOG_NOTICE,"msn=%s\n",msn);
4498 + if (DNID && ((!strcasecmp(msn,DNID)) ||
4499 + (i->isdnmode && (strlen(msn)<strlen(DNID)) && !strncasecmp(msn, DNID, strlen(msn))) || (!strncasecmp(msn,magicmsn,strlen(msn)))) &&
4500 + (i->controllers & (1 << controller))) {
4501 + if (CID != NULL) {
4502 + if(NPLAN == CAPI_ETSI_NPLAN_NATIONAL)
4503 + snprintf(i->cid, (sizeof(i->cid)-1), "%s%s%s", i->prefix, capi_national_prefix, CID);
4504 + else if(NPLAN == CAPI_ETSI_NPLAN_INTERNAT)
4505 + snprintf(i->cid, (sizeof(i->cid)-1), "%s%s%s", i->prefix, capi_international_prefix, CID);
4506 + else
4507 + snprintf(i->cid, (sizeof(i->cid)-1), "%s%s", i->prefix, CID);
4508 + } else
4509 + strncpy(i->cid,emptyid,sizeof(i->cid)-1);
4510 +
4511 + if (DNID != NULL)
4512 + strncpy(i->dnid,DNID,sizeof(i->dnid)-1);
4513 + else
4514 + strncpy(i->dnid,emptydnid,sizeof(i->dnid)-1);
4515 +
4516 + i->controller=controller;
4517 + i->PLCI = PLCI;
4518 + i->MessageNumber = CMSG->Messagenumber;
4519 + if (pipe(fds) == 0) {
4520 + if (option_verbose > 4) {
4521 + ast_verbose(VERBOSE_PREFIX_3 "creating pipe for PLCI=%#x msn = %s\n",PLCI,msn);
4522 + }
4523 + i->fd = fds[0];
4524 + flags = fcntl(i->fd,F_GETFL);
4525 + fcntl(i->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
4526 +// ast_log(LOG_NOTICE,"i->fd = %d\n",i->fd);
4527 + p = malloc(sizeof(struct capi_pipe));
4528 + memset(p, 0, sizeof(struct capi_pipe));
4529 + p->fd = fds[1];
4530 + flags = fcntl(i->fd,F_GETFL);
4531 + fcntl(p->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
4532 +// ast_log(LOG_NOTICE,"p->fd = %d\n",p->fd);
4533 + p->PLCI = PLCI;
4534 + p->i = i;
4535 + ast_mutex_init(&(p->lock));
4536 + i->mypipe = p;
4537 + if (i->isdnmode) {
4538 + p->c = capi_new(i,AST_STATE_DOWN);
4539 + i->state = CAPI_STATE_DID;
4540 + } else {
4541 + p->c = capi_new(i,AST_STATE_RING);
4542 + }
4543 + p->next = pipelist;
4544 + pipelist = p;
4545 + // hmmm....
4546 + ast_mutex_unlock(&iflock);
4547 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
4548 + if ((deflect == 1) && (i->deflect2)) {
4549 + capi_deflect(p->c,i->deflect2);
4550 + }
4551 +#endif
4552 + return;
4553 + } else {
4554 + ast_log(LOG_ERROR,"creating pipe for PLCI=%#x failed\n",PLCI);
4555 + }
4556 + break;
4557 + } // if strcasecmp
4558 + msn = strtok(NULL,",");
4559 + } // while strtok
4560 + } // if
4561 + i = i->next;
4562 + } // while interface list
4563 + ast_mutex_unlock(&iflock); // obviously we are not called...so tell capi to ignore this call
4564 + if (capidebug) {
4565 + ast_log(LOG_ERROR,"did not find device for msn = %s\n",DNID);
4566 + }
4567 + CONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4568 + CONNECT_RESP_PLCI(&CMSG2) = CONNECT_IND_PLCI(CMSG);
4569 + CONNECT_RESP_REJECT(&CMSG2) = 1; // ignore
4570 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4571 + ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4572 + } else {
4573 + if (option_verbose > 5) {
4574 + if (capidebug)
4575 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4576 + }
4577 + }
4578 + ast_mutex_lock(&pipelock);
4579 + if (pipelist == NULL) {
4580 + capi_last_plci = PLCI;
4581 + }
4582 + ast_mutex_unlock(&pipelock);
4583 + // no need to pipe this
4584 + PLCI = 0;
4585 +// ast_mutex_unlock(&iflock);
4586 +// return;
4587 + break;
4588 + case CAPI_FACILITY:
4589 + PLCI = FACILITY_IND_PLCI(CMSG) & 0xffff; // this is for you eicon
4590 + if (option_verbose > 3) {
4591 + if (capidebug)
4592 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4593 + }
4594 +// ast_log(LOG_ERROR,"FACILITY_IND PLCI=%#x\n",PLCI);
4595 + break;
4596 + case CAPI_INFO:
4597 + PLCI = INFO_IND_PLCI(CMSG);
4598 + if (option_verbose > 3) {
4599 + if (capidebug)
4600 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4601 + }
4602 +// ast_log(LOG_ERROR,"INFO_IND PLCI=%#x INFO# = %#x\n",PLCI,INFO_IND_INFONUMBER(CMSG));
4603 + break;
4604 + case CAPI_CONNECT_ACTIVE:
4605 + PLCI = CONNECT_ACTIVE_IND_PLCI(CMSG);
4606 + if (option_verbose > 3) {
4607 + if (capidebug)
4608 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4609 + }
4610 +// ast_log(LOG_ERROR,"CONNECT_ACTIVE_IND PLCI=%#x\n",PLCI);
4611 + break;
4612 + case CAPI_CONNECT_B3:
4613 + NCCI = CONNECT_B3_IND_NCCI(CMSG);
4614 + PLCI = (NCCI << 16) >> 16;
4615 + if (option_verbose > 3) {
4616 + if (capidebug)
4617 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4618 + }
4619 +// ast_log(LOG_ERROR,"CONNECT_B3_IND NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
4620 + break;
4621 + case CAPI_CONNECT_B3_ACTIVE:
4622 + NCCI = CONNECT_B3_IND_NCCI(CMSG);
4623 + PLCI = (NCCI << 16) >> 16;
4624 + if (option_verbose > 3) {
4625 + if (capidebug)
4626 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4627 + }
4628 +// ast_log(LOG_ERROR,"CONNECT_B3_ACTIVE_IND NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
4629 + break;
4630 + case CAPI_DATA_B3:
4631 + NCCI = DATA_B3_IND_NCCI(CMSG);
4632 + PLCI = (NCCI << 16) >> 16;
4633 +// ast_log(LOG_ERROR,"DATA_B3_IND NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
4634 + break;
4635 + case CAPI_DISCONNECT_B3:
4636 + NCCI = DISCONNECT_B3_IND_NCCI(CMSG);
4637 + PLCI = (NCCI << 16) >> 16;
4638 + if (option_verbose > 1) {
4639 + if (capidebug)
4640 + ast_verbose(VERBOSE_PREFIX_2 "DISCONNECT_B3_IND NCCI=%#x\n",NCCI);
4641 + }
4642 + break;
4643 + case CAPI_DISCONNECT:
4644 + PLCI = DISCONNECT_IND_PLCI(CMSG);
4645 + if (option_verbose > 1) {
4646 + if (capidebug)
4647 + ast_verbose(VERBOSE_PREFIX_2 "DISCONNECT_IND PLCI=%#x REASON=%#x\n",PLCI,DISCONNECT_IND_REASON(CMSG));
4648 + }
4649 + break;
4650 + default:
4651 + ast_log(LOG_ERROR,"Command.Subcommand = %#x.%#x\n",CMSG->Command,CMSG->Subcommand);
4652 + }
4653 + break;
4654 + // confirmation msgs
4655 + case CAPI_CONF:
4656 + switch (CMSG->Command) {
4657 + case CAPI_FACILITY:
4658 + NCCI = FACILITY_CONF_NCCI(CMSG);
4659 + PLCI = (NCCI << 16) >> 16;
4660 + if (option_verbose > 2) {
4661 + if (FACILITY_CONF_FACILITYSELECTOR(CMSG) == 6) {
4662 + if (FACILITY_CONF_INFO(CMSG))
4663 + ast_verbose (VERBOSE_PREFIX_3 "Error setting up echo canceller (PLCI=%#x, Info=%#04x)\n", PLCI, FACILITY_CONF_INFO(CMSG));
4664 + else
4665 + ast_verbose (VERBOSE_PREFIX_3 "Echo canceller successfully set up (PLCI=%#x)\n",PLCI);
4666 + }
4667 + }
4668 + if (option_verbose > 3) {
4669 + if (capidebug)
4670 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4671 + }
4672 +// ast_log(LOG_ERROR,"FACILITY_CONF NCCI=%#x INFO=%#x\n",(int)FACILITY_CONF_NCCI(CMSG),FACILITY_CONF_INFO(CMSG));
4673 + break;
4674 + case CAPI_INFO:
4675 + PLCI = INFO_CONF_PLCI(CMSG);
4676 +// ast_log(LOG_ERROR,"INFO_CONF PLCI=%#x INFO=%#x\n",PLCI,INFO_CONF_INFO(CMSG));
4677 + break;
4678 + case CAPI_CONNECT:
4679 + PLCI = CONNECT_CONF_PLCI(CMSG);
4680 + if (option_verbose > 3) {
4681 + if (capidebug)
4682 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4683 + }
4684 +// ast_log(LOG_ERROR,"CONNECT_CONF PLCI=%#x INFO=%#x MN=%#x\n",PLCI,CONNECT_CONF_INFO(CMSG),CMSG->Messagenumber);
4685 + break;
4686 + case CAPI_DISCONNECT:
4687 + PLCI = DISCONNECT_CONF_PLCI(CMSG);
4688 + if (option_verbose > 3) {
4689 + if (capidebug)
4690 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4691 + }
4692 +// ast_log(LOG_ERROR,"DISCONNECT_CONF PLCI=%#x INFO=%#x MN=%#x\n",PLCI,DISCONNECT_CONF_INFO(CMSG),CMSG->Messagenumber);
4693 + break;
4694 + case CAPI_DISCONNECT_B3:
4695 + NCCI = DISCONNECT_B3_CONF_NCCI(CMSG);
4696 + PLCI = (NCCI << 16) >> 16;
4697 + if (option_verbose > 3) {
4698 + if (capidebug)
4699 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4700 + }
4701 +// ast_log(LOG_ERROR,"DISCONNECT_B3_CONF NCCI=%#x INFO=%#x MN=%#x\n",NCCI,DISCONNECT_B3_CONF_INFO(CMSG),CMSG->Messagenumber);
4702 + break;
4703 + case CAPI_CONNECT_B3:
4704 + NCCI = CONNECT_B3_CONF_NCCI(CMSG);
4705 + PLCI = (NCCI << 16) >> 16;
4706 + if (option_verbose > 3) {
4707 + if (capidebug)
4708 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4709 + }
4710 +// ast_log(LOG_ERROR,"CONNECT_B3_CONF PLCI=%#x INFO=%#x MN=%#x\n",PLCI,CONNECT_B3_CONF_INFO(CMSG),CMSG->Messagenumber);
4711 + break;
4712 + case CAPI_ALERT:
4713 + PLCI = ALERT_CONF_PLCI(CMSG);
4714 + if (option_verbose > 3) {
4715 + if (capidebug)
4716 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4717 + }
4718 +// ast_log(LOG_ERROR,"ALERT_CONF PLCI=%#x\n",PLCI);
4719 + break;
4720 + case CAPI_DATA_B3:
4721 + NCCI = DATA_B3_CONF_NCCI(CMSG);
4722 + PLCI = (NCCI << 16) >> 16;
4723 + if (option_verbose > 5) {
4724 + if (capidebug)
4725 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4726 + }
4727 +// ast_log(LOG_ERROR,"DATA_B3_CONF NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
4728 + break;
4729 + default:
4730 + ast_log(LOG_ERROR,"Command.Subcommand = %#x.%#x\n",CMSG->Command,CMSG->Subcommand);
4731 + }
4732 + break;
4733 + }
4734 + if (PLCI > 0) {
4735 + pipe_msg(PLCI,CMSG);
4736 + }
4737 +
4738 +}
4739 +
4740 +// module stuff, monitor...
4741 +
4742 +static void *do_monitor(void *data) {
4743 + unsigned int Info;
4744 + _cmsg *monCMSG;
4745 + for (;;) {
4746 +/*
4747 + if (ast_mutex_lock(&monlock)) {
4748 + ast_log(LOG_ERROR,"Unable to get monitor lock!\n");
4749 + return NULL;
4750 + }
4751 + // do some nifty stuff
4752 + ast_mutex_unlock(&monlock);
4753 +*/
4754 + monCMSG = malloc(sizeof(_cmsg));
4755 + memset(monCMSG,0,sizeof(_cmsg));
4756 + switch(Info = check_wait_get_cmsg(monCMSG)) {
4757 + case 0x0000:
4758 + if (option_verbose > 8) {
4759 + if (capidebug)
4760 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(monCMSG));
4761 + }
4762 + capi_handle_msg(monCMSG);
4763 + break;
4764 + case 0x1104:
4765 + // CAPI queue is empty
4766 + break;
4767 + default:
4768 + // something is wrong!
4769 + break;
4770 + } //switch
4771 + free(monCMSG);
4772 + } // for
4773 + // never reached
4774 + return NULL;
4775 +}
4776 +
4777 +#ifdef CAPI_GAIN
4778 +static void capi_gains(struct ast_capi_gains *g,float rxgain,float txgain) {
4779 + int i=0;
4780 + int x=0;
4781 + if (rxgain != 1.0) {
4782 + for (i=0;i<256;i++) {
4783 + x = (int)(((float)capiXLAW2INT(i)) * rxgain);
4784 + if (x > 32767) x = 32767;
4785 + if (x < -32767) x = -32767;
4786 + g->rxgains[i] = capiINT2XLAW(x);
4787 + }
4788 + } else {
4789 + for (i=0;i<256;i++) {
4790 + g->rxgains[i] = i;
4791 + }
4792 + }
4793 + if (txgain != 1.0) {
4794 + for (i=0;i<256;i++) {
4795 + x = (int)(((float)capiXLAW2INT(i)) * txgain);
4796 + if (x > 32767) x = 32767;
4797 + if (x < -32767) x = -32767;
4798 + g->txgains[i] = capiINT2XLAW(x);
4799 + }
4800 + } else {
4801 + for (i=0;i<256;i++) {
4802 + g->txgains[i] = i;
4803 + }
4804 + }
4805 +
4806 +}
4807 +#endif
4808 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
4809 +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) {
4810 +#else
4811 +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) {
4812 +#endif
4813 + struct ast_capi_pvt *tmp;
4814 + int i=0;
4815 + char buffer[100];
4816 + char *contr;
4817 + unsigned long contrmap=0;
4818 +
4819 + for (i=0;i<devices;i++) {
4820 + tmp = malloc(sizeof(struct ast_capi_pvt));
4821 + memset(tmp, 0, sizeof(struct ast_capi_pvt));
4822 + if (tmp) {
4823 + ast_mutex_init(&(tmp->lock));
4824 + strncpy(tmp->context, context, sizeof(tmp->context)-1);
4825 + strncpy(tmp->incomingmsn, incomingmsn, sizeof(tmp->incomingmsn)-1);
4826 + strncpy(tmp->prefix, prefix, sizeof(tmp->prefix)-1);
4827 + strncpy(tmp->accountcode, accountcode, sizeof(tmp->accountcode)-1);
4828 +
4829 + strncpy(buffer,controllerstr,sizeof(buffer)-1);
4830 + contr = strtok(buffer,",");
4831 + while (contr != NULL) {
4832 + contrmap |= (1 << atoi(contr));
4833 + if (capi_controllers[atoi(contr)]) {
4834 + capi_controllers[atoi(contr)]->isdnmode = isdnmode;
4835 + // ast_log(LOG_NOTICE, "contr %d isdnmode %d\n",atoi(contr),isdnmode);
4836 + }
4837 + contr = strtok(NULL,",");
4838 + }
4839 + tmp->controllers = contrmap;
4840 + capi_used_controllers |= contrmap;
4841 + tmp->controller = 0;
4842 + tmp->CLIR = 0;
4843 + tmp->earlyB3 = -1;
4844 + tmp->onholdPLCI = 0;
4845 + tmp->doEC = echocancel;
4846 + tmp->ecOption = ecoption;
4847 + tmp->ecTail = ectail;
4848 + tmp->isdnmode = isdnmode;
4849 + tmp->doES = es;
4850 + tmp->callgroup = callgroup;
4851 + tmp->group = group;
4852 +#ifdef CAPI_ES
4853 +#endif
4854 +#ifdef CAPI_GAIN
4855 + tmp->rxgain = rxgain;
4856 + tmp->txgain = txgain;
4857 + capi_gains(&tmp->g,rxgain,txgain);
4858 +#endif
4859 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
4860 + strncpy(tmp->deflect2, deflect2, sizeof(tmp->deflect2)-1);
4861 +#endif
4862 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
4863 + if (softdtmf == 1) {
4864 +#endif
4865 + tmp->doDTMF = 1;
4866 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
4867 + } else {
4868 + tmp->doDTMF = 0;
4869 + }
4870 +#endif
4871 + tmp->next = iflist; // prepend
4872 + iflist = tmp;
4873 + // 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);
4874 + if (option_verbose > 2) {
4875 + 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);
4876 + }
4877 +
4878 + } else {
4879 + return -1;
4880 + }
4881 + }
4882 + return 0;
4883 +}
4884 +
4885 +void supported_sservices(struct ast_capi_controller *cp) {
4886 + MESSAGE_EXCHANGE_ERROR error;
4887 + _cmsg CMSG,CMSG2;
4888 + struct timeval tv;
4889 + char fac[20];
4890 +
4891 + FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
4892 + FACILITY_REQ_CONTROLLER(&CMSG) = cp->controller;
4893 + FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 0x0003; // sservices
4894 + fac[0] = 3;
4895 + fac[1] = 0;
4896 + fac[2] = 0;
4897 + fac[3] = 0;
4898 + FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = (unsigned char *)&fac;
4899 + if ((error= _capi_put_cmsg(&CMSG)) != 0) {
4900 + ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
4901 + } else {
4902 + if (option_verbose > 5) {
4903 + ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_REQ (CONTROLLER=%#x)\n",cp->controller);
4904 + }
4905 + }
4906 +
4907 + tv.tv_sec = 1;
4908 + tv.tv_usec = 0;
4909 + for (;;){
4910 + error = capi20_waitformessage(ast_capi_ApplID,&tv);
4911 + error = capi_get_cmsg(&CMSG2,ast_capi_ApplID);
4912 +// error = check_wait_get_cmsg(&CMSG2);
4913 + if (error == 0) {
4914 + if (IS_FACILITY_CONF(&CMSG2)) {
4915 + if (option_verbose > 5) {
4916 + ast_verbose(VERBOSE_PREFIX_4 "FACILITY_CONF INFO = %#x\n",FACILITY_CONF_INFO(&CMSG2));
4917 + }
4918 + break;
4919 + }
4920 + }
4921 + }
4922 + // parse supported sservices
4923 + if (FACILITY_CONF_FACILITYSELECTOR(&CMSG2) == 0x0003) {
4924 + // success
4925 + if (FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[4] == 0) {
4926 + if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 1) == 1) {
4927 + cp->holdretrieve = 1;
4928 + if (option_verbose > 3)
4929 + ast_verbose(VERBOSE_PREFIX_4 "HOLD/RETRIEVE\n");
4930 + } else {
4931 + cp->holdretrieve = 0;
4932 + }
4933 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 2) >> 1) == 1) {
4934 + cp->terminalportability = 1;
4935 + if (option_verbose > 3)
4936 + ast_verbose(VERBOSE_PREFIX_4 "TERMINAL PORTABILITY\n");
4937 + } else {
4938 + cp->terminalportability = 0;
4939 + }
4940 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 4) >> 2) == 1) {
4941 + cp->ECT = 1;
4942 + if (option_verbose > 3)
4943 + ast_verbose(VERBOSE_PREFIX_4 "ECT\n");
4944 + } else {
4945 + cp->ECT = 0;
4946 + }
4947 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 8) >> 3) == 1) {
4948 + cp->threePTY = 1;
4949 + if (option_verbose > 3)
4950 + ast_verbose(VERBOSE_PREFIX_4 "3PTY\n");
4951 + } else {
4952 + cp->threePTY = 0;
4953 + }
4954 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 16) >> 4) == 1) {
4955 + cp->CF = 1;
4956 + if (option_verbose > 3)
4957 + ast_verbose(VERBOSE_PREFIX_4 "CF\n");
4958 + } else {
4959 + cp->CF = 0;
4960 + }
4961 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 32) >> 5) == 1) {
4962 + cp->CD = 1;
4963 + if (option_verbose > 3)
4964 + ast_verbose(VERBOSE_PREFIX_4 "CD\n");
4965 + } else {
4966 + cp->CD = 0;
4967 + }
4968 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 64) >> 6) == 1) {
4969 + cp->MCID = 1;
4970 + if (option_verbose > 3)
4971 + ast_verbose(VERBOSE_PREFIX_4 "MCID\n");
4972 + } else {
4973 + cp->MCID = 0;
4974 + }
4975 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 128) >> 7) == 1) {
4976 + cp->CCBS = 1;
4977 + if (option_verbose > 3)
4978 + ast_verbose(VERBOSE_PREFIX_4 "CCBS\n");
4979 + } else {
4980 + cp->CCBS = 0;
4981 + }
4982 + if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[7] & 1) == 1) {
4983 + cp->MWI = 1;
4984 + if (option_verbose > 3)
4985 + ast_verbose(VERBOSE_PREFIX_4 "MWI\n");
4986 + } else {
4987 + cp->MWI = 0;
4988 + }
4989 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[7] & 2) >> 1) == 1) {
4990 + cp->CCNR = 1;
4991 + if (option_verbose > 3)
4992 + ast_verbose(VERBOSE_PREFIX_4 "CCNR\n");
4993 + } else {
4994 + cp->CCNR = 0;
4995 + }
4996 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[7] & 4) >> 2) == 1) {
4997 + cp->CONF = 1;
4998 + if (option_verbose > 3)
4999 + ast_verbose(VERBOSE_PREFIX_4 "CONF\n");
5000 + } else {
5001 + cp->CONF = 0;
5002 + }
5003 + } else {
5004 + ast_log(LOG_NOTICE,"supplementary services info = %#x\n",(short)FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[1]);
5005 + }
5006 + } else {
5007 + ast_log(LOG_NOTICE,"unexpected FACILITY_SELECTOR = %#x\n",FACILITY_CONF_FACILITYSELECTOR(&CMSG2));
5008 + }
5009 +}
5010 +
5011 +static int capi_info(int fd, int argc, char *argv[])
5012 +{
5013 + int i=0;
5014 + if (argc != 2)
5015 + return RESULT_SHOWUSAGE;
5016 + for (i=1;i<=capi_num_controllers;i++) {
5017 + ast_mutex_lock(&contrlock);
5018 + if (capi_controllers[i] != NULL) {
5019 + ast_cli(fd,"Contr%d: %d B channels total, %d B channels free.\n",i,capi_controllers[i]->nbchannels,capi_controllers[i]->nfreebchannels);
5020 + }
5021 + ast_mutex_unlock(&contrlock);
5022 + }
5023 + return RESULT_SUCCESS;
5024 +}
5025 +
5026 +static int capi_do_debug(int fd, int argc, char *argv[])
5027 +{
5028 + if (argc != 2)
5029 + return RESULT_SHOWUSAGE;
5030 + capidebug = 1;
5031 + ast_cli(fd, "CAPI Debugging Enabled\n");
5032 + return RESULT_SUCCESS;
5033 +}
5034 +
5035 +static int capi_no_debug(int fd, int argc, char *argv[])
5036 +{
5037 + if (argc != 3)
5038 + return RESULT_SHOWUSAGE;
5039 + capidebug = 0;
5040 + ast_cli(fd, "CAPI Debugging Disabled\n");
5041 + return RESULT_SUCCESS;
5042 +}
5043 +
5044 +static char info_usage[] =
5045 +"Usage: capi info\n"
5046 +" Show info about B channels.\n";
5047 +
5048 +static char debug_usage[] =
5049 +"Usage: capi debug\n"
5050 +" Enables dumping of CAPI packets for debugging purposes\n";
5051 +
5052 +static char no_debug_usage[] =
5053 +"Usage: capi no debug\n"
5054 +" Disables dumping of CAPI packets for debugging purposes\n";
5055 +
5056 +static struct ast_cli_entry cli_info =
5057 + { { "capi", "info", NULL }, capi_info, "Show CAPI info", info_usage };
5058 +static struct ast_cli_entry cli_debug =
5059 + { { "capi", "debug", NULL }, capi_do_debug, "Enable CAPI debugging", debug_usage };
5060 +static struct ast_cli_entry cli_no_debug =
5061 + { { "capi", "no", "debug", NULL }, capi_no_debug, "Disable CAPI debugging", no_debug_usage };
5062 +
5063 +static const struct ast_channel_tech capi_tech = {
5064 + .type = type,
5065 + .description = tdesc,
5066 +#ifdef CAPI_ULAW
5067 + .capabilities = AST_FORMAT_ULAW,
5068 +#else
5069 + .capabilities = AST_FORMAT_ALAW,
5070 +#endif
5071 + .requester = capi_request,
5072 + .send_digit = capi_send_digit,
5073 + .send_text = NULL,
5074 + .call = capi_call,
5075 + .hangup = capi_hangup,
5076 + .answer = capi_answer,
5077 + .read = capi_read,
5078 + .write = capi_write,
5079 + .bridge = NULL,
5080 + .exception = NULL,
5081 + .indicate = capi_indicate,
5082 + .fixup = capi_fixup,
5083 + .setoption = NULL,
5084 +};
5085 +
5086 +int load_module(void)
5087 +{
5088 + struct ast_config *cfg;
5089 + struct ast_variable *v;
5090 + char *config = "capi.conf";
5091 + char incomingmsn[AST_MAX_EXTENSION]="";
5092 + char context[AST_MAX_EXTENSION]="";
5093 + char prefix[AST_MAX_EXTENSION]="";
5094 + char accountcode[20]="";
5095 + char *empty = "\0";
5096 + char deflect2[AST_MAX_EXTENSION]="";
5097 + char controllerstr[AST_MAX_EXTENSION]="";
5098 + int res = 0;
5099 + int controller=0;
5100 + int softdtmf=0;
5101 + int echocancel=1;
5102 + int ecoption=EC_OPTION_DISABLE_G165;
5103 + int ectail=EC_DEFAULT_TAIL;
5104 + int es=0;
5105 + float rxgain = 1.0;
5106 + float txgain = 1.0;
5107 + int isdnmode = 0;
5108 + unsigned int callgroup=0;
5109 + unsigned int group=0;
5110 + struct ast_capi_controller *cp;
5111 +
5112 + cfg = ast_config_load(config);
5113 +
5114 + /* We *must* have a config file otherwise stop immediately, well no... */
5115 + if (!cfg) {
5116 + ast_log(LOG_ERROR, "Unable to load config %s, CAPI disabled\n", config);
5117 + return 0;
5118 + }
5119 + if (ast_mutex_lock(&iflock)) {
5120 + ast_log(LOG_ERROR, "Unable to lock interface list???\n");
5121 + return -1;
5122 + }
5123 +
5124 + strncpy(capi_national_prefix, AST_CAPI_NATIONAL_PREF, sizeof(capi_national_prefix)-1);
5125 + strncpy(capi_international_prefix, AST_CAPI_NATIONAL_PREF, sizeof(capi_national_prefix)-1);
5126 + v = ast_variable_browse(cfg, "general");
5127 + while(v) {
5128 + if (!strcasecmp(v->name, "nationalprefix")) {
5129 + strncpy(capi_national_prefix, v->value, sizeof(capi_national_prefix)-1);
5130 + } else if (!strcasecmp(v->name, "internationalprefix")) {
5131 + strncpy(capi_international_prefix, v->value, sizeof(capi_international_prefix)-1);
5132 + } else if (!strcasecmp(v->name, "rxgain")) {
5133 + if (sscanf(v->value,"%f",&rxgain) != 1) {
5134 + ast_log(LOG_ERROR,"invalid rxgain\n");
5135 + }
5136 + } else if (!strcasecmp(v->name, "txgain")) {
5137 + if (sscanf(v->value,"%f",&txgain) != 1) {
5138 + ast_log(LOG_ERROR,"invalid txgain\n");
5139 + }
5140 + }
5141 + v = v->next;
5142 + }
5143 +
5144 +
5145 +
5146 +
5147 + if (capi20_isinstalled() != 0) {
5148 + ast_log(LOG_WARNING,"CAPI not installed, CAPI disabled!\n");
5149 + return 0;
5150 + }
5151 +
5152 + if (capi20_register(AST_CAPI_BCHANS,AST_CAPI_MAX_B3_BLOCKS,AST_CAPI_MAX_B3_BLOCK_SIZE,&ast_capi_ApplID) != 0) {
5153 + ast_log(LOG_NOTICE,"unable to register application at CAPI!\n");
5154 + return -1;
5155 + }
5156 +
5157 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5158 + if (capi20_get_profile(0,&profile) != 0) {
5159 +#else
5160 + if (capi20_get_profile(0,(unsigned char *)&profile) != 0) {
5161 +#endif
5162 + ast_log(LOG_NOTICE,"unable to get CAPI profile!\n");
5163 + return -1;
5164 + } else {
5165 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5166 + capi_num_controllers = profile.wCtlr;
5167 +#else
5168 + capi_num_controllers = profile.ncontrollers;
5169 +#endif
5170 + if (option_verbose > 3)
5171 + ast_verbose(VERBOSE_PREFIX_3 "This box has %d capi controller(s).\n",capi_num_controllers);
5172 + for (controller=1;controller<=capi_num_controllers;controller++) {
5173 +
5174 + memset(&profile,0,sizeof(profile));
5175 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5176 + capi20_get_profile(controller,&profile);
5177 +#else
5178 + capi20_get_profile(controller,(unsigned char *)&profile);
5179 +#endif
5180 + cp = malloc(sizeof(struct ast_capi_controller));
5181 + cp->controller = controller;
5182 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5183 + cp->nbchannels = profile.wNumBChannels;
5184 + cp->nfreebchannels = profile.wNumBChannels;
5185 + if (profile.dwGlobalOptions & CAPI_PROFILE_DTMF_SUPPORT) {
5186 +#else
5187 + cp->nbchannels = profile.nbchannels;
5188 + cp->nfreebchannels = profile.nbchannels;
5189 + if ((profile.globaloptions & 8) >> 3 == 1) {
5190 +#endif
5191 + if (option_verbose > 3)
5192 + ast_verbose(VERBOSE_PREFIX_3 "CAPI/contr%d supports DTMF\n",controller);
5193 + cp->dtmf = 1;
5194 + } else {
5195 + cp->dtmf = 0;
5196 + }
5197 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5198 + if (profile.dwGlobalOptions & CAPI_PROFILE_ECHO_CANCELLATION) {
5199 +#else
5200 + if (profile.globaloptions2 & 1) {
5201 +#endif
5202 + if (option_verbose > 3)
5203 + ast_verbose(VERBOSE_PREFIX_3 "CAPI/contr%d supports echo cancellation\n",controller);
5204 + cp->echocancel = 1;
5205 + } else {
5206 + cp->echocancel = 0;
5207 + }
5208 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5209 + if (profile.dwGlobalOptions & CAPI_PROFILE_SUPPLEMENTARY_SERVICES) {
5210 +#else
5211 + if ((profile.globaloptions & 16) >> 4 == 1) {
5212 +#endif
5213 + cp->sservices = 1;
5214 + } else {
5215 + cp->sservices = 0;
5216 + }
5217 + capi_controllers[controller] = cp;
5218 + if (cp->sservices == 1) {
5219 + if (option_verbose > 3)
5220 + ast_verbose(VERBOSE_PREFIX_3 "CAPI/contr%d supports supplementary services\n",controller);
5221 + supported_sservices(cp);
5222 + }
5223 + }
5224 + }
5225 +
5226 + v = ast_variable_browse(cfg, "interfaces");
5227 + while(v) {
5228 + /* Create the interface list */
5229 + if (!strcasecmp(v->name, "devices")) {
5230 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
5231 + if (mkif(incomingmsn,context,controllerstr,atoi(v->value),softdtmf,echocancel,ecoption,ectail, prefix, isdnmode, es,rxgain,txgain,deflect2,accountcode,callgroup, group)) {
5232 +#else
5233 + if (mkif(incomingmsn,context,controllerstr,atoi(v->value),softdtmf,echocancel,ecoption,ectail, prefix, isdnmode, es,rxgain,txgain,accountcode,callgroup, group)) {
5234 +#endif
5235 + ast_log(LOG_ERROR,"Error creating interface list\n");
5236 + return -1;
5237 + }
5238 + es=0;
5239 + strncpy(deflect2, empty, sizeof(deflect2)-1);
5240 + } else if (!strcasecmp(v->name, "context")) {
5241 + strncpy(context, v->value, sizeof(context)-1);
5242 + } else if (!strcasecmp(v->name, "incomingmsn")) {
5243 + strncpy(incomingmsn, v->value, sizeof(incomingmsn)-1);
5244 + } else if (!strcasecmp(v->name, "controller")) {
5245 + strncpy(controllerstr, v->value, sizeof(controllerstr)-1);
5246 + } else if (!strcasecmp(v->name, "softdtmf")) {
5247 + softdtmf = atoi(v->value);
5248 + } else if (!strcasecmp(v->name, "echosquelch")) {
5249 + es = atoi(v->value);
5250 + } else if (!strcasecmp(v->name, "callgroup")) {
5251 + callgroup = ast_get_group(v->value);
5252 + } else if (!strcasecmp(v->name, "group")) {
5253 + group = ast_get_group(v->value);
5254 + } else if (!strcasecmp(v->name, "deflect")) {
5255 + strncpy(deflect2, v->value, sizeof(deflect2)-1);
5256 + } else if (!strcasecmp(v->name, "rxgain")) {
5257 + if (sscanf(v->value,"%f",&rxgain) != 1) {
5258 + ast_log(LOG_ERROR,"invalid rxgain\n");
5259 + }
5260 + } else if (!strcasecmp(v->name, "txgain")) {
5261 + if (sscanf(v->value,"%f",&txgain) != 1) {
5262 + ast_log(LOG_ERROR,"invalid txgain\n");
5263 + }
5264 + } else if (!strcasecmp(v->name, "echocancel")) {
5265 + if (!strcasecmp(v->value, "yes") || !strcasecmp(v->value, "1") || !strcasecmp(v->value, "on")) {
5266 + echocancel=1;
5267 + ecoption=EC_OPTION_DISABLE_G165;
5268 + }
5269 + else if (!strcasecmp(v->value, "no") || !strcasecmp(v->value, "0") || !strcasecmp(v->value, "off")) {
5270 + echocancel=0;
5271 + ecoption=0;
5272 + }
5273 + else if (!strcasecmp(v->value, "g165") || !strcasecmp(v->value, "g.165")) {
5274 + echocancel=1;
5275 + ecoption=EC_OPTION_DISABLE_G165;
5276 + }
5277 + else if (!strcasecmp(v->value, "g164") || !strcasecmp(v->value, "g.164")) {
5278 + echocancel=1;
5279 + ecoption=EC_OPTION_DISABLE_G164_OR_G165;
5280 + }
5281 + else if (!strcasecmp(v->value, "force")) {
5282 + echocancel=1;
5283 + ecoption=EC_OPTION_DISABLE_NEVER;
5284 + }
5285 + else {
5286 + ast_log(LOG_ERROR,"Unknown echocancel parameter \"%s\" -- ignoring\n",v->value);
5287 + }
5288 + } else if (!strcasecmp(v->name, "echotail")) {
5289 + ectail = atoi(v->value);
5290 + if (ectail > 255)
5291 + ectail = 255;
5292 + } else if (!strcasecmp(v->name, "prefix")) {
5293 + strncpy(prefix, v->value, sizeof(prefix)-1);
5294 + } else if (!strcasecmp(v->name, "accountcode")) {
5295 + strncpy(accountcode, v->value, sizeof(accountcode)-1);
5296 + } else if (!strcasecmp(v->name, "isdnmode")) {
5297 + if (!strcasecmp(v->value, "ptp") || !strcasecmp(v->value, "1"))
5298 + isdnmode = 1;
5299 + else if (!strcasecmp(v->value, "ptm") || !strcasecmp(v->value, "0") || !strcasecmp(v->value, "ptmp"))
5300 + isdnmode = 0;
5301 + else
5302 + ast_log(LOG_ERROR,"Unknown isdnmode parameter \"%s\" -- ignoring\n",v->value);
5303 +
5304 + }
5305 +
5306 + v = v->next;
5307 + }
5308 + ast_config_destroy(cfg);
5309 +
5310 + for (controller=1;controller<=capi_num_controllers;controller++) {
5311 + if (capi_used_controllers & (1 << controller)) {
5312 + if (ListenOnController(ALL_SERVICES,controller) != 0) {
5313 + ast_log(LOG_ERROR,"Unable to listen on contr%d\n",controller);
5314 + } else {
5315 + if (option_verbose > 2)
5316 + ast_verbose(VERBOSE_PREFIX_3 "listening on contr%d CIPmask = %#x\n",controller,ALL_SERVICES);
5317 + }
5318 + } else {
5319 + ast_log(LOG_WARNING,"Unused contr%d\n",controller);
5320 + }
5321 + }
5322 +
5323 +
5324 + ast_mutex_unlock(&iflock);
5325 +
5326 + if (ast_channel_register(&capi_tech)) {
5327 + ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
5328 + unload_module();
5329 + return -1;
5330 + }
5331 +
5332 + ast_cli_register(&cli_info);
5333 + ast_cli_register(&cli_debug);
5334 + ast_cli_register(&cli_no_debug);
5335 +
5336 + if (ast_mutex_lock(&monlock)) {
5337 + ast_log(LOG_WARNING,"Unable to get monitor lock!\n");
5338 + return -1;
5339 + }
5340 + if (monitor_thread == pthread_self()) {
5341 + ast_mutex_unlock(&monlock);
5342 + ast_log(LOG_WARNING,"Unable to kill myself!\n");
5343 + return -1;
5344 + }
5345 +
5346 + if (ast_pthread_create(&monitor_thread,NULL,do_monitor,NULL) < 0) {
5347 + ast_mutex_unlock(&monlock);
5348 + ast_log(LOG_ERROR,"Unable to start monitor thread!\n");
5349 + return -1;
5350 + }
5351 +
5352 + return res;
5353 +}
5354 +
5355 +
5356 +int unload_module()
5357 +{
5358 + if (capi20_release(ast_capi_ApplID) != 0)
5359 + ast_log(LOG_WARNING,"Unable to unregister from CAPI!\n");
5360 + ast_channel_unregister(&capi_tech);
5361 + return 0;
5362 +}
5363 +
5364 +int usecount()
5365 +{
5366 + int res;
5367 + ast_mutex_lock(&usecnt_lock);
5368 + res = usecnt;
5369 + ast_mutex_unlock(&usecnt_lock);
5370 + return res;
5371 +}
5372 +
5373 +char *description()
5374 +{
5375 + return desc;
5376 +}
5377 +
5378 +
5379 +char *key()
5380 +{
5381 + return ASTERISK_GPL_KEY;
5382 +}
5383 diff -urN asterisk-1.2.7.1.orig/channels/chan_features.c asterisk-1.2.7.1/channels/chan_features.c
5384 --- asterisk-1.2.7.1.orig/channels/chan_features.c 2006-01-25 19:39:44.000000000 +0100
5385 +++ asterisk-1.2.7.1/channels/chan_features.c 2006-04-18 14:39:28.000000000 +0200
5386 @@ -438,7 +438,7 @@
5387 }
5388 ast_mutex_unlock(&featurelock);
5389 if (!tmp) {
5390 - chan = ast_request(tech, format, dest, &status);
5391 + chan = ast_request(tech, format, dest, &status, NULL);
5392 if (!chan) {
5393 ast_log(LOG_NOTICE, "Unable to allocate subchannel '%s/%s'\n", tech, dest);
5394 return NULL;
5395 diff -urN asterisk-1.2.7.1.orig/channels/chan_iax2.c asterisk-1.2.7.1/channels/chan_iax2.c
5396 --- asterisk-1.2.7.1.orig/channels/chan_iax2.c 2006-03-31 21:11:26.000000000 +0200
5397 +++ asterisk-1.2.7.1/channels/chan_iax2.c 2006-04-18 14:39:28.000000000 +0200
5398 @@ -11,6 +11,9 @@
5399 * the project provides a web site, mailing lists and IRC
5400 * channels for your use.
5401 *
5402 + * Hangup cause signalling implementation by
5403 + * Levent Guendogdu <levon@feature-it.com>
5404 + *
5405 * This program is free software, distributed under the terms of
5406 * the GNU General Public License Version 2. See the LICENSE file
5407 * at the top of the source tree.
5408 @@ -3065,7 +3068,7 @@
5409 memset(&ied, 0, sizeof(ied));
5410 ast_mutex_lock(&iaxsl[callno]);
5411 if (callno && iaxs[callno]) {
5412 - ast_log(LOG_DEBUG, "We're hanging up %s now...\n", c->name);
5413 + ast_log(LOG_DEBUG, "We're hanging up %s with cause %i now...\n", c->name, c->hangupcause);
5414 alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
5415 /* Send the hangup unless we have had a transmission error or are already gone */
5416 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
5417 @@ -3117,7 +3120,8 @@
5418 static struct ast_frame *iax2_read(struct ast_channel *c)
5419 {
5420 static struct ast_frame f = { AST_FRAME_NULL, };
5421 - ast_log(LOG_NOTICE, "I should never be called!\n");
5422 + if (option_verbose > 3)
5423 + ast_log(LOG_NOTICE, "I should never be called!\n");
5424 return &f;
5425 }
5426
5427 @@ -6702,7 +6706,7 @@
5428 }
5429 if (f.frametype == AST_FRAME_IAX) {
5430 if (iaxs[fr.callno]->initid > -1) {
5431 - /* Don't auto congest anymore since we've gotten something usefulb ack */
5432 + /* Don't auto congest anymore since we've gotten something useful back */
5433 ast_sched_del(sched, iaxs[fr.callno]->initid);
5434 iaxs[fr.callno]->initid = -1;
5435 }
5436 diff -urN asterisk-1.2.7.1.orig/channels/chan_sip.c asterisk-1.2.7.1/channels/chan_sip.c
5437 --- asterisk-1.2.7.1.orig/channels/chan_sip.c 2006-04-07 16:16:41.000000000 +0200
5438 +++ asterisk-1.2.7.1/channels/chan_sip.c 2006-04-25 13:23:13.000000000 +0200
5439 @@ -596,6 +596,7 @@
5440 unsigned int flags; /*!< SIP_ flags */
5441 int timer_t1; /*!< SIP timer T1, ms rtt */
5442 unsigned int sipoptions; /*!< Supported SIP sipoptions on the other end */
5443 + int dialog_established; /*!< SIP dialog established */
5444 int capability; /*!< Special capability (codec) */
5445 int jointcapability; /*!< Supported capability at both ends (codecs ) */
5446 int peercapability; /*!< Supported peer capability */
5447 @@ -619,6 +620,7 @@
5448 char refer_to[AST_MAX_EXTENSION]; /*!< Place to store REFER-TO extension */
5449 char referred_by[AST_MAX_EXTENSION]; /*!< Place to store REFERRED-BY extension */
5450 char refer_contact[AST_MAX_EXTENSION]; /*!< Place to store Contact info from a REFER extension */
5451 + char refer_replaces[AST_MAX_EXTENSION]; /*!< Place to store Replaces header of REFER-TO header */
5452 struct sip_pvt *refer_call; /*!< Call we are referring */
5453 struct sip_route *route; /*!< Head of linked list of routing steps (fm Record-Route) */
5454 int route_persistant; /*!< Is this the "real" route? */
5455 @@ -638,6 +640,7 @@
5456 char peername[256]; /*!< [peer] name, not set if [user] */
5457 char authname[256]; /*!< Who we use for authentication */
5458 char uri[256]; /*!< Original requested URI */
5459 + char origuri[256]; /*!< REAL! Original requested URI */
5460 char okcontacturi[256]; /*!< URI from the 200 OK on INVITE */
5461 char peersecret[256]; /*!< Password */
5462 char peermd5secret[256];
5463 @@ -921,7 +924,7 @@
5464 static int determine_firstline_parts(struct sip_request *req);
5465 static void sip_dump_history(struct sip_pvt *dialog); /* Dump history to LOG_DEBUG at end of dialog, before destroying data */
5466 static const struct cfsubscription_types *find_subscription_type(enum subscriptiontype subtype);
5467 -static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate);
5468 +static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate, char *cid_num, char *cid_name);
5469 static char *gettag(struct sip_request *req, char *header, char *tagbuf, int tagbufsize);
5470
5471 /*! \brief Definition of this channel for PBX channel registration */
5472 @@ -1304,7 +1307,7 @@
5473 /* If this is a subscription, tell the phone that we got a timeout */
5474 if (p->subscribed) {
5475 p->subscribed = TIMEOUT;
5476 - transmit_state_notify(p, AST_EXTENSION_DEACTIVATED, 1, 1); /* Send first notification */
5477 + transmit_state_notify(p, AST_EXTENSION_DEACTIVATED, 1, 1, NULL, NULL); /* Send first notification */
5478 p->subscribed = NONE;
5479 append_history(p, "Subscribestatus", "timeout");
5480 return 10000; /* Reschedule this destruction so that we know that it's gone */
5481 @@ -3124,16 +3127,30 @@
5482
5483 /*! \brief find_call: Connect incoming SIP message to current dialog or create new dialog structure */
5484 /* Called by handle_request, sipsock_read */
5485 -static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *sin, const int intended_method)
5486 +static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *sin, const int intended_method, const int replaces_callid)
5487 {
5488 struct sip_pvt *p;
5489 char *callid;
5490 char *tag = "";
5491 + char *replaces;
5492 char totag[128];
5493 char fromtag[128];
5494 + char *c;
5495
5496 callid = get_header(req, "Call-ID");
5497
5498 + if (replaces_callid) {
5499 + replaces = get_header(req, "Replaces");
5500 + c = strchr(replaces, ';');
5501 + if (c)
5502 + *c = '\0';
5503 + if (!ast_strlen_zero(replaces)) {
5504 + callid = replaces;
5505 + } else {
5506 + return NULL;
5507 + }
5508 + }
5509 +
5510 if (pedanticsipchecking) {
5511 /* In principle Call-ID's uniquely identify a call, but with a forking SIP proxy
5512 we need more to identify a branch - so we have to check branch, from
5513 @@ -4058,6 +4075,7 @@
5514 if (sipmethod == SIP_CANCEL) {
5515 c = p->initreq.rlPart2; /* Use original URI */
5516 } else if (sipmethod == SIP_ACK) {
5517 +// XXX+ } else if (!strcasecmp(msg, "ACK") && !p->dialog_established) {
5518 /* Use URI from Contact: in 200 OK (if INVITE)
5519 (we only have the contacturi on INVITEs) */
5520 if (!ast_strlen_zero(p->okcontacturi))
5521 @@ -4824,13 +4842,15 @@
5522 ast_build_string(&invite, &invite_max, ";%s", p->options->uri_options);
5523
5524 ast_copy_string(p->uri, invite_buf, sizeof(p->uri));
5525 + ast_copy_string(p->origuri, invite, sizeof(p->origuri));
5526
5527 if (sipmethod == SIP_NOTIFY && !ast_strlen_zero(p->theirtag)) {
5528 /* If this is a NOTIFY, use the From: tag in the subscribe (RFC 3265) */
5529 snprintf(to, sizeof(to), "<sip:%s>;tag=%s", p->uri, p->theirtag);
5530 } else if (p->options && p->options->vxml_url) {
5531 /* If there is a VXML URL append it to the SIP URL */
5532 - snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url);
5533 +// snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url);
5534 + snprintf(to, sizeof(to), "<%s;%s>", p->uri, p->options->vxml_url);
5535 } else {
5536 snprintf(to, sizeof(to), "<%s>", p->uri);
5537 }
5538 @@ -4887,6 +4907,11 @@
5539 if (!ast_strlen_zero(p->referred_by))
5540 add_header(&req, "Referred-By", p->referred_by);
5541 }
5542 + if (sipmethod == SIP_INVITE) {
5543 + if (!ast_strlen_zero(p->refer_replaces)) {
5544 + add_header(&req, "Replaces", p->refer_replaces);
5545 + }
5546 + }
5547 #ifdef OSP_SUPPORT
5548 if ((req.method != SIP_OPTIONS) && p->options && !ast_strlen_zero(p->options->osptoken)) {
5549 ast_log(LOG_DEBUG,"Adding OSP Token: %s\n", p->options->osptoken);
5550 @@ -4961,8 +4986,7 @@
5551 }
5552
5553 /*! \brief transmit_state_notify: Used in the SUBSCRIBE notification subsystem ----*/
5554 -static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate)
5555 -{
5556 +static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate, char *cid_num, char *cid_name) {
5557 char tmp[4000], from[256], to[256];
5558 char *t = tmp, *c, *a, *mfrom, *mto;
5559 size_t maxbytes = sizeof(tmp);
5560 @@ -5106,10 +5130,19 @@
5561 case DIALOG_INFO_XML: /* SNOM subscribes in this format */
5562 ast_build_string(&t, &maxbytes, "<?xml version=\"1.0\"?>\n");
5563 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);
5564 - if ((state & AST_EXTENSION_RINGING) && global_notifyringing)
5565 - ast_build_string(&t, &maxbytes, "<dialog id=\"%s\" direction=\"recipient\">\n", p->exten);
5566 - else
5567 + if ((state & AST_EXTENSION_RINGING) && global_notifyringing) {
5568 + ast_build_string(&t, &maxbytes, "<dialog id=\"%s\" direction=\"recipient\">\n", p->exten);
5569 + if (cid_num) {
5570 + ast_build_string(&t, &maxbytes, "<local><identity display=\"%s\">%s</identity><target uri=\"%s\"/></local>\n", p->exten, p->exten, mfrom);
5571 + if (cid_name && !ast_strlen_zero(cid_name)) {
5572 + 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);
5573 + } else {
5574 + 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);
5575 + }
5576 + }
5577 + } else {
5578 ast_build_string(&t, &maxbytes, "<dialog id=\"%s\">\n", p->exten);
5579 + }
5580 ast_build_string(&t, &maxbytes, "<state>%s</state>\n", statestring);
5581 ast_build_string(&t, &maxbytes, "</dialog>\n</dialog-info>\n");
5582 break;
5583 @@ -6321,7 +6354,7 @@
5584 /*! \brief cb_extensionstate: Callback for the devicestate notification (SUBSCRIBE) support subsystem ---*/
5585 /* If you add an "hint" priority to the extension in the dial plan,
5586 you will get notifications on device state changes */
5587 -static int cb_extensionstate(char *context, char* exten, int state, void *data)
5588 +static int cb_extensionstate(char *context, char* exten, int state, void *data, char *cid_num, char *cid_name)
5589 {
5590 struct sip_pvt *p = data;
5591
5592 @@ -6340,7 +6373,7 @@
5593 p->laststate = state;
5594 break;
5595 }
5596 - transmit_state_notify(p, state, 1, 1);
5597 + transmit_state_notify(p, state, 1, 1, cid_num, cid_name);
5598
5599 if (option_debug > 1)
5600 ast_verbose(VERBOSE_PREFIX_1 "Extension Changed %s new state %s for Notify User %s\n", exten, ast_extension_state2str(state), p->username);
5601 @@ -8607,6 +8640,7 @@
5602 char buf[1024];
5603 unsigned int event;
5604 char *c;
5605 + struct ast_call_feature *feature;
5606
5607 /* Need to check the media/type */
5608 if (!strcasecmp(get_header(req, "Content-Type"), "application/dtmf-relay") ||
5609 @@ -8670,6 +8704,19 @@
5610 ast_queue_control(p->owner, AST_CONTROL_VIDUPDATE);
5611 transmit_response(p, "200 OK", req);
5612 return;
5613 + } else if ((c = get_header(req, "Record"))) {
5614 + feature = ast_find_builtin_feature("automon");
5615 + if (feature && (!ast_strlen_zero(feature->exten))) {
5616 + int i = 0;
5617 +// ast_log(LOG_NOTICE, "feature exten %s\n", feature->exten);
5618 + for (i=0; i<strlen(feature->exten); i++) {
5619 + struct ast_frame f = { AST_FRAME_DTMF, feature->exten[i] };
5620 + ast_queue_frame(p->owner, &f);
5621 + }
5622 + } else {
5623 + ast_log(LOG_NOTICE, "Feature \"One Touch Monitor\" not configured in features.conf.\n");
5624 + }
5625 + return;
5626 } else if ((c = get_header(req, "X-ClientCode"))) {
5627 /* Client code (from SNOM phone) */
5628 if (ast_test_flag(p, SIP_USECLIENTCODE)) {
5629 @@ -8769,12 +8816,63 @@
5630 return RESULT_SUCCESS;
5631 }
5632
5633 +
5634 +/*! \brief sip_notify: Send SIP notify to peer */
5635 +static int sip_send_notify(int fd, char *notify_type, char *peer)
5636 +{
5637 + struct ast_variable *varlist;
5638 + struct sip_pvt *p;
5639 + struct sip_request req;
5640 + struct ast_variable *var;
5641 +
5642 + varlist = ast_variable_browse(notify_types, notify_type);
5643 +
5644 + if (!varlist) {
5645 + if (fd > 0)
5646 + ast_cli(fd, "Unable to find notify type '%s'\n", notify_type);
5647 + return RESULT_FAILURE;
5648 + }
5649 +
5650 + p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY);
5651 + if (!p) {
5652 + ast_log(LOG_WARNING, "Unable to build sip pvt data for notify\n");
5653 + return RESULT_FAILURE;
5654 + }
5655 +
5656 + if (create_addr(p, peer)) {
5657 + /* Maybe they're not registered, etc. */
5658 + sip_destroy(p);
5659 + if (fd > 0)
5660 + ast_cli(fd, "Could not create address for '%s'\n", peer);
5661 + return RESULT_FAILURE;
5662 + }
5663 +
5664 + initreqprep(&req, p, SIP_NOTIFY);
5665 +
5666 + for (var = varlist; var; var = var->next)
5667 + add_header(&req, var->name, var->value);
5668 +
5669 + add_blank_header(&req);
5670 + /* Recalculate our side, and recalculate Call ID */
5671 + if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
5672 + memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
5673 + build_via(p, p->via, sizeof(p->via));
5674 + build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
5675 + if (fd > 0)
5676 + ast_cli(fd, "Sending NOTIFY of type '%s' to '%s'\n", notify_type, peer);
5677 + transmit_sip_request(p, &req);
5678 + sip_scheddestroy(p, 15000);
5679 +
5680 + return RESULT_SUCCESS;
5681 +}
5682 +
5683 /*! \brief sip_notify: Send SIP notify to peer */
5684 static int sip_notify(int fd, int argc, char *argv[])
5685 {
5686 struct ast_variable *varlist;
5687 int i;
5688 -
5689 + int res = RESULT_SUCCESS;
5690 +
5691 if (argc < 4)
5692 return RESULT_SHOWUSAGE;
5693
5694 @@ -8791,41 +8889,13 @@
5695 }
5696
5697 for (i = 3; i < argc; i++) {
5698 - struct sip_pvt *p;
5699 - struct sip_request req;
5700 - struct ast_variable *var;
5701 -
5702 - p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY);
5703 - if (!p) {
5704 - ast_log(LOG_WARNING, "Unable to build sip pvt data for notify\n");
5705 - return RESULT_FAILURE;
5706 - }
5707 -
5708 - if (create_addr(p, argv[i])) {
5709 - /* Maybe they're not registered, etc. */
5710 - sip_destroy(p);
5711 - ast_cli(fd, "Could not create address for '%s'\n", argv[i]);
5712 - continue;
5713 - }
5714 -
5715 - initreqprep(&req, p, SIP_NOTIFY);
5716 -
5717 - for (var = varlist; var; var = var->next)
5718 - add_header(&req, var->name, var->value);
5719 + if (sip_send_notify(fd, argv[2], argv[i]) == RESULT_FAILURE)
5720 + res = RESULT_FAILURE;
5721 + }
5722 + return res;
5723 +}
5724
5725 - add_blank_header(&req);
5726 - /* Recalculate our side, and recalculate Call ID */
5727 - if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
5728 - memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
5729 - build_via(p, p->via, sizeof(p->via));
5730 - build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
5731 - ast_cli(fd, "Sending NOTIFY of type '%s' to '%s'\n", argv[2], argv[i]);
5732 - transmit_sip_request(p, &req);
5733 - sip_scheddestroy(p, 15000);
5734 - }
5735
5736 - return RESULT_SUCCESS;
5737 -}
5738 /*! \brief sip_do_history: Enable SIP History logging (CLI) ---*/
5739 static int sip_do_history(int fd, int argc, char *argv[])
5740 {
5741 @@ -9468,12 +9538,13 @@
5742 case 100: /* Trying */
5743 sip_cancel_destroy(p);
5744 break;
5745 + case 183:
5746 case 180: /* 180 Ringing */
5747 sip_cancel_destroy(p);
5748 if (!ignore && p->owner) {
5749 ast_queue_control(p->owner, AST_CONTROL_RINGING);
5750 if (p->owner->_state != AST_STATE_UP)
5751 - ast_setstate(p->owner, AST_STATE_RINGING);
5752 + ast_setstate_and_cid(p->owner, AST_STATE_RINGING, p->owner->cid.cid_num, p->owner->cid.cid_name);
5753 }
5754 if (!strcasecmp(get_header(req, "Content-Type"), "application/sdp")) {
5755 process_sdp(p, req);
5756 @@ -9483,17 +9554,17 @@
5757 }
5758 }
5759 break;
5760 - case 183: /* Session progress */
5761 +/* case 183: // Session progress
5762 sip_cancel_destroy(p);
5763 - /* Ignore 183 Session progress without SDP */
5764 + // Ignore 183 Session progress without SDP
5765 if (!strcasecmp(get_header(req, "Content-Type"), "application/sdp")) {
5766 process_sdp(p, req);
5767 if (!ignore && p->owner) {
5768 - /* Queue a progress frame */
5769 + // Queue a progress frame
5770 ast_queue_control(p->owner, AST_CONTROL_PROGRESS);
5771 }
5772 }
5773 - break;
5774 + break; */
5775 case 200: /* 200 OK on invite - someone's answering our call */
5776 sip_cancel_destroy(p);
5777 p->authtries = 0;
5778 @@ -10287,6 +10358,7 @@
5779 /* This is a call to ourself. Send ourselves an error code and stop
5780 processing immediately, as SIP really has no good mechanism for
5781 being able to call yourself */
5782 +ast_log(LOG_NOTICE, "to: %s uri: %s\n", get_header(req, "To"), p->origuri);
5783 transmit_response(p, "482 Loop Detected", req);
5784 /* We do NOT destroy p here, so that our response will be accepted */
5785 return 0;
5786 @@ -10836,7 +10908,7 @@
5787 struct sip_pvt *p_old;
5788
5789 transmit_response(p, "200 OK", req);
5790 - transmit_state_notify(p, firststate, 1, 1); /* Send first notification */
5791 + transmit_state_notify(p, firststate, 1, 1, NULL, NULL); /* Send first notification */
5792 append_history(p, "Subscribestatus", ast_extension_state2str(firststate));
5793
5794 /* remove any old subscription from this peer for the same exten/context,
5795 @@ -11148,7 +11220,7 @@
5796 /* Process request, with netlock held */
5797 retrylock:
5798 ast_mutex_lock(&netlock);
5799 - p = find_call(&req, &sin, req.method);
5800 + p = find_call(&req, &sin, req.method, 0);
5801 if (p) {
5802 /* Go ahead and lock the owner if it has one -- we may need it */
5803 if (p->owner && ast_mutex_trylock(&p->owner->lock)) {
5804 @@ -11468,6 +11540,52 @@
5805 return 0;
5806 }
5807
5808 +static char mandescr_sip_notify[] =
5809 +"Description: Send a NOTIFY message to one or more SIP peers.\n"
5810 +"Variables: \n"
5811 +" Peer: <name> The peer name you want to send a NOTIFY to.\n"
5812 +" Type: <name> The notify type (see sip_notify.conf).\n"
5813 +" ActionID: <id> Optional action ID for this AMI transaction.\n";
5814 +
5815 +/*! \brief manager_sip_notify: Send a notify (see sip_notify.conf) to a peer ---*/
5816 +static int manager_sip_notify(struct mansession *s, struct message *m)
5817 +{
5818 + char *id = astman_get_header(m,"ActionID");
5819 + char *peer;
5820 + char *notify_type;
5821 + int res = 0;
5822 +
5823 + peer = astman_get_header(m,"Peer");
5824 + if (ast_strlen_zero(peer)) {
5825 + astman_send_error(s, m, "Peer: <name> missing.\n");
5826 + return 0;
5827 + }
5828 + notify_type = astman_get_header(m,"Type");
5829 + if (ast_strlen_zero(notify_type)) {
5830 + astman_send_error(s, m, "Type: <name> missing.\n");
5831 + return 0;
5832 + }
5833 +
5834 + res = sip_send_notify(-1, notify_type, peer);
5835 + if (res != RESULT_SUCCESS) {
5836 + ast_cli(s->fd, "Response: SIPNotify Failure\r\n"
5837 + "Peer: %s\r\n"
5838 + "Type: %s\r\n"
5839 + "ActionID: %s\r\n"
5840 + "\r\n",
5841 + peer, notify_type, id);
5842 + } else {
5843 + ast_cli(s->fd, "Response: SIPNotify Success\r\n"
5844 + "Peer: %s\r\n"
5845 + "Type: %s\r\n"
5846 + "ActionID: %s\r\n"
5847 + "\r\n",
5848 + peer, notify_type, id);
5849 + }
5850 + return res;
5851 +}
5852 +
5853 +
5854 /*! \brief sip_devicestate: Part of PBX channel interface ---*/
5855
5856 /* Return values:---
5857 @@ -13167,6 +13285,8 @@
5858 "List SIP peers (text format)", mandescr_show_peers);
5859 ast_manager_register2("SIPshowpeer", EVENT_FLAG_SYSTEM, manager_sip_show_peer,
5860 "Show SIP peer (text format)", mandescr_show_peer);
5861 + ast_manager_register2("SIPNotify", EVENT_FLAG_SYSTEM, manager_sip_notify,
5862 + "Send NOTIFY to peer", mandescr_sip_notify);
5863
5864 sip_poke_all_peers();
5865 sip_send_all_registers();
5866 @@ -13197,6 +13317,7 @@
5867
5868 ast_rtp_proto_unregister(&sip_rtp);
5869
5870 + ast_manager_unregister("SIPNotify");
5871 ast_manager_unregister("SIPpeers");
5872 ast_manager_unregister("SIPshowpeer");
5873
5874 diff -urN asterisk-1.2.7.1.orig/channels/chan_zap.c asterisk-1.2.7.1/channels/chan_zap.c
5875 --- asterisk-1.2.7.1.orig/channels/chan_zap.c 2006-04-04 20:28:14.000000000 +0200
5876 +++ asterisk-1.2.7.1/channels/chan_zap.c 2006-04-25 14:21:48.000000000 +0200
5877 @@ -11,6 +11,10 @@
5878 * the project provides a web site, mailing lists and IRC
5879 * channels for your use.
5880 *
5881 + * Copyright (C) 2003-2006 Junghanns.NET GmbH
5882 + * Klaus-Peter Junghanns <kpj@junghanns.net>
5883 + *
5884 + *
5885 * This program is free software, distributed under the terms of
5886 * the GNU General Public License Version 2. See the LICENSE file
5887 * at the top of the source tree.
5888 @@ -65,6 +69,9 @@
5889 #ifdef ZAPATA_R2
5890 #include <libmfcr2.h>
5891 #endif
5892 +#ifdef ZAPATA_GSM
5893 +#include <libgsmat.h>
5894 +#endif
5895
5896 #include "asterisk.h"
5897
5898 @@ -96,6 +103,7 @@
5899 #include "asterisk/term.h"
5900 #include "asterisk/utils.h"
5901 #include "asterisk/transcap.h"
5902 +#include "asterisk/devicestate.h"
5903
5904 #ifndef ZT_SIG_EM_E1
5905 #error "Your zaptel is too old. please cvs update"
5906 @@ -173,6 +181,7 @@
5907 #define SIG_FXOGS ZT_SIG_FXOGS
5908 #define SIG_FXOKS ZT_SIG_FXOKS
5909 #define SIG_PRI ZT_SIG_CLEAR
5910 +#define SIG_GSM (0x100000 | ZT_SIG_CLEAR)
5911 #define SIG_R2 ZT_SIG_CAS
5912 #define SIG_SF ZT_SIG_SF
5913 #define SIG_SFWINK (0x0100000 | ZT_SIG_SF)
5914 @@ -183,7 +192,7 @@
5915 #define SIG_GR303FXOKS (0x0100000 | ZT_SIG_FXOKS)
5916 #define SIG_GR303FXSKS (0x0100000 | ZT_SIG_FXSKS)
5917
5918 -#define NUM_SPANS 32
5919 +#define NUM_SPANS 128 /*!<"32 spans", muahahaha, us alaws like to have some more... */
5920 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
5921 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
5922
5923 @@ -201,6 +210,11 @@
5924 static char defaultcic[64] = "";
5925 static char defaultozz[64] = "";
5926
5927 +static char nocid[256] = "No CID available";
5928 +static char withheldcid[256] = "CID withheld";
5929 +static char gsm_modem_pin[20];
5930 +static char gsm_modem_exten[AST_MAX_EXTENSION];
5931 +
5932 static char language[MAX_LANGUAGE] = "";
5933 static char musicclass[MAX_MUSICCLASS] = "";
5934 static char progzone[10]= "";
5935 @@ -287,6 +301,7 @@
5936 static int cur_priexclusive = 0;
5937
5938 static int priindication_oob = 0;
5939 +static int pritransfer = 0;
5940
5941 #ifdef ZAPATA_PRI
5942 static int minunused = 2;
5943 @@ -294,6 +309,7 @@
5944 static char idleext[AST_MAX_EXTENSION];
5945 static char idledial[AST_MAX_EXTENSION];
5946 static int overlapdial = 0;
5947 +static int usercid = 0;
5948 static int facilityenable = 0;
5949 static char internationalprefix[10] = "";
5950 static char nationalprefix[10] = "";
5951 @@ -305,8 +321,6 @@
5952 #ifdef PRI_GETSET_TIMERS
5953 static int pritimers[PRI_MAX_TIMERS];
5954 #endif
5955 -static int pridebugfd = -1;
5956 -static char pridebugfilename[1024]="";
5957 #endif
5958
5959 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
5960 @@ -327,10 +341,6 @@
5961
5962 static int ifcount = 0;
5963
5964 -#ifdef ZAPATA_PRI
5965 -AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
5966 -#endif
5967 -
5968 /*! \brief Whether we answer on a Polarity Switch event */
5969 static int answeronpolarityswitch = 0;
5970
5971 @@ -389,6 +399,18 @@
5972
5973 struct zt_pvt;
5974
5975 +#ifdef ZAPATA_GSM
5976 +struct zt_gsm {
5977 + pthread_t master;
5978 + ast_mutex_t lock; /* Mutex */
5979 + int fd;
5980 + int span;
5981 + struct gsm_modul *modul;
5982 + char pin[256];
5983 + char exten[AST_MAX_EXTENSION]; /* Where to idle extra calls */
5984 + struct zt_pvt *pvt;
5985 +};
5986 +#endif
5987
5988 #ifdef ZAPATA_R2
5989 static int r2prot = -1;
5990 @@ -403,6 +425,28 @@
5991 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
5992 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
5993
5994 +struct zt_suspended_call {
5995 + ast_mutex_t lock; /* Mutex */
5996 + char msn[AST_MAX_EXTENSION]; /* the MSN to which this parked call belongs */
5997 + char callid[10]; /* the callID provided by the user */
5998 + int parked_at; /* extension in the call parking context */
5999 + struct zt_suspended_call *next;
6000 +};
6001 +
6002 +struct zt_holded_call {
6003 + ast_mutex_t lock; /* Mutex */
6004 + char msn[AST_MAX_EXTENSION]; /* the MSN to which this parked call belongs */
6005 + char uniqueid[AST_MAX_EXTENSION]; /* unique id of the onhold channel */
6006 + int tei;
6007 + int cref;
6008 + int alreadyhungup;
6009 + struct ast_channel *channel;
6010 + struct ast_channel *bridge;
6011 + q931_call *call; /* this also covers tei mumbojumbo */
6012 + struct zt_holded_call *next;
6013 +};
6014 +
6015 +
6016 struct zt_pri {
6017 pthread_t master; /*!< Thread of master */
6018 ast_mutex_t lock; /*!< Mutex */
6019 @@ -416,6 +460,8 @@
6020 int nsf; /*!< Network-Specific Facilities */
6021 int dialplan; /*!< Dialing plan */
6022 int localdialplan; /*!< Local dialing plan */
6023 + char nocid[256];
6024 + char withheldcid[256];
6025 char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
6026 char nationalprefix[10]; /*!< area access code ('0' for european dialplans) */
6027 char localprefix[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
6028 @@ -435,6 +481,7 @@
6029 int fds[NUM_DCHANS]; /*!< FD's for d-channels */
6030 int offset;
6031 int span;
6032 + int usercid; /* trust user provided callerid (callerani) ?? */
6033 int resetting;
6034 int resetpos;
6035 time_t lastreset; /*!< time when unused channels were last reset */
6036 @@ -442,6 +489,9 @@
6037 struct zt_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
6038 struct zt_pvt *crvs; /*!< Member CRV structs */
6039 struct zt_pvt *crvend; /*!< Pointer to end of CRV structs */
6040 + struct zt_suspended_call *suspended_calls; /* Calls parked with SUSPEND messages */
6041 + struct zt_holded_call *holded_calls; /* Calls on hold */
6042 + int debugfd;
6043 };
6044
6045
6046 @@ -561,6 +611,8 @@
6047 unsigned int echocanbridged:1;
6048 unsigned int echocanon:1;
6049 unsigned int faxhandled:1; /*!< Has a fax tone already been handled? */
6050 + /*!< KPJ: i will abuse this flag to implement a zapata option for dialing out
6051 + on a zap channel with EC to be off no matter what happens. */
6052 unsigned int firstradio:1;
6053 unsigned int hanguponpolarityswitch:1;
6054 unsigned int hardwaredtmf:1;
6055 @@ -573,7 +625,8 @@
6056 unsigned int overlapdial:1;
6057 unsigned int permcallwaiting:1;
6058 unsigned int permhidecallerid:1; /*!< Whether to hide our outgoing caller ID or not */
6059 - unsigned int priindication_oob:1;
6060 + unsigned int priindication_oob:2;
6061 + unsigned int pritransfer:2;
6062 unsigned int priexclusive:1;
6063 unsigned int pulse:1;
6064 unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */
6065 @@ -612,6 +665,7 @@
6066 #endif
6067 char cid_num[AST_MAX_EXTENSION];
6068 int cid_ton; /*!< Type Of Number (TON) */
6069 + int cid_pres; /*!< Calling Presentation */
6070 char cid_name[AST_MAX_EXTENSION];
6071 char lastcid_num[AST_MAX_EXTENSION];
6072 char lastcid_name[AST_MAX_EXTENSION];
6073 @@ -672,10 +726,15 @@
6074 int polarityonanswerdelay;
6075 struct timeval polaritydelaytv;
6076 int sendcalleridafter;
6077 +#ifdef ZAPATA_GSM
6078 + struct zt_gsm gsm;
6079 +#endif
6080 #ifdef ZAPATA_PRI
6081 struct zt_pri *pri;
6082 struct zt_pvt *bearer;
6083 struct zt_pvt *realcall;
6084 + int tei; /* channel in use by this tei */
6085 + q931_call *holdedcall;
6086 q931_call *call;
6087 int prioffset;
6088 int logicalspan;
6089 @@ -701,11 +760,14 @@
6090 static int zt_indicate(struct ast_channel *chan, int condition);
6091 static int zt_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
6092 static int zt_setoption(struct ast_channel *chan, int option, void *data, int datalen);
6093 +static int zt_devicestate(void *data);
6094 +static void disable_dtmf_detect(struct zt_pvt *p);
6095 +static void enable_dtmf_detect(struct zt_pvt *p);
6096
6097 static const struct ast_channel_tech zap_tech = {
6098 .type = type,
6099 .description = tdesc,
6100 - .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW,
6101 + .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
6102 .requester = zt_request,
6103 .send_digit = zt_digit,
6104 .send_text = zt_sendtext,
6105 @@ -719,6 +781,7 @@
6106 .indicate = zt_indicate,
6107 .fixup = zt_fixup,
6108 .setoption = zt_setoption,
6109 + .devicestate = zt_devicestate
6110 };
6111
6112 #ifdef ZAPATA_PRI
6113 @@ -730,6 +793,13 @@
6114 struct zt_pvt *round_robin[32];
6115
6116 #ifdef ZAPATA_PRI
6117 +struct app_tmp {
6118 + char app[256];
6119 + char data[256];
6120 + struct ast_channel *chan;
6121 + pthread_t t;
6122 +};
6123 +
6124 static inline int pri_grab(struct zt_pvt *pvt, struct zt_pri *pri)
6125 {
6126 int res;
6127 @@ -779,6 +849,112 @@
6128 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
6129 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
6130
6131 +static int zt_devicestate(void *data)
6132 +{
6133 + int groupmatch = 0;
6134 + int channelmatch = 0;
6135 + struct zt_pvt *p;
6136 + char *dest=NULL;
6137 + int x,d;
6138 + char *s;
6139 + char opt=0;
6140 + int res, y=0;
6141 + struct zt_pvt *exit, *start, *end;
6142 + ast_mutex_t *lock;
6143 +
6144 +// ast_log(LOG_NOTICE, "data = %s\n", (char *)data);
6145 + return AST_DEVICE_UNKNOWN;
6146 +
6147 + /* Assume we're locking the iflock */
6148 + lock = &iflock;
6149 + start = iflist;
6150 + end = ifend;
6151 +
6152 + if (data) {
6153 + dest = ast_strdupa((char *)data);
6154 + } else {
6155 + ast_log(LOG_WARNING, "Channel requested with no data\n");
6156 + return AST_DEVICE_INVALID;
6157 + }
6158 + if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
6159 + /* Retrieve the group number */
6160 + char *stringp=NULL;
6161 + stringp=dest + 1;
6162 + s = strsep(&stringp, "/");
6163 + if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
6164 + ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
6165 + return AST_DEVICE_INVALID;
6166 + }
6167 + groupmatch = 1 << x;
6168 + } else {
6169 + char *stringp=NULL;
6170 + stringp=dest;
6171 + s = strsep(&stringp, "/");
6172 + p = iflist;
6173 + if (!strcasecmp(s, "pseudo")) {
6174 + /* Special case for pseudo */
6175 + x = CHAN_PSEUDO;
6176 + channelmatch = x;
6177 + /* bail out */
6178 + return AST_DEVICE_INVALID;
6179 + }
6180 +
6181 + else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
6182 + ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
6183 + return AST_DEVICE_INVALID;
6184 + } else {
6185 + channelmatch = x;
6186 + ast_log(LOG_NOTICE, "channelmatch = %d\n", channelmatch);
6187 + }
6188 + }
6189 + /* Search for an unowned channel */
6190 + if (ast_mutex_lock(lock)) {
6191 + ast_log(LOG_ERROR, "Unable to lock interface list???\n");
6192 + return AST_DEVICE_INVALID;
6193 + }
6194 + p = iflist;
6195 + exit = iflist;
6196 + res = AST_DEVICE_INVALID; /* start pessimistic */
6197 + while(p) {
6198 + if (p) {
6199 + ast_mutex_lock(&p->lock);
6200 + if ((groupmatch && ((p->group & groupmatch) != 0)) || (channelmatch && (p->channel == channelmatch))) {
6201 +#ifdef ZAPATA_PRI
6202 + if (p->pri) {
6203 + for(d=0;d<NUM_DCHANS;d++) {
6204 + if (p->pri->dchanavail[d] & DCHAN_UP) {
6205 + res = AST_DEVICE_UNKNOWN;
6206 + }
6207 + }
6208 + }
6209 +#endif
6210 + 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))))) {
6211 + res = AST_DEVICE_UNKNOWN;
6212 + if (p->owner) {
6213 + if ((p->owner->_state == AST_STATE_RINGING) && (p->outgoing)) {
6214 + res = AST_DEVICE_RINGING;
6215 + }
6216 + 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)){
6217 + res = AST_DEVICE_INUSE;
6218 + }
6219 + }
6220 + if ((res == AST_DEVICE_INUSE) || (res == AST_DEVICE_RINGING)) {
6221 + /* stop searching now, one non-idle channel is sufficient */
6222 + ast_mutex_unlock(&p->lock);
6223 + break;
6224 + }
6225 + }
6226 + }
6227 + ast_mutex_unlock(&p->lock);
6228 + }
6229 + p = p->next;
6230 + }
6231 + ast_mutex_unlock(lock);
6232 +
6233 + return res;
6234 +
6235 +}
6236 +
6237 static int zt_get_index(struct ast_channel *ast, struct zt_pvt *p, int nullok)
6238 {
6239 int res;
6240 @@ -1181,6 +1357,8 @@
6241 return "GR-303 Signalling with FXOKS";
6242 case SIG_GR303FXSKS:
6243 return "GR-303 Signalling with FXSKS";
6244 + case SIG_GSM:
6245 + return "GSM Signalling";
6246 case 0:
6247 return "Pseudo Signalling";
6248 default:
6249 @@ -1381,12 +1559,16 @@
6250 int res;
6251 if (!p)
6252 return;
6253 + if (p->faxhandled) {
6254 + ast_log(LOG_DEBUG, "Not enabling echo cancellation on a fax/modem call\n");
6255 + return;
6256 + }
6257 if (p->echocanon) {
6258 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
6259 return;
6260 }
6261 if (p->digital) {
6262 - ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
6263 + ast_log(LOG_DEBUG, "Echo cancellation does not make any sense on digital connections!\n");
6264 return;
6265 }
6266 if (p->echocancel) {
6267 @@ -1412,7 +1594,7 @@
6268 {
6269 int x;
6270 int res;
6271 - if (p && p->echocancel && p->echotraining) {
6272 + if (p && p->echocancel && p->echotraining && (!p->digital) && (!p->faxhandled)) {
6273 x = p->echotraining;
6274 res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOTRAIN, &x);
6275 if (res)
6276 @@ -1592,7 +1774,7 @@
6277 {
6278 int x, y, res;
6279 x = muted;
6280 - if (p->sig == SIG_PRI) {
6281 + if ((p->sig == SIG_PRI) || (p->sig == SIG_GSM)) {
6282 y = 1;
6283 res = ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &y);
6284 if (res)
6285 @@ -1774,7 +1956,12 @@
6286 ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", p->channel);
6287 p->outgoing = 1;
6288
6289 - set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
6290 + if (IS_DIGITAL(ast->transfercapability)) {
6291 + set_actual_gain(p->subs[SUB_REAL].zfd, 0, 0, 0, p->law);
6292 + } else {
6293 + set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
6294 + }
6295 +
6296
6297 switch(p->sig) {
6298 case SIG_FXOLS:
6299 @@ -1998,6 +2185,26 @@
6300 case SIG_PRI:
6301 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
6302 p->dialdest[0] = '\0';
6303 + disable_dtmf_detect(p);
6304 + break;
6305 + case SIG_GSM:
6306 +#ifdef ZAPATA_GSM
6307 + if (p->gsm.modul) {
6308 + c = strchr(dest, '/');
6309 + if (c)
6310 + c++;
6311 + else
6312 + c = dest;
6313 + ast_mutex_lock(&p->gsm.lock);
6314 + if (gsm_dial(p->gsm.modul, 0, c)) {
6315 + ast_log(LOG_WARNING, "dialing failed on channel %d\n", p->channel);
6316 + ast_mutex_unlock(&p->gsm.lock);
6317 + ast_mutex_unlock(&p->lock);
6318 + return -1;
6319 + }
6320 + ast_mutex_unlock(&p->gsm.lock);
6321 + }
6322 +#endif
6323 break;
6324 default:
6325 ast_log(LOG_DEBUG, "not yet implemented\n");
6326 @@ -2016,6 +2223,12 @@
6327 int ldp_strip;
6328 int exclusive;
6329
6330 + if ((p->pri->nodetype == BRI_NETWORK_PTMP) || (p->pri->nodetype == BRI_NETWORK)) {
6331 + // pass NO audio when ringing an isdn phone
6332 + p->dialing = 1;
6333 + // maybe we could allow passing audio when calling a p2p PBX, but well... ;-)
6334 + }
6335 +
6336 c = strchr(dest, '/');
6337 if (c)
6338 c++;
6339 @@ -2033,6 +2246,7 @@
6340 ast_mutex_unlock(&p->lock);
6341 return -1;
6342 }
6343 + strncpy(p->dnid, (c + p->stripmsd), sizeof(p->dnid)-1);
6344 if (p->sig != SIG_FXSKS) {
6345 p->dop.op = ZT_DIAL_OP_REPLACE;
6346 s = strchr(c + p->stripmsd, 'w');
6347 @@ -2056,6 +2270,8 @@
6348 pri_rel(p->pri);
6349 ast_mutex_unlock(&p->lock);
6350 return -1;
6351 + } else {
6352 + // ast_log(LOG_NOTICE, "call %d\n", p->call);
6353 }
6354 if (!(sr = pri_sr_new())) {
6355 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
6356 @@ -2085,7 +2301,7 @@
6357 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
6358 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
6359 (p->digital ? -1 :
6360 - ((p->law == ZT_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
6361 + ((p->law == ZT_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)), ast->lowlayercompat);
6362 if (p->pri->facilityenable)
6363 pri_facility_enable(p->pri->pri);
6364
6365 @@ -2287,8 +2503,10 @@
6366 }
6367 if (newslot < 0) {
6368 newslot = 0;
6369 - ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
6370 + if (pri->nodetype != BRI_CPE_PTMP) {
6371 + ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
6372 pri->dchannels[newslot]);
6373 + }
6374 }
6375 if (old && (oldslot != newslot))
6376 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
6377 @@ -2344,8 +2562,7 @@
6378
6379 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
6380 p->channel, index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
6381 - p->ignoredtmf = 0;
6382 -
6383 +
6384 if (index > -1) {
6385 /* Real channel, do some fixup */
6386 p->subs[index].owner = NULL;
6387 @@ -2442,6 +2659,7 @@
6388
6389
6390 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
6391 + int outgoing = p->outgoing;
6392 p->owner = NULL;
6393 p->ringt = 0;
6394 p->distinctivering = 0;
6395 @@ -2478,19 +2696,61 @@
6396 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
6397 if (!pri_grab(p, p->pri)) {
6398 if (p->alreadyhungup) {
6399 +/* char *aoc = pbx_builtin_getvar_helper(ast,"AOCEUNITS");
6400 + int iaoc = aoc ? atoi(aoc) : -1;
6401 + char *aocpm = pbx_builtin_getvar_helper(ast,"AOCEUNITSPERMIN");
6402 + int iaocpm = aocpm ? atoi(aocpm) : -1;
6403 +
6404 + if (iaocpm > -1) {
6405 + if (ast->cdr) {
6406 + long bill_sec = ast->cdr->billsec;
6407 + long bill_min = 0;
6408 + if (bill_sec > 0) {
6409 + bill_min = bill_sec / 60;
6410 + if (bill_min < 1) bill_min = 1;
6411 + }
6412 + iaoc = bill_min * iaocpm;
6413 + } else {
6414 + ast_log(LOG_NOTICE, "no cdr \n");
6415 + }
6416 + } else {
6417 + ast_log(LOG_NOTICE, "iaocpm %d \n", iaocpm);
6418 + }
6419 +*/
6420 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
6421
6422 #ifdef SUPPORT_USERUSER
6423 pri_call_set_useruser(p->call, useruser);
6424 #endif
6425
6426 - pri_hangup(p->pri->pri, p->call, -1);
6427 + pri_hangup(p->pri->pri, p->call, -1, -1);
6428 p->call = NULL;
6429 if (p->bearer)
6430 p->bearer->call = NULL;
6431 } else {
6432 char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
6433 int icause = ast->hangupcause ? ast->hangupcause : -1;
6434 +/* char *aoc = pbx_builtin_getvar_helper(ast,"AOCEUNITS");
6435 + int iaoc = aoc ? atoi(aoc) : -1;
6436 + char *aocpm = pbx_builtin_getvar_helper(ast,"AOCEUNITSPERMIN");
6437 + int iaocpm = aocpm ? atoi(aocpm) : -1;
6438 +
6439 + if (iaocpm > -1) {
6440 + if (ast->cdr) {
6441 + long bill_sec = ast->cdr->billsec;
6442 + long bill_min = 0;
6443 + if (bill_sec > 0) {
6444 + bill_min = bill_sec / 60;
6445 + if (bill_min < 1) bill_min = 1;
6446 + }
6447 + iaoc = bill_min * iaocpm;
6448 + } else {
6449 + ast_log(LOG_NOTICE, "no cdr \n");
6450 + }
6451 + } else {
6452 + ast_log(LOG_NOTICE, "iaocpm %d \n", iaocpm);
6453 + }
6454 +*/
6455 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
6456
6457 #ifdef SUPPORT_USERUSER
6458 @@ -2504,7 +2764,28 @@
6459 if (atoi(cause))
6460 icause = atoi(cause);
6461 }
6462 - pri_hangup(p->pri->pri, p->call, icause);
6463 +
6464 + pri_hangup(p->pri->pri, p->call, icause, -1);
6465 +
6466 + /* if we send a release complete we wont ge no hangup event, so clear the call here */
6467 + if (icause == 34 || icause == 44 || icause == 82 || icause == 1 || icause == 81 || icause == 17) {
6468 + if ((ast->_state == AST_STATE_RING) || (ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING)) {
6469 + p->call = NULL;
6470 + } else {
6471 + ast_log(LOG_ERROR, "What is wrong with you? You cannot use cause %d number when in state %d!\n", icause, ast->_state);
6472 + icause = 16; /* Note, in pri_hangup() libpri will already override the cause */
6473 + }
6474 + }
6475 +
6476 + if (p->pri->nodetype == BRI_NETWORK_PTMP) {
6477 + if ((icause == 16 || icause == -1) && (ast->_state != AST_STATE_UP)) {
6478 + if (outgoing) {
6479 + p->call = NULL;
6480 + }
6481 + }
6482 + }
6483 +
6484 +
6485 }
6486 if (res < 0)
6487 ast_log(LOG_WARNING, "pri_disconnect failed\n");
6488 @@ -2532,7 +2813,13 @@
6489
6490 }
6491 #endif
6492 - if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_R2))
6493 +#ifdef ZAPATA_GSM
6494 + if (p->gsm.modul) {
6495 + if (!p->alreadyhungup)
6496 + gsm_hangup(p->gsm.modul);
6497 + }
6498 +#endif
6499 + if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_R2) && (p->sig != SIG_GSM))
6500 res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_ONHOOK);
6501 if (res < 0) {
6502 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
6503 @@ -2701,10 +2988,14 @@
6504 p->proceeding = 1;
6505 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
6506 pri_rel(p->pri);
6507 + /* stop ignoring inband dtmf */
6508 + enable_dtmf_detect(p);
6509 } else {
6510 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
6511 res= -1;
6512 }
6513 + /* the audio path is complete now, train the echo canceler */
6514 + zt_train_ec(p);
6515 break;
6516 #endif
6517 #ifdef ZAPATA_R2
6518 @@ -2714,6 +3005,13 @@
6519 ast_log(LOG_WARNING, "R2 Answer call failed :( on %s\n", ast->name);
6520 break;
6521 #endif
6522 +#ifdef ZAPATA_GSM
6523 + case SIG_GSM:
6524 + if (p->gsm.modul) {
6525 + gsm_answer(p->gsm.modul);
6526 + }
6527 + break;
6528 +#endif
6529 case 0:
6530 ast_mutex_unlock(&p->lock);
6531 return 0;
6532 @@ -3274,6 +3572,15 @@
6533 {
6534 struct zt_pvt *p = newchan->tech_pvt;
6535 int x;
6536 + if (newchan && newchan->tech_pvt) {
6537 + p = newchan->tech_pvt;
6538 + }
6539 + if (!p) {
6540 + if (newchan) {
6541 + ast_log(LOG_ERROR, "channel %s has no tech_pvt structure\n", newchan->name);
6542 + }
6543 + return 0;
6544 + }
6545 ast_mutex_lock(&p->lock);
6546 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
6547 if (p->owner == oldchan) {
6548 @@ -3637,7 +3944,7 @@
6549 if (p->call) {
6550 if (p->pri && p->pri->pri) {
6551 if (!pri_grab(p, p->pri)) {
6552 - pri_hangup(p->pri->pri, p->call, -1);
6553 + pri_hangup(p->pri->pri, p->call, -1, -1);
6554 pri_destroycall(p->pri->pri, p->call);
6555 p->call = NULL;
6556 pri_rel(p->pri);
6557 @@ -4600,7 +4907,7 @@
6558 p->subs[index].f.data = NULL;
6559 p->subs[index].f.datalen= 0;
6560 }
6561 - if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
6562 + if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
6563 /* Perform busy detection. etc on the zap line */
6564 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
6565 if (f) {
6566 @@ -4612,8 +4919,9 @@
6567 }
6568 } else if (f->frametype == AST_FRAME_DTMF) {
6569 #ifdef ZAPATA_PRI
6570 - if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
6571 - /* Don't accept in-band DTMF when in overlap dial mode */
6572 + if (p->sig==SIG_PRI && p->pri && p->pri->overlapdial && p->ignoredtmf) {
6573 + /* Don't accept in-band DTMF when in overlap dial mode
6574 + or when in non-overlap overlapdialing mode ... */
6575 f->frametype = AST_FRAME_NULL;
6576 f->subclass = 0;
6577 }
6578 @@ -4661,8 +4969,10 @@
6579 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
6580 if (ast_async_goto(ast, target_context, "fax", 1))
6581 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
6582 - } else
6583 - ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
6584 + } else {
6585 + if (option_verbose > 2)
6586 + ast_verbose(VERBOSE_PREFIX_3 "Fax detected, but no fax extension\n");
6587 + }
6588 } else
6589 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
6590 } else
6591 @@ -4748,7 +5058,9 @@
6592 #endif
6593 /* Write a frame of (presumably voice) data */
6594 if (frame->frametype != AST_FRAME_VOICE) {
6595 - if (frame->frametype != AST_FRAME_IMAGE)
6596 + if (frame->frametype == AST_FRAME_TEXT) {
6597 + ast_log(LOG_NOTICE, "text\n");
6598 + } else if (frame->frametype != AST_FRAME_IMAGE)
6599 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
6600 return 0;
6601 }
6602 @@ -4819,7 +5131,7 @@
6603 switch(condition) {
6604 case AST_CONTROL_BUSY:
6605 #ifdef ZAPATA_PRI
6606 - if (p->priindication_oob && p->sig == SIG_PRI) {
6607 + if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
6608 chan->hangupcause = AST_CAUSE_USER_BUSY;
6609 chan->_softhangup |= AST_SOFTHANGUP_DEV;
6610 res = 0;
6611 @@ -4901,7 +5213,7 @@
6612 case AST_CONTROL_CONGESTION:
6613 chan->hangupcause = AST_CAUSE_CONGESTION;
6614 #ifdef ZAPATA_PRI
6615 - if (p->priindication_oob && p->sig == SIG_PRI) {
6616 + if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
6617 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
6618 chan->_softhangup |= AST_SOFTHANGUP_DEV;
6619 res = 0;
6620 @@ -5086,8 +5398,12 @@
6621 if (state == AST_STATE_RING)
6622 tmp->rings = 1;
6623 tmp->tech_pvt = i;
6624 - if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
6625 - /* Only FXO signalled stuff can be picked up */
6626 +#ifdef ZAPATA_PRI
6627 + if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS) || (i->sig == SIG_PRI)) {
6628 +#else
6629 + if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
6630 +#endif
6631 + /* Only FXO signalled stuff can be picked up */ /* i dont think so, mr. ulaw! we alaws like to pick up BRIs/PRIs */
6632 tmp->callgroup = i->callgroup;
6633 tmp->pickupgroup = i->pickupgroup;
6634 }
6635 @@ -5217,6 +5533,7 @@
6636 int len = 0;
6637 int res;
6638 int index;
6639 + int network;
6640 if (option_verbose > 2)
6641 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
6642 index = zt_get_index(chan, p, 1);
6643 @@ -5235,10 +5552,17 @@
6644 len = strlen(exten);
6645 res = 0;
6646 while((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
6647 - if (len && !ast_ignore_pattern(chan->context, exten))
6648 + if (len && !ast_ignore_pattern(chan->context, exten)) {
6649 tone_zone_play_tone(p->subs[index].zfd, -1);
6650 - else
6651 - tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
6652 + } else {
6653 + network = p->pri->nodetype == PRI_NETWORK || p->pri->nodetype == BRI_NETWORK || p->pri->nodetype == BRI_NETWORK_PTMP;
6654 + if (network) {
6655 + tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
6656 + } else {
6657 + /* cpe be quiet */
6658 + tone_zone_play_tone(p->subs[index].zfd, -1);
6659 + }
6660 + }
6661 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
6662 timeout = matchdigittimeout;
6663 else
6664 @@ -6719,6 +7043,8 @@
6665 } else {
6666 if (si->totalchans == 31) { /* if it's an E1 */
6667 pris[*span].dchannels[0] = 16 + offset;
6668 + } else if (si->totalchans == 3) { /* if it's an S0 ZAPBRI */
6669 + pris[*span].dchannels[0] = 3 + offset;
6670 } else {
6671 pris[*span].dchannels[0] = 24 + offset;
6672 }
6673 @@ -6806,6 +7132,10 @@
6674
6675 #endif
6676
6677 +#ifdef ZAPATA_GSM
6678 +static void *gsm_dchannel(void *vgsm);
6679 +#endif
6680 +
6681 static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_pri *pri, int reloading)
6682 {
6683 /* Make a zt_pvt structure for this interface (or CRV if "pri" is specified) */
6684 @@ -6964,6 +7294,11 @@
6685 destroy_zt_pvt(&tmp);
6686 return NULL;
6687 }
6688 + if ((pris[span].localdialplan) && (pris[span].localdialplan != localdialplan)) {
6689 + ast_log(LOG_ERROR, "Span %d is already a %s local dialing plan\n", span + 1, dialplan2str(pris[span].localdialplan));
6690 + destroy_zt_pvt(&tmp);
6691 + return NULL;
6692 + }
6693 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, idledial)) {
6694 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, idledial);
6695 destroy_zt_pvt(&tmp);
6696 @@ -6991,6 +7326,17 @@
6697 return NULL;
6698 }
6699 pris[span].nodetype = pritype;
6700 +// XXX
6701 + if (pritype == BRI_NETWORK_PTMP) {
6702 + pris[span].dchanavail[0] = DCHAN_AVAILABLE;
6703 + pri_find_dchan(&pris[span]);
6704 + }
6705 +// XXX tuev
6706 +
6707 + if ((pritype == BRI_CPE) || (pritype == BRI_CPE_PTMP)) {
6708 + pris[span].dchanavail[0] = DCHAN_AVAILABLE;
6709 + pri_find_dchan(&pris[span]);
6710 + }
6711 pris[span].switchtype = myswitchtype;
6712 pris[span].nsf = nsf;
6713 pris[span].dialplan = dialplan;
6714 @@ -6999,9 +7345,14 @@
6715 pris[span].minunused = minunused;
6716 pris[span].minidle = minidle;
6717 pris[span].overlapdial = overlapdial;
6718 + pris[span].usercid = usercid;
6719 + pris[span].suspended_calls = NULL;
6720 + pris[span].holded_calls = NULL;
6721 pris[span].facilityenable = facilityenable;
6722 ast_copy_string(pris[span].idledial, idledial, sizeof(pris[span].idledial));
6723 ast_copy_string(pris[span].idleext, idleext, sizeof(pris[span].idleext));
6724 + ast_copy_string(pris[span].nocid, nocid, sizeof(pris[span].nocid) - 1);
6725 + ast_copy_string(pris[span].withheldcid, withheldcid, sizeof(pris[span].withheldcid) - 1);
6726 ast_copy_string(pris[span].internationalprefix, internationalprefix, sizeof(pris[span].internationalprefix));
6727 ast_copy_string(pris[span].nationalprefix, nationalprefix, sizeof(pris[span].nationalprefix));
6728 ast_copy_string(pris[span].localprefix, localprefix, sizeof(pris[span].localprefix));
6729 @@ -7022,6 +7373,36 @@
6730 tmp->prioffset = 0;
6731 }
6732 #endif
6733 +#ifdef ZAPATA_GSM
6734 + if (signalling == SIG_GSM) {
6735 + struct zt_bufferinfo bi;
6736 + ast_mutex_init(&tmp->gsm.lock);
6737 + strncpy(tmp->gsm.pin, gsm_modem_pin, sizeof(tmp->gsm.pin) - 1);
6738 + strncpy(tmp->gsm.exten, gsm_modem_exten, sizeof(tmp->gsm.exten) - 1);
6739 + snprintf(fn, sizeof(fn), "%d", channel + 1);
6740 + /* Open non-blocking */
6741 + tmp->gsm.fd = zt_open(fn);
6742 + bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
6743 + bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
6744 + bi.numbufs = 16;
6745 + bi.bufsize = 1024;
6746 + if (ioctl(tmp->gsm.fd, ZT_SET_BUFINFO, &bi)) {
6747 + ast_log(LOG_ERROR, "Unable to set buffer info on channel '%s': %s\n", fn, strerror(errno));
6748 + return NULL;
6749 + }
6750 + tmp->gsm.pvt = tmp;
6751 + tmp->gsm.span = tmp->span;
6752 + tmp->gsm.modul = gsm_new(tmp->gsm.fd, 0, tmp->gsm.pin, tmp->span);
6753 + if (ioctl(tmp->subs[SUB_REAL].zfd, ZT_AUDIOMODE, tmp->channel)) {
6754 + ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d: %s\n", tmp->channel, strerror(errno));
6755 + destroy_zt_pvt(&tmp);
6756 + return NULL;
6757 + }
6758 + if (ast_pthread_create(&tmp->gsm.master, NULL, gsm_dchannel, &tmp->gsm)) {
6759 + zt_close(tmp->gsm.fd);
6760 + }
6761 + }
6762 +#endif
6763 #ifdef ZAPATA_R2
6764 if (signalling == SIG_R2) {
6765 if (r2prot < 0) {
6766 @@ -7155,6 +7536,7 @@
6767 tmp->restrictcid = restrictcid;
6768 tmp->use_callingpres = use_callingpres;
6769 tmp->priindication_oob = priindication_oob;
6770 + tmp->pritransfer = pritransfer;
6771 tmp->priexclusive = cur_priexclusive;
6772 if (tmp->usedistinctiveringdetection) {
6773 if (!tmp->use_callerid) {
6774 @@ -7428,7 +7810,7 @@
6775 break;
6776 if (!backwards && (x >= pri->numchans))
6777 break;
6778 - if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
6779 + if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner && !pri->pvts[x]->call) {
6780 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
6781 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
6782 return x;
6783 @@ -7475,7 +7857,7 @@
6784 end = ifend;
6785 /* We do signed linear */
6786 oldformat = format;
6787 - format &= (AST_FORMAT_SLINEAR | AST_FORMAT_ULAW);
6788 + format &= (AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW);
6789 if (!format) {
6790 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
6791 return NULL;
6792 @@ -7635,6 +8017,11 @@
6793 p->digital = 1;
6794 if (tmp)
6795 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
6796 + } else if (opt == 'm') {
6797 + /* If this is a modem/fax call, pretend to have the fax handled and dont do EC */
6798 + p->faxhandled = 1;
6799 + if (tmp)
6800 + tmp->transfercapability = AST_TRANS_CAP_3_1K_AUDIO;
6801 } else {
6802 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
6803 }
6804 @@ -7674,6 +8061,164 @@
6805 return tmp;
6806 }
6807
6808 +#ifdef ZAPATA_GSM
6809 +static void handle_gsm_event(struct zt_gsm *gsm, gsm_event *e)
6810 +{
6811 + struct ast_channel *c = NULL;
6812 + int law = ZT_LAW_ALAW;
6813 + int res = 0;
6814 +
6815 + switch(e->e) {
6816 + case GSM_EVENT_DCHAN_UP:
6817 + if (option_verbose > 2)
6818 + ast_verbose(VERBOSE_PREFIX_3 "GSM Span %d registered to network!\n", gsm->span);
6819 + break;
6820 + case GSM_EVENT_DCHAN_DOWN:
6821 + if (option_verbose > 2)
6822 + ast_verbose(VERBOSE_PREFIX_3 "GSM Span %d unregistered from network!\n", gsm->span);
6823 + break;
6824 + case GSM_EVENT_RING:
6825 + ast_mutex_lock(&gsm->pvt->lock);
6826 + if (!ast_strlen_zero(e->ring.callingnum)) {
6827 + strncpy(gsm->pvt->cid_num, e->ring.callingnum, sizeof(gsm->pvt->cid_num) - 1);
6828 + }
6829 + if (!ast_strlen_zero(gsm->exten)) {
6830 + strncpy(gsm->pvt->exten, gsm->exten, sizeof(gsm->pvt->exten) - 1);
6831 + } else {
6832 + gsm->pvt->exten[0] = 's';
6833 + gsm->pvt->exten[1] = '\0';
6834 + }
6835 + c = zt_new(gsm->pvt, AST_STATE_RING, 1, SUB_REAL, ZT_LAW_ALAW, AST_TRANS_CAP_SPEECH);
6836 + if (c) {
6837 + if (option_verbose > 2)
6838 + ast_verbose(VERBOSE_PREFIX_3 "Ring on channel %d (from %s to %s)\n", e->ring.channel, e->ring.callingnum, gsm->exten);
6839 + gsm->pvt->owner = c;
6840 + if (ioctl(gsm->pvt->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
6841 + ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", gsm->pvt->channel, law);
6842 + res = zt_setlaw(gsm->pvt->subs[SUB_REAL].zfd, law);
6843 + res = set_actual_gain(gsm->pvt->subs[SUB_REAL].zfd, 0, gsm->pvt->rxgain, gsm->pvt->txgain, law);
6844 + if (res < 0) {
6845 + ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", gsm->pvt->channel);
6846 +// } else {
6847 +// 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);
6848 + }
6849 + }
6850 + ast_mutex_unlock(&gsm->pvt->lock);
6851 + break;
6852 + case GSM_EVENT_HANGUP:
6853 + ast_verbose(VERBOSE_PREFIX_3 "Got hang up on channel %d\n", e->hangup.channel);
6854 + ast_mutex_lock(&gsm->pvt->lock);
6855 + gsm->pvt->alreadyhungup = 1;
6856 + if (gsm->pvt->owner) {
6857 + gsm->pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
6858 + }
6859 + ast_mutex_unlock(&gsm->pvt->lock);
6860 + break;
6861 + case GSM_EVENT_ALERTING:
6862 + ast_mutex_lock(&gsm->pvt->lock);
6863 + gsm->pvt->subs[SUB_REAL].needringing =1;
6864 + ast_mutex_unlock(&gsm->pvt->lock);
6865 + break;
6866 + case GSM_EVENT_ANSWER:
6867 + ast_mutex_lock(&gsm->pvt->lock);
6868 + gsm->pvt->dialing = 0;
6869 + gsm->pvt->subs[SUB_REAL].needanswer =1;
6870 + gsm->pvt->ignoredtmf = 0;
6871 + ast_mutex_unlock(&gsm->pvt->lock);
6872 + break;
6873 + case GSM_EVENT_PIN_REQUIRED:
6874 + gsm_send_pin(gsm->modul, gsm->pin);
6875 + break;
6876 + case GSM_EVENT_SM_RECEIVED:
6877 + ast_verbose(VERBOSE_PREFIX_3 "SMS received on span %d. PDU: %s\n", gsm->span, e->sm_received.pdu);
6878 + break;
6879 + default:
6880 + ast_log(LOG_WARNING,"!! Unknown GSM event %d !!\n", e->e);
6881 + }
6882 +}
6883 +
6884 +static void *gsm_dchannel(void *vgsm)
6885 +{
6886 + struct zt_gsm *gsm = vgsm;
6887 + gsm_event *e;
6888 + struct timeval tv = {0,0}, *next;
6889 + fd_set rfds, efds;
6890 + int res,x;
6891 +
6892 + if (!gsm) return NULL;
6893 +
6894 + if (!gsm->modul) {
6895 + fprintf(stderr, "No gsm_mod\n");
6896 + return NULL;
6897 + }
6898 + gsm_set_debug(gsm->modul, 1);
6899 + for (;;) {
6900 +
6901 + /* Run the D-Channel */
6902 + FD_ZERO(&rfds);
6903 + FD_ZERO(&efds);
6904 + FD_SET(gsm->fd, &rfds);
6905 + FD_SET(gsm->fd, &efds);
6906 +
6907 + if ((next = gsm_schedule_next(gsm->modul))) {
6908 + gettimeofday(&tv, NULL);
6909 + tv.tv_sec = next->tv_sec - tv.tv_sec;
6910 + tv.tv_usec = next->tv_usec - tv.tv_usec;
6911 + if (tv.tv_usec < 0) {
6912 + tv.tv_usec += 1000000;
6913 + tv.tv_sec -= 1;
6914 + }
6915 + if (tv.tv_sec < 0) {
6916 + tv.tv_sec = 0;
6917 + tv.tv_usec = 0;
6918 + }
6919 + }
6920 + res = select(gsm->fd + 1, &rfds, NULL, &efds, next ? &tv : NULL);
6921 + e = NULL;
6922 +
6923 + ast_mutex_lock(&gsm->lock);
6924 + if (!res) {
6925 + e = gsm_schedule_run(gsm->modul);
6926 + } else if (res > 0) {
6927 + e = gsm_check_event(gsm->modul, 1);
6928 + } else if (errno == ELAST) {
6929 + res = ioctl(gsm->fd, ZT_GETEVENT, &x);
6930 + printf("Got Zaptel event: %d\n", x);
6931 + } else if (errno != EINTR)
6932 + fprintf(stderr, "Error (%d) on select: %s\n", ELAST, strerror(errno));
6933 +
6934 + if (!e) {
6935 + e = gsm_check_event(gsm->modul, 0);
6936 + }
6937 +
6938 + if (e) {
6939 + handle_gsm_event(gsm, e);
6940 + }
6941 + ast_mutex_unlock(&gsm->lock);
6942 +
6943 + res = ioctl(gsm->fd, ZT_GETEVENT, &x);
6944 +
6945 + if (!res && x) {
6946 + switch (x) {
6947 + case ZT_EVENT_NOALARM:
6948 + ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", gsm->span);
6949 + usleep(1000);
6950 + gsm_restart(gsm->modul);
6951 + break;
6952 + case ZT_EVENT_ALARM:
6953 + ast_log(LOG_NOTICE, "Alarm detected on span %d\n", gsm->span);
6954 + break;
6955 + default:
6956 + fprintf(stderr, "Got event on GSM interface: %d\n", x);
6957 + }
6958 + }
6959 +
6960 +
6961 + }
6962 + return NULL;
6963 +}
6964 +
6965 +#endif
6966
6967 #ifdef ZAPATA_PRI
6968 static struct zt_pvt *pri_find_crv(struct zt_pri *pri, int crv)
6969 @@ -7688,6 +8233,57 @@
6970 return NULL;
6971 }
6972
6973 +static int pri_find_tei(struct zt_pri *pri, q931_call *c, int tei)
6974 +{
6975 + int x=0;
6976 + for (x=0;x<pri->numchans;x++) {
6977 + if (!pri->pvts[x]) continue;
6978 + if ((pri->pvts[x]->tei == tei) && (pri->pvts[x]-> call != c)) {
6979 + return x;
6980 + }
6981 + }
6982 + return -1;
6983 +}
6984 +
6985 +static struct zt_holded_call *pri_get_callonhold(struct zt_pri *pri, int cref, int tei) {
6986 + struct zt_holded_call *zhc = pri->holded_calls;
6987 + struct zt_holded_call *zhctemp = NULL;
6988 +
6989 + while (zhc) {
6990 + if ((zhc->tei == tei) && ((zhc->cref == cref) || (cref == -1))) {
6991 + return zhc;
6992 + }
6993 + zhctemp = zhc;
6994 + if (zhc) zhc = zhc->next;
6995 + }
6996 + return NULL;
6997 +}
6998 +
6999 +static int pri_destroy_callonhold(struct zt_pri *pri, struct zt_holded_call *onhold) {
7000 + struct zt_holded_call *zhc = pri->holded_calls;
7001 + struct zt_holded_call *zhctemp = NULL;
7002 +
7003 + while (zhc) {
7004 + if (zhc == onhold) {
7005 + if (zhctemp) {
7006 + zhctemp->next = zhc->next;
7007 + zhc = zhctemp;
7008 + } else {
7009 + pri->holded_calls = zhc->next;
7010 + zhc = pri->holded_calls;
7011 + zhctemp = NULL;
7012 + }
7013 + }
7014 + zhctemp = zhc;
7015 + if (zhc) zhc = zhc->next;
7016 + }
7017 + if (onhold) {
7018 + free(onhold);
7019 + onhold = NULL;
7020 + return 1;
7021 + }
7022 + return 0;
7023 +}
7024
7025 static int pri_find_principle(struct zt_pri *pri, int channel)
7026 {
7027 @@ -7720,7 +8316,9 @@
7028 static int pri_fixup_principle(struct zt_pri *pri, int principle, q931_call *c)
7029 {
7030 int x;
7031 + int res = 0;
7032 struct zt_pvt *crv;
7033 + char tmpname[256];
7034 if (!c) {
7035 if (principle < 0)
7036 return -1;
7037 @@ -7734,6 +8332,7 @@
7038 /* First, check for other bearers */
7039 for (x=0;x<pri->numchans;x++) {
7040 if (!pri->pvts[x]) continue;
7041 +// ast_log(LOG_NOTICE, "principle %d channel %d call %d channel[x]->call %d\n",principle, x, c, pri->pvts[x]->call);
7042 if (pri->pvts[x]->call == c) {
7043 /* Found our call */
7044 if (principle != x) {
7045 @@ -7747,19 +8346,56 @@
7046 }
7047 /* Fix it all up now */
7048 pri->pvts[principle]->owner = pri->pvts[x]->owner;
7049 + pri->pvts[principle]->outgoing = pri->pvts[x]->outgoing;
7050 if (pri->pvts[principle]->owner) {
7051 snprintf(pri->pvts[principle]->owner->name, sizeof(pri->pvts[principle]->owner->name),
7052 "Zap/%d:%d-%d", pri->trunkgroup, pri->pvts[principle]->channel, 1);
7053 pri->pvts[principle]->owner->tech_pvt = pri->pvts[principle];
7054 pri->pvts[principle]->owner->fds[0] = pri->pvts[principle]->subs[SUB_REAL].zfd;
7055 pri->pvts[principle]->subs[SUB_REAL].owner = pri->pvts[x]->subs[SUB_REAL].owner;
7056 - } else
7057 + } else {
7058 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);
7059 + }
7060 pri->pvts[principle]->call = pri->pvts[x]->call;
7061 + pri->pvts[principle]->dsp = pri->pvts[x]->dsp;
7062 + pri->pvts[principle]->alreadyhungup = pri->pvts[x]->alreadyhungup;
7063 + pri->pvts[principle]->digital = pri->pvts[x]->digital;
7064 + pri->pvts[principle]->faxhandled = pri->pvts[x]->faxhandled;
7065 +
7066 + if ((pri->nodetype == BRI_CPE_PTMP) || (pri->nodetype == BRI_CPE)) {
7067 + /* this might also apply for other pri types! */
7068 + pri->pvts[principle]->law = pri->pvts[x]->law;
7069 + if (ioctl(pri->pvts[principle]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &pri->pvts[principle]->law) == -1)
7070 + ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", pri->pvts[principle]->channel, pri->pvts[principle]->law);
7071 + res = zt_setlaw(pri->pvts[principle]->subs[SUB_REAL].zfd, pri->pvts[principle]->law);
7072 + if (res < 0)
7073 + ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[principle]->channel);
7074 + if (!pri->pvts[principle]->digital) {
7075 + res = set_actual_gain(pri->pvts[principle]->subs[SUB_REAL].zfd, 0, pri->pvts[principle]->rxgain, pri->pvts[principle]->txgain, pri->pvts[principle]->law);
7076 + } else {
7077 + res = set_actual_gain(pri->pvts[principle]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[principle]->law);
7078 + }
7079 + if (res < 0)
7080 + ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[principle]->channel);
7081 + zt_confmute(pri->pvts[x], 0);
7082 + update_conf(pri->pvts[x]);
7083 + reset_conf(pri->pvts[x]);
7084 + restore_gains(pri->pvts[x]);
7085 + zt_disable_ec(pri->pvts[x]);
7086 + zt_setlinear(pri->pvts[x]->subs[SUB_REAL].zfd, 0);
7087 + }
7088 +
7089 + if (pri->pvts[principle]->owner) {
7090 + snprintf(tmpname, sizeof(tmpname), "Zap/%d-1", pri->pvts[principle]->channel);
7091 + ast_change_name(pri->pvts[principle]->owner, tmpname);
7092 + }
7093 +
7094 +
7095 /* Free up the old channel, now not in use */
7096 pri->pvts[x]->subs[SUB_REAL].owner = NULL;
7097 pri->pvts[x]->owner = NULL;
7098 pri->pvts[x]->call = NULL;
7099 + pri->pvts[x]->dsp = NULL;
7100 }
7101 return principle;
7102 }
7103 @@ -7788,7 +8424,9 @@
7104 }
7105 crv = crv->next;
7106 }
7107 - ast_log(LOG_WARNING, "Call specified, but not found?\n");
7108 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
7109 + ast_log(LOG_WARNING, "Call specified, but not found?\n");
7110 + }
7111 return -1;
7112 }
7113
7114 @@ -7850,86 +8488,33 @@
7115 #ifndef PRI_RESTART
7116 #error "Upgrade your libpri"
7117 #endif
7118 -static void zt_pri_message(struct pri *pri, char *s)
7119 +static void zt_pri_message(char *s, int span)
7120 {
7121 - int x, y;
7122 - int dchan = -1, span = -1;
7123 - int dchancount = 0;
7124 -
7125 - if (pri) {
7126 - for (x = 0; x < NUM_SPANS; x++) {
7127 - for (y = 0; y < NUM_DCHANS; y++) {
7128 - if (pris[x].dchans[y])
7129 - dchancount++;
7130 -
7131 - if (pris[x].dchans[y] == pri)
7132 - dchan = y;
7133 - }
7134 - if (dchan >= 0) {
7135 - span = x;
7136 - break;
7137 - }
7138 - dchancount = 0;
7139 - }
7140 - if ((dchan >= 0) && (span >= 0)) {
7141 - if (dchancount > 1)
7142 - ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
7143 - else
7144 - ast_verbose("%s", s);
7145 - } else
7146 - ast_verbose("PRI debug error: could not find pri associated it with debug message output\n");
7147 - } else
7148 - ast_verbose("%s", s);
7149 -
7150 - ast_mutex_lock(&pridebugfdlock);
7151 -
7152 - if (pridebugfd >= 0)
7153 - write(pridebugfd, s, strlen(s));
7154 -
7155 - ast_mutex_unlock(&pridebugfdlock);
7156 + ast_verbose("%d %s", span, s);
7157 }
7158
7159 -static void zt_pri_error(struct pri *pri, char *s)
7160 +static void zt_pri_error(char *s, int span)
7161 {
7162 - int x, y;
7163 - int dchan = -1, span = -1;
7164 - int dchancount = 0;
7165 -
7166 - if (pri) {
7167 - for (x = 0; x < NUM_SPANS; x++) {
7168 - for (y = 0; y < NUM_DCHANS; y++) {
7169 - if (pris[x].dchans[y])
7170 - dchancount++;
7171 -
7172 - if (pris[x].dchans[y] == pri)
7173 - dchan = y;
7174 - }
7175 - if (dchan >= 0) {
7176 - span = x;
7177 - break;
7178 - }
7179 - dchancount = 0;
7180 - }
7181 - if ((dchan >= 0) && (span >= 0)) {
7182 - if (dchancount > 1)
7183 - ast_log(LOG_WARNING, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
7184 - else
7185 - ast_verbose("%s", s);
7186 - } else
7187 - ast_verbose("PRI debug error: could not find pri associated it with debug message output\n");
7188 - } else
7189 - ast_log(LOG_WARNING, "%s", s);
7190 -
7191 - ast_mutex_lock(&pridebugfdlock);
7192 + ast_log(LOG_WARNING, "%d %s", span, s);
7193 +}
7194
7195 - if (pridebugfd >= 0)
7196 - write(pridebugfd, s, strlen(s));
7197 +#ifdef ZAPATA_GSM
7198 +static void zt_gsm_message(char *s, int span)
7199 +{
7200 +// ast_verbose("%d %s", span, s);
7201 +}
7202
7203 - ast_mutex_unlock(&pridebugfdlock);
7204 +static void zt_gsm_error(char *s, int span)
7205 +{
7206 + ast_log(LOG_WARNING, "GSM: %d %s", span, s);
7207 }
7208 +#endif
7209
7210 static int pri_check_restart(struct zt_pri *pri)
7211 {
7212 + if ((pri->nodetype != PRI_NETWORK) || (pri->nodetype != PRI_CPE)) {
7213 + return 0;
7214 + }
7215 do {
7216 pri->resetpos++;
7217 } while((pri->resetpos < pri->numchans) &&
7218 @@ -8012,6 +8597,32 @@
7219 }
7220 }
7221
7222 +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) {
7223 + if (callingnum && (callingnum_len > stripmsd)) {
7224 + callingnum += stripmsd;
7225 + }
7226 + switch (callingplan) {
7227 + case PRI_INTERNATIONAL_ISDN:
7228 + snprintf(callerid, callerid_len, "%s%s", pri->internationalprefix, callingnum);
7229 + break;
7230 + case PRI_NATIONAL_ISDN:
7231 + snprintf(callerid, callerid_len, "%s%s", pri->nationalprefix, callingnum);
7232 + break;
7233 + case PRI_LOCAL_ISDN:
7234 + snprintf(callerid, callerid_len, "%s%s", pri->localprefix, callingnum);
7235 + break;
7236 + case PRI_PRIVATE:
7237 + snprintf(callerid, callerid_len, "%s%s", pri->privateprefix, callingnum);
7238 + break;
7239 + case PRI_UNKNOWN:
7240 + snprintf(callerid, callerid_len, "%s%s", pri->unknownprefix, callingnum);
7241 + break;
7242 + default:
7243 + snprintf(callerid, callerid_len, "%s", callingnum);
7244 + break;
7245 + }
7246 +}
7247 +
7248 static void *pri_dchannel(void *vpri)
7249 {
7250 struct zt_pri *pri = vpri;
7251 @@ -8103,6 +8714,8 @@
7252 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
7253 activeidles++;
7254 }
7255 + // 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);
7256 +
7257 #if 0
7258 printf("nextidle: %d, haveidles: %d, minunsed: %d\n",
7259 nextidle, haveidles, minunused);
7260 @@ -8204,9 +8817,36 @@
7261 if (x == ZT_EVENT_ALARM) {
7262 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
7263 pri_find_dchan(pri);
7264 + if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
7265 + if (pri->pri) {
7266 + ast_log(LOG_NOTICE, "pri_shutdown\n");
7267 + for (i=0; i<pri->numchans; i++) {
7268 + struct zt_pvt *p = pri->pvts[i];
7269 + if (p) {
7270 + if (p->call) {
7271 + if (p->pri && p->pri->pri) {
7272 + pri_destroycall(p->pri->pri, p->call);
7273 + p->call = NULL;
7274 + p->tei = -1;
7275 + } else
7276 + ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
7277 + }
7278 + if (p->owner)
7279 + p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7280 + p->inalarm = 1;
7281 + }
7282 + }
7283 + pri_shutdown(pri->pri);
7284 + }
7285 + }
7286 } else if (x == ZT_EVENT_NOALARM) {
7287 - pri->dchanavail[which] |= DCHAN_NOTINALARM;
7288 - pri_restart(pri->dchans[which]);
7289 + if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
7290 + pri->dchanavail[which] |= DCHAN_NOTINALARM;
7291 + pri->dchanavail[which] |= DCHAN_UP;
7292 + } else {
7293 + pri->dchanavail[which] |= DCHAN_NOTINALARM;
7294 + pri_restart(pri->dchans[which]);
7295 + }
7296 }
7297
7298 if (option_debug)
7299 @@ -8218,8 +8858,7 @@
7300 break;
7301 }
7302 } else if (errno != EINTR)
7303 - ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
7304 -
7305 + ast_log(LOG_WARNING, "pri_event returned error %d (%s) on span %d\n", errno, strerror(errno), pri->span);
7306 if (e) {
7307 if (pri->debug)
7308 pri_dump_event(pri->dchans[which], e);
7309 @@ -8227,32 +8866,102 @@
7310 pri->dchanavail[which] |= DCHAN_UP;
7311 switch(e->e) {
7312 case PRI_EVENT_DCHAN_UP:
7313 - if (option_verbose > 1)
7314 - ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
7315 - pri->dchanavail[which] |= DCHAN_UP;
7316 - if (!pri->pri) pri_find_dchan(pri);
7317 -
7318 - /* Note presense of D-channel */
7319 - time(&pri->lastreset);
7320 -
7321 - /* Restart in 5 seconds */
7322 - if (pri->resetinterval > -1) {
7323 - pri->lastreset -= pri->resetinterval;
7324 - pri->lastreset += 5;
7325 - }
7326 - pri->resetting = 0;
7327 - /* Take the channels from inalarm condition */
7328 - for (i=0; i<pri->numchans; i++)
7329 - if (pri->pvts[i]) {
7330 - pri->pvts[i]->inalarm = 0;
7331 - }
7332 + if (pri->nodetype == BRI_NETWORK_PTMP) {
7333 + if (option_verbose > 3)
7334 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
7335 + pri->dchanavail[which] |= (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP);
7336 + pri_find_dchan(pri);
7337 +
7338 + /* Note presense of D-channel */
7339 + time(&pri->lastreset);
7340 +
7341 + pri->resetting = 0;
7342 + /* Take the channels from inalarm condition */
7343 + for (i=0; i<pri->numchans; i++)
7344 + if (pri->pvts[i]) {
7345 + pri->pvts[i]->inalarm = 0;
7346 + }
7347 + } else {
7348 + if (pri->nodetype == BRI_CPE_PTMP) {
7349 + if (option_verbose > 3)
7350 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
7351 + } else {
7352 + if (option_verbose > 1)
7353 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
7354 + }
7355 + pri->dchanavail[which] |= (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP);
7356 + pri_find_dchan(pri);
7357 +
7358 + /* Note presense of D-channel */
7359 + time(&pri->lastreset);
7360 +
7361 + /* Restart in 5 seconds */
7362 + pri->lastreset -= pri->resetinterval;
7363 + pri->lastreset += 5;
7364 + pri->resetting = 0;
7365 + /* Take the channels from inalarm condition */
7366 + for (i=0; i<pri->numchans; i++) {
7367 + struct zt_pvt *p = pri->pvts[i];
7368 + if (p) {
7369 + p->inalarm = 0;
7370 + /* hang up calls that are not bridged yet, dont touch bridged calls */
7371 + if (p->call) {
7372 + if (p->pri && p->pri->pri) {
7373 + if (p->owner) {
7374 + if (p->owner->_state != AST_STATE_UP) {
7375 + p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7376 + pri_destroycall(p->pri->pri, p->call);
7377 + p->call = NULL;
7378 + }
7379 + } else {
7380 + pri_destroycall(p->pri->pri, p->call);
7381 + p->call = NULL;
7382 + }
7383 + }
7384 + }
7385 + }
7386 + }
7387 + }
7388 break;
7389 case PRI_EVENT_DCHAN_DOWN:
7390 - if (option_verbose > 1)
7391 - ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
7392 - pri->dchanavail[which] &= ~DCHAN_UP;
7393 - pri_find_dchan(pri);
7394 - if (!pri_is_up(pri)) {
7395 + if (pri->nodetype == BRI_NETWORK_PTMP) {
7396 + if (option_verbose > 3)
7397 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
7398 + // PTMP BRIs have N dchans, handled by libpri
7399 + if (e->gen.tei == 0) break;
7400 + /* Hangup active channels */
7401 + for (i=0; i<pri->numchans; i++) {
7402 + struct zt_pvt *p = pri->pvts[i];
7403 + if (p) {
7404 + // ast_log(LOG_NOTICE, "chan %d tei %d\n",i,p->tei);
7405 + if (p->tei == e->gen.tei) {
7406 + if (p->call) {
7407 + if (p->pri && p->pri->pri) {
7408 + // pri_hangup(p->pri->pri, p->call, -1);
7409 + pri_destroycall(p->pri->pri, p->call);
7410 + p->tei = -1;
7411 + p->call = NULL;
7412 + } else
7413 + ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
7414 + }
7415 + if (p->owner)
7416 + p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7417 + p->inalarm = 1;
7418 + p->tei = -1;
7419 + }
7420 + }
7421 + }
7422 + } else {
7423 + if (pri->nodetype == BRI_CPE_PTMP) {
7424 + if (option_verbose > 3)
7425 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
7426 + } else {
7427 + if (option_verbose > 1)
7428 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
7429 + }
7430 + pri->dchanavail[which] &= ~DCHAN_UP;
7431 + pri_find_dchan(pri);
7432 + if (!pri_is_up(pri)) {
7433 pri->resetting = 0;
7434 /* Hangup active channels and put them in alarm mode */
7435 for (i=0; i<pri->numchans; i++) {
7436 @@ -8260,19 +8969,29 @@
7437 if (p) {
7438 if (p->call) {
7439 if (p->pri && p->pri->pri) {
7440 - pri_hangup(p->pri->pri, p->call, -1);
7441 - pri_destroycall(p->pri->pri, p->call);
7442 - p->call = NULL;
7443 + if (p->owner) {
7444 + if (p->owner->_state != AST_STATE_UP) {
7445 + // pri_hangup(p->pri->pri, p->call, -1);
7446 + pri_destroycall(p->pri->pri, p->call);
7447 + p->call = NULL;
7448 + p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7449 + p->inalarm = 1;
7450 + }
7451 + } else {
7452 + pri_destroycall(p->pri->pri, p->call);
7453 + p->call = NULL;
7454 + p->inalarm = 1;
7455 + }
7456 } else
7457 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
7458 }
7459 if (p->realcall) {
7460 - pri_hangup_all(p->realcall, pri);
7461 - } else if (p->owner)
7462 - p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7463 - p->inalarm = 1;
7464 + pri_hangup_all(p->realcall, pri);
7465 + p->inalarm = 1;
7466 + }
7467 }
7468 }
7469 + }
7470 }
7471 break;
7472 case PRI_EVENT_RESTART:
7473 @@ -8307,8 +9026,8 @@
7474 pri_destroycall(pri->pri, pri->pvts[x]->call);
7475 pri->pvts[x]->call = NULL;
7476 }
7477 - if (pri->pvts[chanpos]->realcall)
7478 - pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
7479 + if (pri->pvts[x]->realcall)
7480 + pri_hangup_all(pri->pvts[x]->realcall, pri);
7481 else if (pri->pvts[x]->owner)
7482 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7483 ast_mutex_unlock(&pri->pvts[x]->lock);
7484 @@ -8342,7 +9061,6 @@
7485 }
7486 }
7487 break;
7488 -
7489 case PRI_EVENT_INFO_RECEIVED:
7490 chanpos = pri_find_principle(pri, e->ring.channel);
7491 if (chanpos < 0) {
7492 @@ -8351,9 +9069,11 @@
7493 } else {
7494 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
7495 if (chanpos > -1) {
7496 +// ast_log(LOG_NOTICE, "INFO received on channel %d/%d span %d\n",
7497 +// PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
7498 ast_mutex_lock(&pri->pvts[chanpos]->lock);
7499 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
7500 - if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
7501 + if (pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
7502 /* how to do that */
7503 int digitlen = strlen(e->ring.callednum);
7504 char digit;
7505 @@ -8365,6 +9085,14 @@
7506 zap_queue_frame(pri->pvts[chanpos], &f, pri);
7507 }
7508 }
7509 + if (!pri->overlapdial) {
7510 + strncat(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
7511 + if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
7512 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
7513 + } else {
7514 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
7515 + }
7516 + }
7517 }
7518 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7519 }
7520 @@ -8372,39 +9100,55 @@
7521 break;
7522 case PRI_EVENT_RING:
7523 crv = NULL;
7524 - if (e->ring.channel == -1)
7525 + if (e->ring.channel == -1) {
7526 + /* if no channel specified find one empty */
7527 chanpos = pri_find_empty_chan(pri, 1);
7528 - else
7529 + } else {
7530 chanpos = pri_find_principle(pri, e->ring.channel);
7531 - /* if no channel specified find one empty */
7532 + }
7533 if (chanpos < 0) {
7534 - ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
7535 - PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
7536 + /* no channel specified and no free channel. this is a callwating SETUP */
7537 + if (e->ring.channel == -1) {
7538 + if (option_verbose > 2)
7539 + 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);
7540 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_USER_BUSY, -1);
7541 + break;
7542 + }
7543 } else {
7544 + /* ok, we got a b channel for this call, lock it */
7545 ast_mutex_lock(&pri->pvts[chanpos]->lock);
7546 if (pri->pvts[chanpos]->owner) {
7547 - if (pri->pvts[chanpos]->call == e->ring.call) {
7548 - ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
7549 - PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
7550 - break;
7551 - } else {
7552 - ast_log(LOG_WARNING, "Ring requested on channel %d/%d already in use on span %d. Hanging up owner.\n",
7553 + /* safety check, for messed up retransmissions? */
7554 + if (pri->pvts[chanpos]->call == e->ring.call) {
7555 + ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
7556 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
7557 - if (pri->pvts[chanpos]->realcall)
7558 - pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
7559 - else
7560 - pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7561 - ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7562 - chanpos = -1;
7563 - }
7564 - }
7565 - if (chanpos > -1)
7566 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7567 + chanpos = -1;
7568 + break;
7569 + } else {
7570 + ast_log(LOG_WARNING, "Ring requested on channel %d/%d already in use on span %d. Hanging up owner.\n",
7571 + PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
7572 + if (pri->pvts[chanpos]->realcall)
7573 + pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
7574 + else
7575 + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7576 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7577 + chanpos = -1;
7578 + break;
7579 + }
7580 + }
7581 + if (chanpos > -1) {
7582 + /* everything is ok with the b channel */
7583 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7584 + }
7585 }
7586 - if ((chanpos < 0) && (e->ring.flexible))
7587 - chanpos = pri_find_empty_chan(pri, 1);
7588 + /* actually, we already got a valid channel by now */
7589 if (chanpos > -1) {
7590 ast_mutex_lock(&pri->pvts[chanpos]->lock);
7591 + /* dont detect dtmfs before the signalling is done */
7592 + disable_dtmf_detect(pri->pvts[chanpos]);
7593 + /* this channel is owned by this TEI */
7594 + pri->pvts[chanpos]->tei = e->ring.tei;
7595 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
7596 /* Should be safe to lock CRV AFAIK while bearer is still locked */
7597 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
7598 @@ -8418,13 +9162,14 @@
7599 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);
7600 } else
7601 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);
7602 - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
7603 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE, -1);
7604 if (crv)
7605 ast_mutex_unlock(&crv->lock);
7606 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7607 break;
7608 }
7609 }
7610 + /* assign call to b channel */
7611 pri->pvts[chanpos]->call = e->ring.call;
7612 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
7613 if (pri->pvts[chanpos]->use_callerid) {
7614 @@ -8449,29 +9194,78 @@
7615 }
7616 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
7617 e->ring.redirectingnum, e->ring.callingplanrdnis);
7618 + /* get callingpres */
7619 + pri->pvts[chanpos]->cid_pres = e->ring.callingpres;
7620 + switch (e->ring.callingpres) {
7621 + case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
7622 + case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
7623 + case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
7624 + case PRES_PROHIB_NETWORK_NUMBER:
7625 + strncpy(pri->pvts[chanpos]->cid_name, pri->withheldcid, sizeof(pri->pvts[chanpos]->cid_name));
7626 + break;
7627 + case PRES_NUMBER_NOT_AVAILABLE:
7628 + strncpy(pri->pvts[chanpos]->cid_name, pri->nocid, sizeof(pri->pvts[chanpos]->cid_name));
7629 + break;
7630 + }
7631 /* If immediate=yes go to s|1 */
7632 if (pri->pvts[chanpos]->immediate) {
7633 if (option_verbose > 2)
7634 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
7635 pri->pvts[chanpos]->exten[0] = 's';
7636 pri->pvts[chanpos]->exten[1] = '\0';
7637 - }
7638 - /* Get called number */
7639 - else if (!ast_strlen_zero(e->ring.callednum)) {
7640 - ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
7641 - ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
7642 - } else
7643 - pri->pvts[chanpos]->exten[0] = '\0';
7644 - /* Set DNID on all incoming calls -- even immediate */
7645 - if (!ast_strlen_zero(e->ring.callednum))
7646 - ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
7647 - /* No number yet, but received "sending complete"? */
7648 - if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
7649 + } else if (ast_strlen_zero(e->ring.callednum)) {
7650 + /* called party number is empty */
7651 + if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
7652 + if (!pri->overlapdial) {
7653 + // be able to set digittimeout for BRI phones
7654 + pri->pvts[chanpos]->exten[0] = 's';
7655 + pri->pvts[chanpos]->exten[1] = '\0';
7656 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
7657 + } else {
7658 + pri->pvts[chanpos]->exten[0] = '\0';
7659 + }
7660 + } else {
7661 + if (pri->nodetype == BRI_CPE) {
7662 + /* fix for .at p2p bri lines */
7663 + pri->pvts[chanpos]->exten[0] = 's';
7664 + pri->pvts[chanpos]->exten[1] = '\0';
7665 + } else {
7666 + pri->pvts[chanpos]->exten[0] = '\0';
7667 + }
7668 + }
7669 + /* No number yet, but received "sending complete"? */
7670 + if (e->ring.complete) {
7671 if (option_verbose > 2)
7672 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
7673 pri->pvts[chanpos]->exten[0] = 's';
7674 pri->pvts[chanpos]->exten[1] = '\0';
7675 - }
7676 + }
7677 + } else {
7678 + /* Get called number */
7679 + 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);
7680 + 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);
7681 + if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
7682 + /* if we get the next digit we should stop the dialtone */
7683 + if (!pri->overlapdial) {
7684 + // with overlapdial=no the exten is always prefixed by "s"
7685 + if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
7686 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
7687 + } else {
7688 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
7689 + }
7690 + } else {
7691 + if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten)) {
7692 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
7693 + } else {
7694 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
7695 + }
7696 + }
7697 + }
7698 + }
7699 + /* Part 3: create channel, setup audio... */
7700 + /* Set DNID on all incoming calls -- even immediate */
7701 + if (!ast_strlen_zero(e->ring.callednum))
7702 + strncpy(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid) - 1);
7703 /* Make sure extension exists (or in overlap dial mode, can exist) */
7704 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
7705 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
7706 @@ -8490,22 +9284,38 @@
7707 res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
7708 if (res < 0)
7709 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
7710 - res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
7711 + if (IS_DIGITAL(e->ring.ctype)) {
7712 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[chanpos]->law);
7713 + } else {
7714 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
7715 + }
7716 if (res < 0)
7717 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
7718 - if (e->ring.complete || !pri->overlapdial)
7719 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
7720 + if (e->ring.complete || !pri->overlapdial) {
7721 /* Just announce proceeding */
7722 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
7723 - else {
7724 + // pri->pvts[chanpos]->ignoredtmf = 0;
7725 + } else {
7726 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
7727 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
7728 else
7729 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
7730 + }
7731 + } else {
7732 + /* BRI_NETWORK | BRI_NETWORK_PTMP */
7733 + if (pri->overlapdial || (!strcasecmp(pri->pvts[chanpos]->exten, "s"))) {
7734 + /* send a SETUP_ACKNOWLEDGE */
7735 + pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
7736 + } else {
7737 + /* send an ALERTING ??? wtf */
7738 + // pri_acknowledge(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
7739 + pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
7740 + }
7741 }
7742 - /* Get the use_callingpres state */
7743 - pri->pvts[chanpos]->callingpres = e->ring.callingpres;
7744 -
7745 - /* Start PBX */
7746 +
7747 + /* overlapdial = yes and the extension can be valid */
7748 +
7749 if (pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
7750 /* Release the PRI lock while we create the channel */
7751 ast_mutex_unlock(&pri->lock);
7752 @@ -8513,14 +9323,31 @@
7753 /* Set bearer and such */
7754 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
7755 c = zt_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
7756 + if (c && (e->ring.lowlayercompat[0] > 0)) {
7757 + memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
7758 + }
7759 pri->pvts[chanpos]->owner = &inuse;
7760 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
7761 } else {
7762 c = zt_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
7763 + if (c && (e->ring.lowlayercompat[0] > 0)) {
7764 + memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
7765 + }
7766 + zt_enable_ec(pri->pvts[chanpos]);
7767 }
7768 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
7769 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
7770 }
7771 + if (!ast_strlen_zero(e->ring.callingnum)) {
7772 + char tmpstr[256];
7773 + pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
7774 + pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
7775 + }
7776 + if (!ast_strlen_zero(e->ring.callingani)) {
7777 + char tmpstr[256];
7778 + pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
7779 + pbx_builtin_setvar_helper(c, "PRI_USER_CID", tmpstr);
7780 + }
7781 if(e->ring.ani2 >= 0) {
7782 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
7783 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
7784 @@ -8540,8 +9367,8 @@
7785 ast_mutex_lock(&pri->lock);
7786 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
7787 if (option_verbose > 2)
7788 - ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
7789 - plancallingnum, !ast_strlen_zero(pri->pvts[chanpos]->exten) ? pri->pvts[chanpos]->exten : "<unspecified>",
7790 + ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap %s call from '%s' to '%s' on channel %d/%d, span %d\n",
7791 + pri->pvts[chanpos]->digital ? "data" : "voice", plancallingnum, !ast_strlen_zero(pri->pvts[chanpos]->exten) ? pri->pvts[chanpos]->exten : "<unspecified>",
7792 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
7793 } else {
7794 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
7795 @@ -8549,14 +9376,18 @@
7796 if (c)
7797 ast_hangup(c);
7798 else {
7799 - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
7800 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION, -1);
7801 pri->pvts[chanpos]->call = NULL;
7802 }
7803 }
7804 } else {
7805 + /* overlapdial = no */
7806 ast_mutex_unlock(&pri->lock);
7807 /* Release PRI lock while we create the channel */
7808 c = zt_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
7809 + if (c && (e->ring.lowlayercompat[0] > 0)) {
7810 + memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
7811 + }
7812 ast_mutex_lock(&pri->lock);
7813 if (c) {
7814 char calledtonstr[10];
7815 @@ -8577,23 +9408,40 @@
7816 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
7817 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
7818 if (option_verbose > 2)
7819 - ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
7820 - plancallingnum, pri->pvts[chanpos]->exten,
7821 + ast_verbose(VERBOSE_PREFIX_3 "Accepting %s call from '%s' to '%s' on channel %d/%d, span %d\n",
7822 + pri->pvts[chanpos]->digital ? "data" : "voice", e->ring.callingnum, pri->pvts[chanpos]->exten,
7823 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
7824 zt_enable_ec(pri->pvts[chanpos]);
7825 + if(!ast_strlen_zero(e->ring.callingsubaddr)) {
7826 + pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
7827 + }
7828 + if (!ast_strlen_zero(e->ring.callingnum)) {
7829 + char tmpstr[256];
7830 + pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
7831 + pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
7832 + }
7833 + if (!ast_strlen_zero(e->ring.callingani)) {
7834 + char tmpstr[256];
7835 + pri_make_callerid(pri, tmpstr,sizeof(tmpstr), e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
7836 + pbx_builtin_setvar_helper(c, "PRI_USER_CID", e->ring.callednum);
7837 + }
7838 + if (!ast_strlen_zero(e->ring.useruserinfo)) {
7839 + pbx_builtin_setvar_helper(c, "UUI", e->ring.useruserinfo);
7840 + }
7841 } else {
7842 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
7843 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
7844 - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
7845 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION, -1);
7846 pri->pvts[chanpos]->call = NULL;
7847 }
7848 }
7849 } else {
7850 + /* invalid extension */
7851 if (option_verbose > 2)
7852 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
7853 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
7854 pri->pvts[chanpos]->prioffset, pri->span);
7855 - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
7856 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED, -1);
7857 pri->pvts[chanpos]->call = NULL;
7858 pri->pvts[chanpos]->exten[0] = '\0';
7859 }
7860 @@ -8601,7 +9449,7 @@
7861 ast_mutex_unlock(&crv->lock);
7862 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7863 } else
7864 - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
7865 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL, -1);
7866 break;
7867 case PRI_EVENT_RINGING:
7868 chanpos = pri_find_principle(pri, e->ringing.channel);
7869 @@ -8619,7 +9467,7 @@
7870 } else {
7871 ast_mutex_lock(&pri->pvts[chanpos]->lock);
7872 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
7873 - zt_enable_ec(pri->pvts[chanpos]);
7874 + // XXX zt_enable_ec(pri->pvts[chanpos]);
7875 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
7876 pri->pvts[chanpos]->alerting = 1;
7877 } else
7878 @@ -8648,9 +9496,15 @@
7879 }
7880 break;
7881 case PRI_EVENT_PROGRESS:
7882 - /* Get chan value if e->e is not PRI_EVNT_RINGING */
7883 + /* Get chan value if e->e is not PRI_EVENT_RINGING */
7884 chanpos = pri_find_principle(pri, e->proceeding.channel);
7885 if (chanpos > -1) {
7886 + if ((pri->pvts[chanpos]->priindication_oob == 2) && (e->proceeding.cause == PRI_CAUSE_USER_BUSY)) {
7887 + /* received PROGRESS with cause BUSY, no inband callprogress wanted => hang up! */
7888 + if (pri->pvts[chanpos]->owner) {
7889 + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7890 + }
7891 + } else {
7892 #ifdef PRI_PROGRESS_MASK
7893 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
7894 #else
7895 @@ -8697,6 +9551,12 @@
7896 case PRI_EVENT_PROCEEDING:
7897 chanpos = pri_find_principle(pri, e->proceeding.channel);
7898 if (chanpos > -1) {
7899 + chanpos = pri_fixup_principle(pri, chanpos, e->proceeding.call);
7900 + if (chanpos < 0) {
7901 + ast_log(LOG_WARNING, "Received PROCEEDING on channel %d/%d not in use on span %d\n",
7902 + PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), pri->span);
7903 + chanpos = -1;
7904 + } else {
7905 if (!pri->pvts[chanpos]->proceeding) {
7906 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
7907
7908 @@ -8747,6 +9607,295 @@
7909 }
7910 }
7911 break;
7912 + case PRI_EVENT_SUSPEND_REQ:
7913 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
7914 + pri_suspend_reject(pri->pri, e->suspend_req.call, "");
7915 + break;
7916 + }
7917 + chanpos = pri_find_principle(pri, e->suspend_req.channel);
7918 + if (chanpos < 0) {
7919 + ast_log(LOG_WARNING, "Suspend requested on unconfigured channel %d span %d\n", chanpos, pri->span);
7920 + chanpos = -1;
7921 + }
7922 +
7923 + if (chanpos > -1) {
7924 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
7925 + if (pri->pvts[chanpos]->owner) {
7926 + if (ast_bridged_channel(pri->pvts[chanpos]->owner)) {
7927 + struct zt_suspended_call *zpc;
7928 + char tmpstr[256];
7929 + zpc = malloc(sizeof(struct zt_suspended_call));
7930 + if (!zpc) {
7931 + ast_log(LOG_ERROR, "unable to malloc zt_suspended_call\n");
7932 + break;
7933 + }
7934 + strncpy(zpc->msn, pri->pvts[chanpos]->cid_num, sizeof(zpc->msn));
7935 + strncpy(zpc->callid, e->suspend_req.callid, sizeof(zpc->callid));
7936 + ast_masq_park_call(ast_bridged_channel(pri->pvts[chanpos]->owner), NULL, 0, &zpc->parked_at);
7937 + zpc->next = pri->suspended_calls;
7938 + pri->suspended_calls = zpc;
7939 + snprintf(tmpstr, sizeof(tmpstr), "Parked at %d", zpc->parked_at);
7940 + pri_suspend_acknowledge(pri->pri, e->suspend_req.call,tmpstr);
7941 + pri->pvts[chanpos]->call = NULL;
7942 + pri->pvts[chanpos]->tei = -1;
7943 + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7944 + } else {
7945 + pri_suspend_reject(pri->pri, e->suspend_req.call, "cant park a non-bridge");
7946 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7947 + break;
7948 + }
7949 + } else {
7950 + pri_suspend_reject(pri->pri, e->suspend_req.call, "");
7951 + }
7952 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7953 + }
7954 + break;
7955 + case PRI_EVENT_RESUME_REQ:
7956 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
7957 + break;
7958 + }
7959 + chanpos = pri_find_empty_chan(pri, 1);
7960 + if (chanpos < 0) {
7961 + pri_resume_reject(pri->pri, e->resume_req.call,"All channels busy");
7962 + ast_log(LOG_WARNING, "Resume requested on odd channel number %d span %d\n", chanpos, pri->span);
7963 + chanpos = -1;
7964 + } else if (!pri->pvts[chanpos]) {
7965 + pri_resume_reject(pri->pri, e->resume_req.call,"General protection fault in module 0x0BRI");
7966 + chanpos = -1;
7967 + }
7968 +
7969 + if (chanpos > -1) {
7970 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
7971 + if (!pri->pvts[chanpos]->owner) {
7972 + struct zt_suspended_call *zpc, *zpcl;
7973 + int unparked=0;
7974 + char extenstr[255], temp[255];
7975 + zpc = NULL;
7976 + zpcl = pri->suspended_calls;
7977 + while (zpcl) {
7978 + // ast_log(LOG_NOTICE, "zpc->parked_at %d zpcl->callid %s\n",zpcl->parked_at, zpcl->callid);
7979 + if (((strlen(zpcl->callid) == 0) && (strlen(e->resume_req.callid)==0)) || (!strcmp(zpcl->callid,e->resume_req.callid))) {
7980 + int law;
7981 + // found a parked call
7982 + snprintf(extenstr, sizeof(extenstr), "%d", zpcl->parked_at);
7983 + strncpy(pri->pvts[chanpos]->exten, extenstr, sizeof(pri->pvts[chanpos]->exten));
7984 + // strncpy(pri->pvts[chanpos]->context, ast_parking_con(), sizeof(pri->pvts[chanpos]->context));
7985 + pri->pvts[chanpos]->call = e->resume_req.call;
7986 + law = 1;
7987 + if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
7988 + ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]), law);
7989 + // uhh ohh...what shall we do without the bearer cap???
7990 + law = ZT_LAW_ALAW;
7991 + res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
7992 + if (res < 0)
7993 + ast_log(LOG_WARNING, "Unable to set law on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
7994 + if (!pri->pvts[chanpos]->digital) {
7995 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
7996 + } else {
7997 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[chanpos]->law);
7998 + }
7999 + if (res < 0)
8000 + ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
8001 + /* Start PBX */
8002 + c = zt_new(pri->pvts[chanpos], AST_STATE_UP, 1, SUB_REAL, law, PRI_TRANS_CAP_SPEECH);
8003 + if (c) {
8004 + pri->pvts[chanpos]->owner = c;
8005 + pri->pvts[chanpos]->call = e->resume_req.call;
8006 + zt_enable_ec(pri->pvts[chanpos]);
8007 + zt_train_ec(pri->pvts[chanpos]);
8008 + } else {
8009 + ast_log(LOG_ERROR, "unable to start pbx\n");
8010 + }
8011 +
8012 + if (zpc) {
8013 + zpc->next = zpcl->next;
8014 + free(zpcl);
8015 + zpcl = zpc->next;
8016 + } else {
8017 + // remove head
8018 + pri->suspended_calls = zpcl->next;
8019 + free(zpcl);
8020 + zpcl = pri->suspended_calls;
8021 + zpc = NULL;
8022 + }
8023 + unparked = 1;
8024 + snprintf(temp, sizeof(temp), "Unparked %s", extenstr);
8025 + pri_resume_acknowledge(pri->pri, e->resume_req.call, chanpos + 1, temp);
8026 + break;
8027 + }
8028 + zpc = zpcl;
8029 + if (zpcl) zpcl = zpcl->next;
8030 + }
8031 + if (!unparked)
8032 + pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
8033 + } else {
8034 + pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
8035 + }
8036 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8037 + }
8038 + break;
8039 + case PRI_EVENT_HOLD_REQ:
8040 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
8041 + pri_hold_reject(pri->pri, e->hold_req.call);
8042 + break;
8043 + }
8044 + chanpos = pri_find_principle(pri, e->hold_req.channel);
8045 + if (chanpos < 0) {
8046 + ast_log(LOG_WARNING, "Hold requested on unconfigured channel %d span %d\n", chanpos, pri->span);
8047 + chanpos = -1;
8048 + }
8049 + if (chanpos > -1) {
8050 + // ast_log(LOG_NOTICE, "Hold request for channel number %d span %d\n", chanpos, pri->span);
8051 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
8052 + if (pri->pvts[chanpos]->owner) {
8053 + struct zt_pvt *p = pri->pvts[chanpos];
8054 + struct zt_holded_call *zhc;
8055 + int holdacked=0;
8056 +
8057 +// ast_log(LOG_NOTICE,"HOLD request from channel %s tei %d\n",p->owner->name, e->hold_req.tei);
8058 + if (ast_bridged_channel(p->owner)) {
8059 + zhc = malloc(sizeof(struct zt_holded_call));
8060 + if (!zhc) {
8061 + ast_log(LOG_ERROR, "unable to malloc zt_holded_call\n");
8062 + break;
8063 + }
8064 + memset(zhc, 0, sizeof(zhc));
8065 + strncpy(zhc->msn, pri->pvts[chanpos]->cid_num, sizeof(zhc->msn));
8066 + strncpy(zhc->uniqueid, ast_bridged_channel(p->owner)->uniqueid, sizeof(zhc->uniqueid));
8067 + zhc->tei = e->hold_req.tei;
8068 + zhc->cref = e->hold_req.cref;
8069 + zhc->call = e->hold_req.call;
8070 + zhc->channel = p->owner;
8071 + zhc->alreadyhungup = 0;
8072 + zhc->bridge = ast_bridged_channel(p->owner);
8073 + zhc->next = pri->holded_calls;
8074 + pri->holded_calls = zhc;
8075 +
8076 + /* put channel on hold */
8077 + ast_masq_hold_call(ast_bridged_channel(p->owner), p->owner);
8078 +
8079 + pri_hold_acknowledge(pri->pri, e->hold_req.call);
8080 + holdacked = 1;
8081 + p->call = NULL; // free the bchannel withouth destroying the call
8082 + p->tei = -1;
8083 + } else {
8084 + // cant hold a non-bridge,...yet
8085 +
8086 + // make a fake channel
8087 +
8088 + // masquerade
8089 +
8090 + // put on hold
8091 + pri_hold_reject(pri->pri, e->hold_req.call);
8092 + }
8093 + } else {
8094 + pri_hold_reject(pri->pri, e->hold_req.call);
8095 + }
8096 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8097 + } else {
8098 + pri_hold_reject(pri->pri, e->hold_req.call);
8099 + }
8100 + break;
8101 + case PRI_EVENT_RETRIEVE_REQ:
8102 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
8103 + pri_retrieve_reject(pri->pri, e->retrieve_req.call);
8104 + break;
8105 + }
8106 + chanpos = pri_find_empty_chan(pri, 1);
8107 + if (chanpos < 0) {
8108 + pri_retrieve_reject(pri->pri, e->retrieve_req.call);
8109 + ast_log(LOG_WARNING, "Retrieve requested on odd channel number %d span %d\n", chanpos, pri->span);
8110 + chanpos = -1;
8111 + break;
8112 + } else if (!pri->pvts[chanpos]) {
8113 + ast_log(LOG_WARNING, "Retrieve requested on unconfigured channel number %d span %d\n", chanpos, pri->span);
8114 + pri_retrieve_reject(pri->pri, e->retrieve_req.call);
8115 + chanpos = -1;
8116 + break;
8117 + }
8118 + if (chanpos > -1) {
8119 + struct zt_holded_call *onhold = NULL;
8120 + int retrieved = 0;
8121 + int res = -1;
8122 + struct app_tmp *tmp;
8123 + pthread_attr_t attr;
8124 + int law;
8125 +
8126 + onhold = pri_get_callonhold(pri, e->retrieve_req.cref, e->retrieve_req.tei);
8127 +
8128 + if (!onhold) {
8129 + pri_retrieve_reject(pri->pri, e->retrieve_req.call);
8130 + break;
8131 + }
8132 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
8133 + // found a parked call
8134 + law = 1;
8135 + if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
8136 + ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]), law);
8137 + // uhh ohh...what shall we do without the bearer cap???
8138 + law = ZT_LAW_ALAW;
8139 + res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
8140 + if (res < 0)
8141 + ast_log(LOG_WARNING, "Unable to set law on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
8142 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
8143 + if (res < 0)
8144 + ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
8145 + /* Start PBX */
8146 + c = zt_new(pri->pvts[chanpos], AST_STATE_UP, 0, SUB_REAL, law, PRI_TRANS_CAP_SPEECH);
8147 + if (c) {
8148 + pri->pvts[chanpos]->owner = c;
8149 + pri->pvts[chanpos]->outgoing = 1; /* for not sending proceedings... */
8150 + pri->pvts[chanpos]->call = e->retrieve_req.call;
8151 + pri->pvts[chanpos]->tei = e->retrieve_req.tei;
8152 + zt_enable_ec(pri->pvts[chanpos]);
8153 + zt_train_ec(pri->pvts[chanpos]);
8154 + } else {
8155 + ast_log(LOG_ERROR, "unable to start pbx\n");
8156 + }
8157 +
8158 + retrieved = 1;
8159 + // 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);
8160 + pri_retrieve_acknowledge(pri->pri, e->retrieve_req.call, chanpos + 1);
8161 +
8162 + // the magic begins here: ....
8163 + tmp = malloc(sizeof(struct app_tmp));
8164 + if (tmp) {
8165 + memset(tmp, 0, sizeof(struct app_tmp));
8166 + strncpy(tmp->app, "holdedcall", sizeof(tmp->app) - 1);
8167 + strncpy(tmp->data, onhold->uniqueid, sizeof(tmp->data) - 1);
8168 + tmp->chan = c;
8169 + }
8170 + pri_destroy_callonhold(pri, onhold);
8171 + onhold = NULL;
8172 +
8173 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8174 + pthread_attr_init(&attr);
8175 + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
8176 + if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
8177 + ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", c->name, strerror(errno));
8178 + free(tmp);
8179 + ast_hangup(c);
8180 + retrieved = 0;
8181 + }
8182 +
8183 + if (!retrieved) {
8184 + pri_retrieve_reject(pri->pri, e->retrieve_req.call);
8185 + }
8186 + }
8187 + break;
8188 + case PRI_EVENT_DISPLAY_RECEIVED:
8189 + ast_log(LOG_NOTICE, "DISPLAY IE: [ %s ] received\n",e->display.text);
8190 + chanpos = pri_find_principle(pri, e->display.channel);
8191 + if (chanpos < 0) {
8192 + ast_log(LOG_WARNING, "odd channel number %d span %d\n", chanpos, pri->span);
8193 + chanpos = -1;
8194 + }
8195 + if (chanpos > -1) {
8196 + if (pri->pvts[chanpos]->owner) {
8197 + // ast_sendtext(pri->pvt[chanpos]->owner, e->display.text);
8198 + }
8199 + }
8200 + break;
8201 case PRI_EVENT_ANSWER:
8202 chanpos = pri_find_principle(pri, e->answer.channel);
8203 if (chanpos < 0) {
8204 @@ -8762,6 +9911,7 @@
8205 chanpos = -1;
8206 } else {
8207 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8208 + pri->pvts[chanpos]->tei = e->answer.tei;
8209 /* Now we can do call progress detection */
8210
8211 /* We changed this so it turns on the DSP no matter what... progress or no progress.
8212 @@ -8791,11 +9941,15 @@
8213 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
8214 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
8215 } else if (pri->pvts[chanpos]->confirmanswer) {
8216 - ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
8217 + ast_log(LOG_DEBUG, "Waiting for answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
8218 } else {
8219 + pri->pvts[chanpos]->dialing = 0;
8220 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
8221 /* Enable echo cancellation if it's not on already */
8222 zt_enable_ec(pri->pvts[chanpos]);
8223 + zt_train_ec(pri->pvts[chanpos]);
8224 + /* stop ignoring inband dtmf */
8225 + enable_dtmf_detect(pri->pvts[chanpos]);
8226 }
8227
8228 #ifdef SUPPORT_USERUSER
8229 @@ -8844,23 +9998,32 @@
8230 }
8231 }
8232 if (option_verbose > 2)
8233 - ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup\n",
8234 - pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8235 + ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
8236 + pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
8237 } else {
8238 - pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
8239 + pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
8240 pri->pvts[chanpos]->call = NULL;
8241 + pri->pvts[chanpos]->tei = -1;
8242 }
8243 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
8244 - if (option_verbose > 2)
8245 + if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
8246 + if (option_verbose > 2)
8247 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
8248 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
8249 - pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
8250 - pri->pvts[chanpos]->resetting = 1;
8251 + pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
8252 + pri->pvts[chanpos]->resetting = 1;
8253 + }
8254 }
8255 - if (e->hangup.aoc_units > -1)
8256 + if (e->hangup.aoc_units > -1) {
8257 + if (pri->pvts[chanpos]->owner) {
8258 + char tmpstr[256];
8259 + snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
8260 + pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
8261 + }
8262 if (option_verbose > 2)
8263 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
8264 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
8265 + }
8266
8267 #ifdef SUPPORT_USERUSER
8268 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
8269 @@ -8870,8 +10033,20 @@
8270
8271 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8272 } else {
8273 - ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
8274 - PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
8275 + struct zt_holded_call *onhold = NULL;
8276 + /* check calls on hold */
8277 + onhold = pri_get_callonhold(pri, e->hangup.cref, e->hangup.tei);
8278 +
8279 + if (onhold) {
8280 + // ast_log(LOG_NOTICE, "hangup, found cref %d, tei %d\n",e->hangup.cref, e->hangup.tei);
8281 + pri_hangup(pri->pri, onhold->call, e->hangup.cause, -1);
8282 + pri_destroy_callonhold(pri, onhold);
8283 + onhold = NULL;
8284 + } else {
8285 + ast_log(LOG_NOTICE, "Hangup, did not find cref %d, tei %d\n",e->hangup.cref, e->hangup.tei);
8286 + ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
8287 + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
8288 + }
8289 }
8290 }
8291 break;
8292 @@ -8881,17 +10056,25 @@
8293 case PRI_EVENT_HANGUP_REQ:
8294 chanpos = pri_find_principle(pri, e->hangup.channel);
8295 if (chanpos < 0) {
8296 - ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
8297 - PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
8298 + if (pri->nodetype == BRI_NETWORK_PTMP) {
8299 + pri_hangup(pri->pri, e->hangup.call, e->hangup.cause, -1);
8300 + } else {
8301 + ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
8302 + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
8303 + }
8304 chanpos = -1;
8305 }
8306 - if (chanpos > -1) {
8307 + /* dont hang up if we want to hear inband call progress */
8308 + if ((chanpos > -1) && ((pri->pvts[chanpos]->priindication_oob != 2) || (!e->hangup.inband_progress) || (!pri->pvts[chanpos]->outgoing))){
8309 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
8310 if (chanpos > -1) {
8311 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8312 if (pri->pvts[chanpos]->realcall)
8313 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8314 else if (pri->pvts[chanpos]->owner) {
8315 + char tmpstr[256];
8316 + snprintf(tmpstr, sizeof(tmpstr), "%d", e->hangup.cause);
8317 + pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "PRI_CAUSE", tmpstr);
8318 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
8319 switch(e->hangup.cause) {
8320 case PRI_CAUSE_USER_BUSY:
8321 @@ -8910,20 +10093,87 @@
8322 }
8323 if (option_verbose > 2)
8324 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);
8325 - if (e->hangup.aoc_units > -1)
8326 - if (option_verbose > 2)
8327 - ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
8328 - pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
8329 + if (e->hangup.aoc_units > -1) {
8330 + if (pri->pvts[chanpos]->owner) {
8331 + char tmpstr[256];
8332 + snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
8333 + pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
8334 + }
8335 + if (option_verbose > 2)
8336 + ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
8337 + pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
8338 + }
8339 + if (pri->nodetype == BRI_NETWORK_PTMP) {
8340 + // check for bri transfers, not everybody uses ECT...
8341 + if (pri->pvts[chanpos]->owner) {
8342 + // find on hold call
8343 + struct zt_holded_call *onhold = NULL;
8344 + struct ast_channel *transferee = NULL;
8345 + int transfer_ok = 0;
8346 +
8347 + onhold = pri_get_callonhold(pri, -1, e->hangup.tei);
8348 +
8349 + if (onhold) {
8350 + if (pri->pvts[chanpos]->pritransfer == 2) {
8351 + 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))))) {
8352 + transferee = ast_get_holded_call(onhold->uniqueid);
8353 +
8354 + if (transferee) {
8355 + if (pri->pvts[chanpos]->owner->_state == AST_STATE_RINGING) {
8356 + ast_indicate(transferee, AST_CONTROL_RINGING);
8357 + }
8358 +
8359 + pri->pvts[chanpos]->owner->_softhangup &= ~AST_SOFTHANGUP_DEV;
8360 +
8361 + ast_mutex_unlock(&transferee->lock);
8362 + if (ast_channel_masquerade(pri->pvts[chanpos]->owner, transferee)) {
8363 + ast_log(LOG_WARNING, "unable to masquerade\n");
8364 + } else {
8365 + /* beware of zombies!!! */
8366 + ast_set_flag(transferee, AST_FLAG_ZOMBIE);
8367 + pri->pvts[chanpos]->owner = NULL;
8368 + pri->pvts[chanpos]->tei = -1;
8369 + transfer_ok = 1;
8370 + }
8371 + }
8372 + }
8373 + } else if (pri->pvts[chanpos]->pritransfer == 0) {
8374 + ast_log(LOG_NOTICE, "killing channel %s \n", onhold->uniqueid);
8375 + ast_retrieve_call_to_death(onhold->uniqueid);
8376 + transfer_ok = 1;
8377 + } else if (pri->pvts[chanpos]->pritransfer == 1) {
8378 + /* we use ECT transfers, so just ignore this */
8379 + transfer_ok = 0;
8380 + }
8381 +
8382 + if (transfer_ok) {
8383 + onhold->alreadyhungup = 1;
8384 + pri_hangup(pri->pri, onhold->call, e->hangup.cause, -1);
8385 + onhold = NULL;
8386 + }
8387 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8388 + break;
8389 + } else {
8390 + pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
8391 + pri->pvts[chanpos]->call = NULL;
8392 + pri->pvts[chanpos]->tei = -1;
8393 + }
8394 + }
8395 + }
8396 } else {
8397 - pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
8398 + pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
8399 pri->pvts[chanpos]->call = NULL;
8400 + pri->pvts[chanpos]->tei = -1;
8401 }
8402 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
8403 - if (option_verbose > 2)
8404 - ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
8405 - PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
8406 - pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
8407 - pri->pvts[chanpos]->resetting = 1;
8408 + if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
8409 + if (option_verbose > 2)
8410 + ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
8411 + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
8412 + pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
8413 + pri->pvts[chanpos]->resetting = 1;
8414 + }
8415 +
8416 }
8417
8418 #ifdef SUPPORT_USERUSER
8419 @@ -8934,9 +10184,36 @@
8420
8421 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8422 } else {
8423 - 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);
8424 + if (pri->nodetype != BRI_NETWORK_PTMP) {
8425 + 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);
8426 + } else {
8427 + // check holded_calls!!!
8428 + struct zt_holded_call *onhold = NULL;
8429 +
8430 + onhold = pri_get_callonhold(pri, e->hangup.cref, e->hangup.tei);
8431 +
8432 + if (onhold) {
8433 + pri_hangup(pri->pri, e->hangup.call, e->hangup.cause, -1);
8434 + ast_retrieve_call_to_death(onhold->uniqueid);
8435 + pri_destroy_callonhold(pri, onhold);
8436 + onhold = NULL;
8437 + } else {
8438 + 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);
8439 + }
8440 + }
8441 }
8442 }
8443 + if ((chanpos > -1) && (pri->pvts[chanpos]->owner) && (pri->pvts[chanpos]->priindication_oob == 2) && (e->hangup.inband_progress) && (pri->pvts[chanpos]->outgoing)) {
8444 + if (e->hangup.aoc_units > -1) {
8445 + char tmpstr[256];
8446 + snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
8447 + pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
8448 + if (option_verbose > 2)
8449 + ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
8450 + pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
8451 + }
8452 + ast_channel_setwhentohangup(pri->pvts[chanpos]->owner, 5);
8453 + }
8454 break;
8455 case PRI_EVENT_HANGUP_ACK:
8456 chanpos = pri_find_principle(pri, e->hangup.channel);
8457 @@ -8950,6 +10227,7 @@
8458 if (chanpos > -1) {
8459 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8460 pri->pvts[chanpos]->call = NULL;
8461 + pri->pvts[chanpos]->tei = -1;
8462 pri->pvts[chanpos]->resetting = 0;
8463 if (pri->pvts[chanpos]->owner) {
8464 if (option_verbose > 2)
8465 @@ -8963,7 +10241,9 @@
8466 #endif
8467
8468 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8469 + }
8470 }
8471 + }
8472 }
8473 break;
8474 case PRI_EVENT_CONFIG_ERR:
8475 @@ -9030,7 +10310,7 @@
8476 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
8477 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
8478 } else {
8479 - chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
8480 + chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
8481 if (chanpos > -1) {
8482 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8483 pri->pvts[chanpos]->setup_ack = 1;
8484 @@ -9055,10 +10335,22 @@
8485 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8486 switch(e->notify.info) {
8487 case PRI_NOTIFY_REMOTE_HOLD:
8488 + if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
8489 + ast_log(LOG_DEBUG, "Received REMOTE_HOLD notification on NETWORK channel. Starting MoH\n");
8490 + ast_moh_start(ast_bridged_channel(pri->pvts[chanpos]->owner), NULL);
8491 + } else {
8492 + ast_log(LOG_DEBUG, "Received REMOTE_HOLD notification on CPE channel. Not Starting MoH\n");
8493 + }
8494 f.subclass = AST_CONTROL_HOLD;
8495 zap_queue_frame(pri->pvts[chanpos], &f, pri);
8496 break;
8497 case PRI_NOTIFY_REMOTE_RETRIEVAL:
8498 + if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
8499 + ast_log(LOG_DEBUG, "Received REMOTE_RETRIEVAL notification on NETWORK channel. Stopping MoH\n");
8500 + ast_moh_stop(ast_bridged_channel(pri->pvts[chanpos]->owner));
8501 + } else {
8502 + ast_log(LOG_DEBUG, "Received REMOTE_RETRIEVAL notification on CPE channel.\n");
8503 + }
8504 f.subclass = AST_CONTROL_UNHOLD;
8505 zap_queue_frame(pri->pvts[chanpos], &f, pri);
8506 break;
8507 @@ -9066,6 +10358,77 @@
8508 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8509 }
8510 break;
8511 + case PRI_EVENT_FACILITY:
8512 + if (e->facility.operation == 0x06) {
8513 + struct ast_channel *chan = NULL;
8514 + struct zt_holded_call *onhold = NULL;
8515 + if (option_verbose > 2) {
8516 + ast_verbose(VERBOSE_PREFIX_3 "ECT requested by TEI %d for cref %d\n", e->facility.tei, e->facility.cref);
8517 + }
8518 + /* search for cref/tei in held calls */
8519 + onhold = pri_get_callonhold(pri, e->facility.cref, e->facility.tei);
8520 + if (onhold) {
8521 + chan = ast_get_holded_call(onhold->uniqueid);
8522 + onhold->alreadyhungup = 1;
8523 + onhold = NULL;
8524 + if (!chan) {
8525 + /* hang up */
8526 + pri_hangup(pri->pri, e->facility.call, 16, -1);
8527 + break;
8528 + }
8529 + } else {
8530 + /* unknown cref/tei */
8531 + ast_log(LOG_WARNING, "did not find call on hold for cref %d tei %d\n", e->facility.tei, e->facility.cref);
8532 + /* hang up */
8533 + pri_hangup(pri->pri, e->facility.call, 16, -1);
8534 + break;
8535 + }
8536 +
8537 + /* find an active call for the same tei */
8538 + chanpos = pri_find_tei(pri, e->facility.call, e->facility.tei);
8539 + if (chanpos < 0) {
8540 + /* did not find active call, hangup call on hold */
8541 + if (chan) {
8542 + ast_hangup(chan);
8543 + chan = NULL;
8544 + }
8545 + } else {
8546 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
8547 + /* transfer */
8548 + if (pri->pvts[chanpos]->owner) {
8549 + if (option_verbose > 3) {
8550 + ast_verbose(VERBOSE_PREFIX_3 "ECT: found %s on channel %d for tei %d\n", pri->pvts[chanpos]->owner->name ,chanpos, e->facility.tei);
8551 + }
8552 + /* pass callprogress if the channel is not up yet */
8553 + if (pri->pvts[chanpos]->owner->_state == AST_STATE_RINGING) {
8554 + ast_indicate(chan, AST_CONTROL_RINGING);
8555 + }
8556 + /* unlock the channel we removed from hold */
8557 + ast_mutex_unlock(&chan->lock);
8558 + if (ast_channel_masquerade(pri->pvts[chanpos]->owner, chan)) {
8559 + ast_log(LOG_WARNING, "unable to masquerade\n");
8560 + } else {
8561 + /* beware of zombies !!! */
8562 + ast_set_flag(chan, AST_FLAG_ZOMBIE);
8563 + // chan->zombie = 1;
8564 + }
8565 + }
8566 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8567 + }
8568 + /* disconnect */
8569 + pri_hangup(pri->pri, e->facility.call, 16, -1);
8570 + } else if (e->facility.operation == 0x0D) {
8571 + ast_log(LOG_NOTICE, "call deflection to %s requested.\n", e->facility.forwardnum);
8572 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
8573 + /* transfer */
8574 + if (pri->pvts[chanpos]->owner) {
8575 + 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);
8576 + }
8577 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8578 + } else {
8579 + ast_log(LOG_WARNING, "Unknown facility operation %#x requested.\n", e->facility.operation);
8580 + }
8581 + break;
8582 default:
8583 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
8584 }
8585 @@ -9127,7 +10490,7 @@
8586 pri->fds[i] = -1;
8587 return -1;
8588 }
8589 - pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
8590 + pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype, pri->span);
8591 /* Force overlap dial if we're doing GR-303! */
8592 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
8593 pri->overlapdial = 1;
8594 @@ -9196,39 +10559,77 @@
8595
8596 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
8597 {
8598 - int myfd;
8599 + int myfd, x, d;
8600 + int span;
8601 +
8602 + if (argc < 6)
8603 + return RESULT_SHOWUSAGE;
8604
8605 if (!strncasecmp(argv[1], "set", 3)) {
8606 - if (argc < 5)
8607 + if (argc < 7)
8608 return RESULT_SHOWUSAGE;
8609
8610 - if (ast_strlen_zero(argv[4]))
8611 + if (!argv[4] || ast_strlen_zero(argv[4]))
8612 return RESULT_SHOWUSAGE;
8613
8614 + if (!argv[5])
8615 + return RESULT_SHOWUSAGE;
8616 +
8617 + if (!argv[6] || ast_strlen_zero(argv[6]))
8618 + return RESULT_SHOWUSAGE;
8619 +
8620 + span = atoi(argv[6]);
8621 + if ((span < 1) && (span > NUM_SPANS)) {
8622 + return RESULT_SUCCESS;
8623 + }
8624 +
8625 +
8626 myfd = open(argv[4], O_CREAT|O_WRONLY);
8627 if (myfd < 0) {
8628 - ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
8629 - return RESULT_SUCCESS;
8630 + ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
8631 + return RESULT_SUCCESS;
8632 }
8633 -
8634 - ast_mutex_lock(&pridebugfdlock);
8635 -
8636 - if (pridebugfd >= 0)
8637 - close(pridebugfd);
8638 -
8639 - pridebugfd = myfd;
8640 - ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
8641 -
8642 - ast_mutex_unlock(&pridebugfdlock);
8643 -
8644 - ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
8645 + for (x=0; x < NUM_SPANS; x++) {
8646 + ast_mutex_lock(&pris[x].lock);
8647 +
8648 + if (pris[x].span == span) {
8649 + if (pris[x].debugfd >= 0)
8650 + close(pris[x].debugfd);
8651 + pris[x].debugfd = myfd;
8652 + for (d=0; d < NUM_DCHANS; d++) {
8653 + if (pris[x].dchans[d])
8654 + pri_set_debug_fd(pris[x].dchans[d], myfd);
8655 + }
8656 + }
8657 + ast_mutex_unlock(&pris[x].lock);
8658 + }
8659 +
8660 + ast_cli(fd, "PRI debug output for span %d will be sent to '%s'\n", span, argv[4]);
8661 } else {
8662 + if (!argv[5] || ast_strlen_zero(argv[5]))
8663 + return RESULT_SHOWUSAGE;
8664 /* Assume it is unset */
8665 - ast_mutex_lock(&pridebugfdlock);
8666 - close(pridebugfd);
8667 - pridebugfd = -1;
8668 - ast_cli(fd, "PRI debug output to file disabled\n");
8669 - ast_mutex_unlock(&pridebugfdlock);
8670 + span = atoi(argv[5]);
8671 + if ((span < 1) && (span > NUM_SPANS)) {
8672 + return RESULT_SUCCESS;
8673 + }
8674 +
8675 + for (x=0; x < NUM_SPANS; x++) {
8676 + ast_mutex_lock(&pris[x].lock);
8677 +
8678 + if (pris[x].span == span) {
8679 + if (pris[x].debugfd >= 0)
8680 + close(pris[x].debugfd);
8681 + pris[x].debugfd = -1;
8682 + for (d=0; d < NUM_DCHANS; d++) {
8683 + if (pris[x].dchans[d])
8684 + pri_set_debug_fd(pris[x].dchans[d], -1);
8685 + }
8686 + }
8687 + ast_mutex_unlock(&pris[x].lock);
8688 + }
8689 +
8690 + ast_cli(fd, "PRI debug output to file for span %d disabled\n", span);
8691 }
8692
8693 return RESULT_SUCCESS;
8694 @@ -9260,6 +10661,7 @@
8695
8696
8697
8698 +
8699 static int handle_pri_no_debug(int fd, int argc, char *argv[])
8700 {
8701 int span;
8702 @@ -9366,36 +10768,6 @@
8703 return RESULT_SUCCESS;
8704 }
8705
8706 -static int handle_pri_show_debug(int fd, int argc, char *argv[])
8707 -{
8708 - int x;
8709 - int span;
8710 - int count=0;
8711 - int debug=0;
8712 -
8713 - for(span=0;span<NUM_SPANS;span++) {
8714 - if (pris[span].pri) {
8715 - for(x=0;x<NUM_DCHANS;x++) {
8716 - debug=0;
8717 - if (pris[span].dchans[x]) {
8718 - debug = pri_get_debug(pris[span].dchans[x]);
8719 - 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" );
8720 - count++;
8721 - }
8722 - }
8723 - }
8724 -
8725 - }
8726 - ast_mutex_lock(&pridebugfdlock);
8727 - if (pridebugfd >= 0)
8728 - ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
8729 - ast_mutex_unlock(&pridebugfdlock);
8730 -
8731 - if (!count)
8732 - ast_cli(fd, "No debug set or no PRI running\n");
8733 - return RESULT_SUCCESS;
8734 -}
8735 -
8736 static char pri_debug_help[] =
8737 "Usage: pri debug span <span>\n"
8738 " Enables debugging on a given PRI span\n";
8739 @@ -9412,6 +10784,18 @@
8740 "Usage: pri show span <span>\n"
8741 " Displays PRI Information\n";
8742
8743 +static char bri_debug_help[] =
8744 + "Usage: bri debug span <span>\n"
8745 + " Enables debugging on a given BRI span\n";
8746 +
8747 +static char bri_no_debug_help[] =
8748 + "Usage: bri no debug span <span>\n"
8749 + " Disables debugging on a given BRI span\n";
8750 +
8751 +static char bri_really_debug_help[] =
8752 + "Usage: bri intensive debug span <span>\n"
8753 + " Enables debugging down to the Q.921 level\n";
8754 +
8755 static struct ast_cli_entry zap_pri_cli[] = {
8756 { { "pri", "debug", "span", NULL }, handle_pri_debug,
8757 "Enables PRI debugging on a span", pri_debug_help, complete_span_4 },
8758 @@ -9419,19 +10803,207 @@
8759 "Disables PRI debugging on a span", pri_no_debug_help, complete_span_5 },
8760 { { "pri", "intense", "debug", "span", NULL }, handle_pri_really_debug,
8761 "Enables REALLY INTENSE PRI debugging", pri_really_debug_help, complete_span_5 },
8762 + { { "bri", "debug", "span", NULL }, handle_pri_debug,
8763 + "Enables BRI debugging on a span", bri_debug_help, complete_span_4 },
8764 + { { "bri", "no", "debug", "span", NULL }, handle_pri_no_debug,
8765 + "Disables BRI debugging on a span", bri_no_debug_help, complete_span_5 },
8766 + { { "bri", "intense", "debug", "span", NULL }, handle_pri_really_debug,
8767 + "Enables REALLY INTENSE BRI debugging", bri_really_debug_help, complete_span_5 },
8768 { { "pri", "show", "span", NULL }, handle_pri_show_span,
8769 "Displays PRI Information", pri_show_span_help, complete_span_4 },
8770 - { { "pri", "show", "debug", NULL }, handle_pri_show_debug,
8771 - "Displays current PRI debug settings" },
8772 { { "pri", "set", "debug", "file", NULL }, handle_pri_set_debug_file,
8773 "Sends PRI debug output to the specified file" },
8774 - { { "pri", "unset", "debug", "file", NULL }, handle_pri_set_debug_file,
8775 + { { "pri", "unset", "debug", "file", "span", NULL }, handle_pri_set_debug_file,
8776 "Ends PRI debug output to file" },
8777 };
8778
8779 +static int app_zapCD(struct ast_channel *chan, void *data)
8780 +{
8781 + struct zt_pvt *p = chan->tech_pvt;
8782 +
8783 + if(!data) {
8784 + ast_log(LOG_WARNING, "zapCD wants a number to deflect to\n");
8785 + return -1;
8786 + }
8787 + return pri_deflect(p->pri->pri, p->call, data);
8788 +}
8789 +
8790 +static char *zapCD_tdesc = "Call Deflection";
8791 +static char *zapCD_app = "zapCD";
8792 +static char *zapCD_synopsis = "Call Deflection";
8793 #endif /* ZAPATA_PRI */
8794
8795
8796 +#ifdef ZAPATA_GSM
8797 +
8798 +static char gsm_send_pdu_help[] =
8799 + "Usage: gsm send pdu <channel> <length> <pdu>\n"
8800 + " Sends a PDU on a GSM channel\n";
8801 +
8802 +
8803 +static int handle_gsm_send_pdu(int fd, int argc, char *argv[])
8804 +{
8805 +/* gsm send sms <channel> <destination> <message> */
8806 + int channel;
8807 + int len;
8808 + struct zt_pvt *pvt = NULL;
8809 + if (argc < 6) {
8810 + return RESULT_SHOWUSAGE;
8811 + }
8812 + channel = atoi(argv[3]);
8813 + if (channel < 1) {
8814 + ast_cli(fd, "Invalid channel %s. Should be a number.\n", argv[3]);
8815 + return RESULT_SUCCESS;
8816 + }
8817 + len = atoi(argv[4]);
8818 + if (len < 1) {
8819 + ast_cli(fd, "Invalid length %s. Should be a number.\n", argv[4]);
8820 + return RESULT_SUCCESS;
8821 + }
8822 + pvt = iflist;
8823 + while (pvt) {
8824 + if (pvt->channel == channel) {
8825 + if (pvt->owner) {
8826 + ast_cli(fd, "Channel in use.\n");
8827 + return RESULT_FAILURE;
8828 + } else {
8829 + ast_mutex_lock(&pvt->lock);
8830 + gsm_sms_send_pdu(pvt->gsm.modul, argv[5], len);
8831 + ast_mutex_unlock(&pvt->lock);
8832 + return RESULT_SUCCESS;
8833 + }
8834 + }
8835 + pvt = pvt->next;
8836 + }
8837 +
8838 + return RESULT_SUCCESS;
8839 +}
8840 +
8841 +static struct ast_cli_entry gsm_send_pdu = {
8842 + { "gsm", "send", "pdu", NULL }, handle_gsm_send_pdu, "Sends a SM on a GSM channel", gsm_send_pdu_help, complete_span_4 };
8843 +
8844 +
8845 +static char gsm_send_sms_help[] =
8846 + "Usage: gsm send sms <channel> <destination> <message>\n"
8847 + " Sends a SM on a GSM channel\n";
8848 +
8849 +
8850 +static int handle_gsm_send_sms(int fd, int argc, char *argv[])
8851 +{
8852 +/* gsm send sms <channel> <destination> <message> */
8853 + int channel;
8854 + struct zt_pvt *pvt = NULL;
8855 + if (argc < 6) {
8856 + return RESULT_SHOWUSAGE;
8857 + }
8858 + channel = atoi(argv[3]);
8859 + if (channel < 1) {
8860 + ast_cli(fd, "Invalid channel %s. Should be a number.\n", argv[3]);
8861 + return RESULT_SUCCESS;
8862 + }
8863 + pvt = iflist;
8864 + while (pvt) {
8865 + if (pvt->channel == channel) {
8866 + if (pvt->owner) {
8867 + ast_cli(fd, "Channel in use.\n");
8868 + return RESULT_FAILURE;
8869 + } else {
8870 + ast_mutex_lock(&pvt->lock);
8871 + gsm_sms_send_text(pvt->gsm.modul, argv[4], argv[5]);
8872 + ast_mutex_unlock(&pvt->lock);
8873 + return RESULT_SUCCESS;
8874 + }
8875 + }
8876 + pvt = pvt->next;
8877 + }
8878 +
8879 + return RESULT_SUCCESS;
8880 +}
8881 +
8882 +static struct ast_cli_entry gsm_send_sms = {
8883 + { "gsm", "send", "sms", NULL }, handle_gsm_send_sms, "Sends a SM on a GSM channel", gsm_send_sms_help, complete_span_4 };
8884 +
8885 +static char gsm_show_status_help[] =
8886 + "Usage: gsm show status <channel>>\n"
8887 + " Displays status information about the GSM channel.\n";
8888 +
8889 +
8890 +static int handle_gsm_show_status(int fd, int argc, char *argv[])
8891 +{
8892 + int channel;
8893 + struct zt_pvt *pvt = NULL;
8894 + if (argc < 4) {
8895 + return RESULT_SHOWUSAGE;
8896 + }
8897 + channel = atoi(argv[3]);
8898 + if (channel < 1) {
8899 + ast_cli(fd, "Invalid channel %s. Should be a number.\n", argv[3]);
8900 + return RESULT_SUCCESS;
8901 + }
8902 + pvt = iflist;
8903 + while (pvt) {
8904 + if (pvt->channel == channel) {
8905 + if (pvt->owner) {
8906 + ast_cli(fd, "Channel in use.\n");
8907 + return RESULT_FAILURE;
8908 + } else {
8909 + ast_mutex_lock(&pvt->lock);
8910 + gsm_request_status(pvt->gsm.modul);
8911 + ast_mutex_unlock(&pvt->lock);
8912 + return RESULT_SUCCESS;
8913 + }
8914 + }
8915 + pvt = pvt->next;
8916 + }
8917 +
8918 + return RESULT_SUCCESS;
8919 +}
8920 +
8921 +static struct ast_cli_entry gsm_show_status = {
8922 + { "gsm", "show", "status", NULL }, handle_gsm_show_status, "Displays status information about the GSM channel.", gsm_show_status_help, complete_span_4 };
8923 +
8924 +#endif /* ZAPATA_GSM */
8925 +
8926 +static int app_zapEC(struct ast_channel *chan, void *data)
8927 +{
8928 + int res=-1;
8929 + struct zt_pvt *p = NULL;
8930 +
8931 + if (!data) {
8932 + ast_log(LOG_WARNING, "zapEC requires one argument (on | off)\n");
8933 + }
8934 + if (chan && !strcasecmp("ZAP",chan->type)) {
8935 + p = chan->tech_pvt;
8936 + if (!p) return res;
8937 + if (!strcasecmp("on",(char *)data)) {
8938 + zt_enable_ec(p);
8939 + res = 0;
8940 + if (option_verbose > 3) {
8941 + ast_verbose(VERBOSE_PREFIX_3 "Enabled echo cancelation on channel %s.\n", chan->name);
8942 + }
8943 + } else if (!strcasecmp("off",(char *)data)) {
8944 + zt_disable_ec(p);
8945 + res = 0;
8946 + if (option_verbose > 3) {
8947 + ast_verbose(VERBOSE_PREFIX_3 "Disabled echo cancelation on channel %s.\n", chan->name);
8948 + }
8949 + } else {
8950 + ast_log(LOG_WARNING, "Unknown argument %s to zapEC\n", (char *)data);
8951 + }
8952 + } else {
8953 + ast_log(LOG_WARNING, "zapNoEC only works on ZAP channels, check your extensions.conf!\n");
8954 + res = 0;
8955 + }
8956 +
8957 + return res;
8958 +}
8959 +
8960 +static char *zapEC_tdesc = "Enable/disable Echo cancelation";
8961 +static char *zapEC_app = "zapEC";
8962 +static char *zapEC_synopsis = "Enable/Disable Echo Cancelation on a Zap channel";
8963 +
8964 +
8965 +
8966 #ifdef ZAPATA_R2
8967 static int handle_r2_no_debug(int fd, int argc, char *argv[])
8968 {
8969 @@ -10044,6 +11616,11 @@
8970 }
8971 ast_cli_unregister_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(zap_pri_cli[0]));
8972 #endif
8973 +#ifdef ZAPATA_GSM
8974 + ast_cli_unregister(&gsm_send_sms);
8975 + ast_cli_unregister(&gsm_send_pdu);
8976 + ast_cli_unregister(&gsm_show_status);
8977 +#endif
8978 #ifdef ZAPATA_R2
8979 ast_cli_unregister_multiple(zap_r2_cli, sizeof(zap_r2_cli) / sizeof(zap_r2_cli[0]));
8980 #endif
8981 @@ -10054,6 +11631,7 @@
8982 ast_manager_unregister( "ZapDNDoff" );
8983 ast_manager_unregister( "ZapDNDon" );
8984 ast_manager_unregister("ZapShowChannels");
8985 + ast_unregister_application(zapEC_app);
8986 ast_channel_unregister(&zap_tech);
8987 if (!ast_mutex_lock(&iflock)) {
8988 /* Hangup all interfaces if they have an owner */
8989 @@ -10412,8 +11990,8 @@
8990 }
8991 } else if (!strcasecmp(v->name, "echotraining")) {
8992 if (sscanf(v->value, "%d", &y) == 1) {
8993 - if ((y < 10) || (y > 4000)) {
8994 - ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 2000 ms at line %d\n", v->lineno);
8995 + if ((y < 10) || (y > 1000)) {
8996 + ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 1000 ms at line %d\n", v->lineno);
8997 } else {
8998 echotraining = y;
8999 }
9000 @@ -10599,12 +12177,33 @@
9001 cur_signalling = SIG_GR303FXSKS;
9002 cur_radio = 0;
9003 pritype = PRI_CPE;
9004 + } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
9005 + cur_radio = 0;
9006 + cur_signalling = SIG_PRI;
9007 + pritype = BRI_NETWORK_PTMP;
9008 + } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
9009 + cur_signalling = SIG_PRI;
9010 + cur_radio = 0;
9011 + pritype = BRI_CPE_PTMP;
9012 + } else if (!strcasecmp(v->value, "bri_net")) {
9013 + cur_radio = 0;
9014 + cur_signalling = SIG_PRI;
9015 + pritype = BRI_NETWORK;
9016 + } else if (!strcasecmp(v->value, "bri_cpe")) {
9017 + cur_signalling = SIG_PRI;
9018 + cur_radio = 0;
9019 + pritype = BRI_CPE;
9020 #endif
9021 #ifdef ZAPATA_R2
9022 } else if (!strcasecmp(v->value, "r2")) {
9023 cur_signalling = SIG_R2;
9024 cur_radio = 0;
9025 #endif
9026 +#ifdef ZAPATA_GSM
9027 + } else if (!strcasecmp(v->value, "gsm")) {
9028 + cur_signalling = SIG_GSM;
9029 + cur_radio = 0;
9030 +#endif
9031 } else {
9032 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
9033 }
9034 @@ -10687,8 +12286,20 @@
9035 priindication_oob = 1;
9036 else if (!strcasecmp(v->value, "inband"))
9037 priindication_oob = 0;
9038 + else if (!strcasecmp(v->value, "passthrough"))
9039 + priindication_oob = 2;
9040 else
9041 - ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
9042 + ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' , 'outofband' or 'passthrough' at line %d\n",
9043 + v->value, v->lineno);
9044 + } else if (!strcasecmp(v->name, "pritransfer")) {
9045 + if (!strcasecmp(v->value, "no"))
9046 + pritransfer = 0;
9047 + else if (!strcasecmp(v->value, "ect"))
9048 + pritransfer = 1;
9049 + else if (!strcasecmp(v->value, "hangup"))
9050 + pritransfer = 2;
9051 + else
9052 + ast_log(LOG_WARNING, "'%s' is not a valid pri transfer value, should be 'no' , 'ect' or 'hangup' at line %d\n",
9053 v->value, v->lineno);
9054 } else if (!strcasecmp(v->name, "priexclusive")) {
9055 cur_priexclusive = ast_true(v->value);
9056 @@ -10702,6 +12313,14 @@
9057 ast_copy_string(privateprefix, v->value, sizeof(privateprefix));
9058 } else if (!strcasecmp(v->name, "unknownprefix")) {
9059 ast_copy_string(unknownprefix, v->value, sizeof(unknownprefix));
9060 + } else if (!strcasecmp(v->name, "nocid")) {
9061 + ast_copy_string(nocid, v->value, sizeof(nocid) - 1);
9062 + } else if (!strcasecmp(v->name, "withheldcid")) {
9063 + ast_copy_string(withheldcid, v->value, sizeof(withheldcid) - 1);
9064 + } else if (!strcasecmp(v->name, "pin")) {
9065 + ast_copy_string(gsm_modem_pin, v->value, sizeof(gsm_modem_pin) - 1);
9066 + } else if (!strcasecmp(v->name, "exten")) {
9067 + ast_copy_string(gsm_modem_exten, v->value, sizeof(gsm_modem_exten) - 1);
9068 } else if (!strcasecmp(v->name, "resetinterval")) {
9069 if (!strcasecmp(v->value, "never"))
9070 resetinterval = -1;
9071 @@ -10716,6 +12335,8 @@
9072 ast_copy_string(idleext, v->value, sizeof(idleext));
9073 } else if (!strcasecmp(v->name, "idledial")) {
9074 ast_copy_string(idledial, v->value, sizeof(idledial));
9075 + } else if (!strcasecmp(v->name, "pritrustusercid")) {
9076 + usercid = ast_true(v->value);
9077 } else if (!strcasecmp(v->name, "overlapdial")) {
9078 overlapdial = ast_true(v->value);
9079 } else if (!strcasecmp(v->name, "pritimer")) {
9080 @@ -10901,6 +12522,7 @@
9081 #ifdef ZAPATA_PRI
9082 if (!reload) {
9083 for (x=0;x<NUM_SPANS;x++) {
9084 + pris[x].debugfd = -1;
9085 if (pris[x].pvts[0]) {
9086 if (start_pri(pris + x)) {
9087 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
9088 @@ -10933,6 +12555,10 @@
9089 pri_set_error(zt_pri_error);
9090 pri_set_message(zt_pri_message);
9091 #endif
9092 +#ifdef ZAPATA_GSM
9093 + gsm_set_error(zt_gsm_error);
9094 + gsm_set_message(zt_gsm_message);
9095 +#endif
9096 res = setup_zap(0);
9097 /* Make sure we can register our Zap channel type */
9098 if(res) {
9099 @@ -10950,6 +12576,11 @@
9100 ast_cli_register_multiple(zap_r2_cli, sizeof(zap_r2_cli) / sizeof(zap_r2_cli[0]));
9101 #endif
9102 ast_cli_register_multiple(zap_cli, sizeof(zap_cli) / sizeof(zap_cli[0]));
9103 +#ifdef ZAPATA_GSM
9104 + ast_cli_register(&gsm_send_sms);
9105 + ast_cli_register(&gsm_send_pdu);
9106 + ast_cli_register(&gsm_show_status);
9107 +#endif
9108
9109 memset(round_robin, 0, sizeof(round_robin));
9110 ast_manager_register( "ZapTransfer", 0, action_transfer, "Transfer Zap Channel" );
9111 @@ -10958,11 +12589,46 @@
9112 ast_manager_register( "ZapDNDon", 0, action_zapdndon, "Toggle Zap channel Do Not Disturb status ON" );
9113 ast_manager_register( "ZapDNDoff", 0, action_zapdndoff, "Toggle Zap channel Do Not Disturb status OFF" );
9114 ast_manager_register("ZapShowChannels", 0, action_zapshowchannels, "Show status zapata channels");
9115 -
9116 + ast_register_application(zapEC_app, app_zapEC, zapEC_synopsis, zapEC_tdesc);
9117 +#ifdef ZAPATA_PRI
9118 + ast_register_application(zapCD_app, app_zapCD, zapCD_synopsis, zapCD_tdesc);
9119 +#endif
9120 return res;
9121 }
9122
9123 +#ifdef ZAPATA_PRI
9124 +static int zt_tdd_sendtext(struct ast_channel *c, const char *text);
9125 +
9126 +static int zt_pri_sendtext(struct ast_channel *c, const char *text) {
9127 + struct zt_pvt *p = c->tech_pvt;
9128 + if (!p) return -1;
9129 + if (!p->pri) return -1;
9130 + if (strlen(text)) {
9131 + if (p->pri) {
9132 + if (!pri_grab(p, p->pri)) {
9133 + // ast_log(LOG_NOTICE, "Sending Display IE '%s'\n", text);
9134 + pri_information_display(p->pri->pri,p->call,(char *)text);
9135 + pri_rel(p->pri);
9136 + } else ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
9137 + }
9138 + }
9139 + return 0;
9140 +}
9141 +
9142 +static int zt_sendtext(struct ast_channel *c, const char *text) {
9143 + struct zt_pvt *p = c->tech_pvt;
9144 + if (!p) return -1;
9145 + if (p->sig == SIG_PRI) {
9146 + return zt_pri_sendtext(c, text);
9147 + } else {
9148 + return zt_tdd_sendtext(c, text);
9149 + }
9150 +}
9151 +
9152 +static int zt_tdd_sendtext(struct ast_channel *c, const char *text)
9153 +#else
9154 static int zt_sendtext(struct ast_channel *c, const char *text)
9155 +#endif
9156 {
9157 #define END_SILENCE_LEN 400
9158 #define HEADER_MS 50
9159 @@ -10981,6 +12647,7 @@
9160 float scont = 0.0;
9161 int index;
9162
9163 +
9164 index = zt_get_index(c, p, 0);
9165 if (index < 0) {
9166 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
9167 diff -urN asterisk-1.2.7.1.orig/codecs/codec_ilbc.c asterisk-1.2.7.1/codecs/codec_ilbc.c
9168 --- asterisk-1.2.7.1.orig/codecs/codec_ilbc.c 2005-11-29 19:24:39.000000000 +0100
9169 +++ asterisk-1.2.7.1/codecs/codec_ilbc.c 2006-04-18 14:39:28.000000000 +0200
9170 @@ -49,7 +49,7 @@
9171 #include "slin_ilbc_ex.h"
9172 #include "ilbc_slin_ex.h"
9173
9174 -#define USE_ILBC_ENHANCER 0
9175 +#define USE_ILBC_ENHANCER 1
9176 #define ILBC_MS 30
9177 /* #define ILBC_MS 20 */
9178
9179 diff -urN asterisk-1.2.7.1.orig/configs/capi.conf.sample asterisk-1.2.7.1/configs/capi.conf.sample
9180 --- asterisk-1.2.7.1.orig/configs/capi.conf.sample 1970-01-01 01:00:00.000000000 +0100
9181 +++ asterisk-1.2.7.1/configs/capi.conf.sample 2006-04-18 14:39:28.000000000 +0200
9182 @@ -0,0 +1,44 @@
9183 +;
9184 +; CAPI config
9185 +;
9186 +;
9187 +[general]
9188 +nationalprefix=0
9189 +internationalprefix=00
9190 +rxgain=0.8
9191 +txgain=0.8
9192 +
9193 +[interfaces]
9194 +
9195 +; mode: ptmp (point-to-multipoint) or ptp (point-to-point)
9196 +isdnmode=ptmp
9197 +; allow incoming calls to this list of MSNs, * == any
9198 +incomingmsn=*
9199 +; capi controller number
9200 +controller=1
9201 +; dialout group
9202 +group=1
9203 +; enable/disable software dtmf detection, recommended for AVM cards
9204 +softdtmf=1
9205 +; accountcode to use in CDRs
9206 +accountcode=
9207 +; context for incoming calls
9208 +context=capi-in
9209 +; _VERY_PRIMITIVE_ echo suppression
9210 +;echosquelch=1
9211 +; EICON DIVA SERVER echo cancelation
9212 +;echocancel=yes
9213 +;echotail=64
9214 +; call group
9215 +;callgroup=1
9216 +; deflect incoming calls to 12345678 if all B channels are busy
9217 +;deflect=12345678
9218 +; number of concurrent calls on this controller (2 makes sense for single BRI)
9219 +devices => 2
9220 +
9221 +
9222 +;PointToPoint (55512-0)
9223 +;isdnmode=ptp
9224 +;msn=55512
9225 +;controller=2
9226 +;devices => 30
9227 diff -urN asterisk-1.2.7.1.orig/configs/modules.conf.sample asterisk-1.2.7.1/configs/modules.conf.sample
9228 --- asterisk-1.2.7.1.orig/configs/modules.conf.sample 2005-11-29 19:24:39.000000000 +0100
9229 +++ asterisk-1.2.7.1/configs/modules.conf.sample 2006-04-18 14:39:28.000000000 +0200
9230 @@ -51,3 +51,4 @@
9231 ; exported to modules loaded after them.
9232 ;
9233 [global]
9234 +chan_capi.so=yes
9235 diff -urN asterisk-1.2.7.1.orig/configs/watchdog.conf.sample asterisk-1.2.7.1/configs/watchdog.conf.sample
9236 --- asterisk-1.2.7.1.orig/configs/watchdog.conf.sample 1970-01-01 01:00:00.000000000 +0100
9237 +++ asterisk-1.2.7.1/configs/watchdog.conf.sample 2006-04-18 14:39:28.000000000 +0200
9238 @@ -0,0 +1,22 @@
9239 +;
9240 +; Configuration file for res_watchdog
9241 +;
9242 +; type = isdnguard | watchdog
9243 +; device = /dev/...
9244 +; interval = interval to trigger the watchdog in ms
9245 +
9246 +;[ISDNguard-direct]
9247 +;type = isdnguard
9248 +;device = /dev/ttyS0
9249 +;interval = 200
9250 +
9251 +;[ISDNguard-with-daemon]
9252 +;type = isdnguard
9253 +;device = /var/run/guard.ctl
9254 +;interval = 200
9255 +
9256 +;[kernel_watchdog]
9257 +;type = watchdog
9258 +;device = /dev/watchdog
9259 +;interval = 100
9260 +
9261 diff -urN asterisk-1.2.7.1.orig/configs/zapata.conf.sample asterisk-1.2.7.1/configs/zapata.conf.sample
9262 --- asterisk-1.2.7.1.orig/configs/zapata.conf.sample 2006-03-06 03:32:35.000000000 +0100
9263 +++ asterisk-1.2.7.1/configs/zapata.conf.sample 2006-04-18 14:39:28.000000000 +0200
9264 @@ -121,9 +121,20 @@
9265 ;
9266 ; outofband: Signal Busy/Congestion out of band with RELEASE/DISCONNECT
9267 ; inband: Signal Busy/Congestion using in-band tones
9268 +; passthrough: Listen to the telco
9269 ;
9270 ; priindication = outofband
9271 ;
9272 +; PRI/BRI transfers (HOLD -> SETUP -> ECT/Hangup)
9273 +;
9274 +; Configure how transfers are initiated. ECT should be preferred
9275 +;
9276 +; no: no transfers allowed (results in hangup)
9277 +; ect: use ECT (facility)
9278 +: hangup: transfer on hangup (if your phones dont support ECT)
9279 +;
9280 +; pritransfer = ect
9281 +;
9282 ; If you need to override the existing channels selection routine and force all
9283 ; PRI channels to be marked as exclusively selected, set this to yes.
9284 ; priexclusive = yes
9285 diff -urN asterisk-1.2.7.1.orig/db.c asterisk-1.2.7.1/db.c
9286 --- asterisk-1.2.7.1.orig/db.c 2006-01-09 19:09:53.000000000 +0100
9287 +++ asterisk-1.2.7.1/db.c 2006-04-18 14:39:28.000000000 +0200
9288 @@ -516,11 +516,18 @@
9289 struct ast_cli_entry cli_database_deltree =
9290 { { "database", "deltree", NULL }, database_deltree, "Removes database keytree/values", database_deltree_usage };
9291
9292 +static char mandescr_dbput[] =
9293 +"Description: Put a value into astdb\n"
9294 +"Variables: \n"
9295 +" Family: ...\n"
9296 +" Key: ...\n"
9297 +" Value: ...\n";
9298 +
9299 static int manager_dbput(struct mansession *s, struct message *m)
9300 {
9301 char *family = astman_get_header(m, "Family");
9302 char *key = astman_get_header(m, "Key");
9303 - char *val = astman_get_header(m, "Val");
9304 + char *val = astman_get_header(m, "Value");
9305 int res;
9306
9307 if (!strlen(family)) {
9308 @@ -545,6 +552,12 @@
9309 return 0;
9310 }
9311
9312 +static char mandescr_dbget[] =
9313 +"Description: Get a value from astdb\n"
9314 +"Variables: \n"
9315 +" Family: ...\n"
9316 +" Key: ...\n";
9317 +
9318 static int manager_dbget(struct mansession *s, struct message *m)
9319 {
9320 char *id = astman_get_header(m,"ActionID");
9321 @@ -574,7 +587,7 @@
9322 ast_cli(s->fd, "Event: DBGetResponse\r\n"
9323 "Family: %s\r\n"
9324 "Key: %s\r\n"
9325 - "Val: %s\r\n"
9326 + "Value: %s\r\n"
9327 "%s"
9328 "\r\n",
9329 family, key, tmp, idText);
9330 @@ -582,6 +595,39 @@
9331 return 0;
9332 }
9333
9334 +static char mandescr_dbdel[] =
9335 +"Description: remove value from astdb\n"
9336 +"Variables: \n"
9337 +" Family: ...\n"
9338 +" Key: ...\n";
9339 +
9340 +static int manager_dbdel(struct mansession *s, struct message *m)
9341 +{
9342 + char *family = astman_get_header(m, "Family");
9343 + char *key = astman_get_header(m, "Key");
9344 + char *id = astman_get_header(m,"ActionID");
9345 +
9346 + if (!strlen(family)) {
9347 + astman_send_error(s, m, "No family specified");
9348 + return 0;
9349 + }
9350 + if (!strlen(key)) {
9351 + astman_send_error(s, m, "No key specified");
9352 + return 0;
9353 + }
9354 +
9355 + if (ast_db_del(family, key)) {
9356 + ast_cli(s->fd, "Response: Failed\r\n");
9357 + } else {
9358 + ast_cli(s->fd, "Response: Success\r\n");
9359 + }
9360 + if (id && !ast_strlen_zero(id))
9361 + ast_cli(s->fd, "ActionID: %s\r\n",id);
9362 + ast_cli(s->fd, "\r\n");
9363 +
9364 + return 0;
9365 +}
9366 +
9367 int astdb_init(void)
9368 {
9369 dbinit();
9370 @@ -591,7 +637,8 @@
9371 ast_cli_register(&cli_database_put);
9372 ast_cli_register(&cli_database_del);
9373 ast_cli_register(&cli_database_deltree);
9374 - ast_manager_register("DBGet", EVENT_FLAG_SYSTEM, manager_dbget, "Get DB Entry");
9375 - ast_manager_register("DBPut", EVENT_FLAG_SYSTEM, manager_dbput, "Put DB Entry");
9376 + ast_manager_register("DBget", EVENT_FLAG_SYSTEM, manager_dbget, mandescr_dbget);
9377 + ast_manager_register("DBput", EVENT_FLAG_SYSTEM, manager_dbput, mandescr_dbput);
9378 + ast_manager_register("DBdel", EVENT_FLAG_SYSTEM, manager_dbdel, mandescr_dbdel);
9379 return 0;
9380 }
9381 diff -urN asterisk-1.2.7.1.orig/devicestate.c asterisk-1.2.7.1/devicestate.c
9382 --- asterisk-1.2.7.1.orig/devicestate.c 2006-02-10 21:38:59.000000000 +0100
9383 +++ asterisk-1.2.7.1/devicestate.c 2006-04-18 14:39:28.000000000 +0200
9384 @@ -62,6 +62,8 @@
9385
9386 struct state_change {
9387 AST_LIST_ENTRY(state_change) list;
9388 + char cid_num[AST_MAX_EXTENSION];
9389 + char cid_name[AST_MAX_EXTENSION];
9390 char device[1];
9391 };
9392
9393 @@ -177,7 +179,7 @@
9394 }
9395
9396 /*--- do_state_change: Notify callback watchers of change, and notify PBX core for hint updates */
9397 -static void do_state_change(const char *device)
9398 +static void do_state_change(const char *device, char *cid_num, char *cid_name)
9399 {
9400 int state;
9401 struct devstate_cb *devcb;
9402 @@ -188,13 +190,13 @@
9403
9404 AST_LIST_LOCK(&devstate_cbs);
9405 AST_LIST_TRAVERSE(&devstate_cbs, devcb, list)
9406 - devcb->callback(device, state, devcb->data);
9407 + devcb->callback(device, state, devcb->data, cid_num, cid_name);
9408 AST_LIST_UNLOCK(&devstate_cbs);
9409
9410 - ast_hint_state_changed(device);
9411 + ast_hint_state_changed(device, cid_num, cid_name);
9412 }
9413
9414 -static int __ast_device_state_changed_literal(char *buf)
9415 +static int __ast_device_state_changed_literal(char *buf, char *cid_num, char *cid_name)
9416 {
9417 char *device, *tmp;
9418 struct state_change *change = NULL;
9419 @@ -209,10 +211,16 @@
9420 if (!change) {
9421 /* we could not allocate a change struct, or */
9422 /* there is no background thread, so process the change now */
9423 - do_state_change(device);
9424 + do_state_change(device, cid_num, cid_name);
9425 } else {
9426 /* queue the change */
9427 strcpy(change->device, device);
9428 + if (cid_num && (!ast_strlen_zero(cid_num))) {
9429 + strncpy(change->cid_num, cid_num, sizeof(change->cid_num) - 1);
9430 + }
9431 + if (cid_name && (!ast_strlen_zero(cid_name))) {
9432 + strncpy(change->cid_name, cid_name, sizeof(change->cid_name) - 1);
9433 + }
9434 AST_LIST_LOCK(&state_changes);
9435 AST_LIST_INSERT_TAIL(&state_changes, change, list);
9436 if (AST_LIST_FIRST(&state_changes) == change)
9437 @@ -224,23 +232,49 @@
9438 return 1;
9439 }
9440
9441 -int ast_device_state_changed_literal(const char *dev)
9442 +int ast_device_state_changed_literal(const char *dev, const char *cid_num, const char *cid_name)
9443 {
9444 char *buf;
9445 + char *buf2 = NULL;
9446 + char *buf3 = NULL;
9447 buf = ast_strdupa(dev);
9448 - return __ast_device_state_changed_literal(buf);
9449 + if (cid_num)
9450 + buf2 = ast_strdupa(cid_num);
9451 + if (cid_name)
9452 + buf3 = ast_strdupa(cid_name);
9453 + return __ast_device_state_changed_literal(buf, buf2, buf3);
9454 }
9455
9456 /*--- ast_device_state_changed: Accept change notification, add it to change queue */
9457 int ast_device_state_changed(const char *fmt, ...)
9458 {
9459 char buf[AST_MAX_EXTENSION];
9460 + char cid_num[AST_MAX_EXTENSION];
9461 + char cid_name[AST_MAX_EXTENSION];
9462 + char *s = NULL;
9463 va_list ap;
9464
9465 va_start(ap, fmt);
9466 - vsnprintf(buf, sizeof(buf), fmt, ap);
9467 + if (*fmt == 's') {
9468 + s = va_arg(ap, char *);
9469 + snprintf(buf, sizeof(buf), s);
9470 + *fmt++;
9471 + if (*fmt == 's') {
9472 + s = va_arg(ap, char *);
9473 + if (s) {
9474 + snprintf(cid_num, sizeof(cid_num), s);
9475 + }
9476 + *fmt++;
9477 + if (*fmt == 's') {
9478 + s = va_arg(ap, char *);
9479 + if (s) {
9480 + snprintf(cid_name, sizeof(cid_name), s);
9481 + }
9482 + }
9483 + }
9484 + }
9485 va_end(ap);
9486 - return __ast_device_state_changed_literal(buf);
9487 + return __ast_device_state_changed_literal(buf, cid_num, cid_name);
9488 }
9489
9490 /*--- do_devstate_changes: Go through the dev state change queue and update changes in the dev state thread */
9491 @@ -255,7 +289,7 @@
9492 if (cur) {
9493 /* we got an entry, so unlock the list while we process it */
9494 AST_LIST_UNLOCK(&state_changes);
9495 - do_state_change(cur->device);
9496 + do_state_change(cur->device, cur->cid_num, cur->cid_name);
9497 free(cur);
9498 AST_LIST_LOCK(&state_changes);
9499 } else {
9500 diff -urN asterisk-1.2.7.1.orig/doc/README.asterisk.conf asterisk-1.2.7.1/doc/README.asterisk.conf
9501 --- asterisk-1.2.7.1.orig/doc/README.asterisk.conf 2005-11-29 19:24:39.000000000 +0100
9502 +++ asterisk-1.2.7.1/doc/README.asterisk.conf 2006-04-18 14:39:28.000000000 +0200
9503 @@ -62,6 +62,7 @@
9504 maxcalls = 255 ; The maximum number of concurrent calls you want to allow
9505 execincludes = yes | no ; Allow #exec entries in configuration files
9506 dontwarn = yes | no ; Don't over-inform the Asterisk sysadm, he's a guru
9507 +uniquename = asterisk ; host name part to be included in the uniqueid
9508
9509 [files]
9510 ; Changing the following lines may compromise your security
9511 diff -urN asterisk-1.2.7.1.orig/editline/cygdef.h asterisk-1.2.7.1/editline/cygdef.h
9512 --- asterisk-1.2.7.1.orig/editline/cygdef.h 1970-01-01 01:00:00.000000000 +0100
9513 +++ asterisk-1.2.7.1/editline/cygdef.h 2006-04-18 14:39:28.000000000 +0200
9514 @@ -0,0 +1,11 @@
9515 +/* cygdef.h. Generated automatically by configure. */
9516 +#ifndef _CYGDEF_H_
9517 +#define _CYGDEF_H_ 1
9518 +#include <sys/ioctl.h>
9519 +#define __linux__ 1
9520 +
9521 +
9522 +typedef void (*sig_t)(int);
9523 +
9524 +
9525 +#endif /* _CYGDEF_H_ */
9526 diff -urN asterisk-1.2.7.1.orig/include/asterisk/agi.h asterisk-1.2.7.1/include/asterisk/agi.h
9527 --- asterisk-1.2.7.1.orig/include/asterisk/agi.h 2005-11-29 19:24:39.000000000 +0100
9528 +++ asterisk-1.2.7.1/include/asterisk/agi.h 2006-04-18 14:39:28.000000000 +0200
9529 @@ -29,7 +29,8 @@
9530
9531 typedef struct agi_state {
9532 int fd; /* FD for general output */
9533 - int audio; /* FD for audio output */
9534 + int audio_out; /* FD for audio output */
9535 + int audio_in; /* FD for audio output */
9536 int ctrl; /* FD for input control */
9537 } AGI;
9538
9539 diff -urN asterisk-1.2.7.1.orig/include/asterisk/chan_capi.h asterisk-1.2.7.1/include/asterisk/chan_capi.h
9540 --- asterisk-1.2.7.1.orig/include/asterisk/chan_capi.h 1970-01-01 01:00:00.000000000 +0100
9541 +++ asterisk-1.2.7.1/include/asterisk/chan_capi.h 2006-04-18 14:39:28.000000000 +0200
9542 @@ -0,0 +1,276 @@
9543 +/*
9544 + * (CAPI*)
9545 + *
9546 + * An implementation of Common ISDN API 2.0 for Asterisk
9547 + *
9548 + * Copyright (C) 2002, 2003, 2004, Junghanns.NET GmbH
9549 + *
9550 + * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
9551 + *
9552 + * This program is free software and may be modified and
9553 + * distributed under the terms of the GNU Public License.
9554 + */
9555 +
9556 +#ifndef _ASTERISK_CAPI_H
9557 +#define _ASTERISK_CAPI_H
9558 +
9559 +#define AST_CAPI_MAX_CONTROLLERS 16
9560 +#define AST_CAPI_MAX_DEVICES 30
9561 +#define AST_CAPI_MAX_BUF 160
9562 +
9563 +#define AST_CAPI_MAX_B3_BLOCKS 7
9564 +
9565 +/* was : 130 bytes Alaw = 16.25 ms audio not suitable for VoIP */
9566 +/* now : 160 bytes Alaw = 20 ms audio */
9567 +/* you can tune this to your need. higher value == more latency */
9568 +#define AST_CAPI_MAX_B3_BLOCK_SIZE 160
9569 +
9570 +#define AST_CAPI_BCHANS 120
9571 +#define ALL_SERVICES 0x1FFF03FF
9572 +
9573 +/* duration in ms for sending and detecting dtmfs */
9574 +#define AST_CAPI_DTMF_DURATION 0x40
9575 +
9576 +#define AST_CAPI_NATIONAL_PREF "0"
9577 +#define AST_CAPI_INTERNAT_PREF "00"
9578 +
9579 +#ifdef CAPI_ES
9580 +#define ECHO_TX_COUNT 5 // 5 x 20ms = 100ms
9581 +#define ECHO_EFFECTIVE_TX_COUNT 3 // 2 x 20ms = 40ms == 40-100ms ... ignore first 40ms
9582 +#define ECHO_TXRX_RATIO 2.3 // if( rx < (txavg/ECHO_TXRX_RATIO) ) rx=0;
9583 +#endif
9584 +
9585 +/*
9586 + * state combination for a normal incoming call:
9587 + * DIS -> ALERT -> CON -> BCON -> CON -> DIS
9588 + *
9589 + * outgoing call:
9590 + * DIS -> CONP -> BCONNECTED -> CON -> DIS
9591 + */
9592 +
9593 +#define CAPI_STATE_ALERTING 1
9594 +#define CAPI_STATE_CONNECTED 2
9595 +#define CAPI_STATE_BCONNECTED 3
9596 +
9597 +#define CAPI_STATE_DISCONNECTING 4
9598 +#define CAPI_STATE_DISCONNECTED 5
9599 +#define CAPI_STATE_REMOTE_HANGUP 6
9600 +
9601 +#define CAPI_STATE_CONNECTPENDING 7
9602 +#define CAPI_STATE_ONHOLD 8
9603 +#define CAPI_STATE_NETWORKHANGUP 9
9604 +#define CAPI_STATE_ANSWERING 10
9605 +#define CAPI_STATE_PUTTINGONHOLD 11
9606 +#define CAPI_STATE_RETRIEVING 12
9607 +
9608 +#define CAPI_STATE_DID 13
9609 +
9610 +#define AST_CAPI_B3_DONT 0
9611 +#define AST_CAPI_B3_ALWAYS 1
9612 +#define AST_CAPI_B3_ON_SUCCESS 2
9613 +
9614 +#ifdef CAPI_GAIN
9615 +struct ast_capi_gains {
9616 + unsigned char txgains[256];
9617 + unsigned char rxgains[256];
9618 +};
9619 +#endif
9620 +
9621 +#define PRES_ALLOWED_USER_NUMBER_NOT_SCREENED 0x00
9622 +#define PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN 0x01
9623 +#define PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN 0x02
9624 +#define PRES_ALLOWED_NETWORK_NUMBER 0x03
9625 +#define PRES_PROHIB_USER_NUMBER_NOT_SCREENED 0x20
9626 +#define PRES_PROHIB_USER_NUMBER_PASSED_SCREEN 0x21
9627 +#define PRES_PROHIB_USER_NUMBER_FAILED_SCREEN 0x22
9628 +#define PRES_PROHIB_NETWORK_NUMBER 0x23
9629 +#define PRES_NUMBER_NOT_AVAILABLE 0x43
9630 +
9631 +
9632 +//! Private data for a capi device
9633 +struct ast_capi_pvt {
9634 + ast_mutex_t lock;
9635 + int fd;
9636 +
9637 + /*! Channel we belong to, possibly NULL */
9638 + struct ast_channel *owner;
9639 + /*! Frame */
9640 + struct ast_frame fr;
9641 +
9642 + char offset[AST_FRIENDLY_OFFSET];
9643 +
9644 + // capi message number
9645 + _cword MessageNumber;
9646 + int NCCI;
9647 + int PLCI;
9648 + /* on which controller we do live */
9649 + int controller;
9650 +
9651 + /* we could live on those */
9652 + unsigned long controllers;
9653 +
9654 + int datahandle;
9655 +
9656 + short buf[AST_CAPI_MAX_BUF];
9657 + int buflen;
9658 + /*! Immediate, or wait for an answer */
9659 + int mode;
9660 + /*! State of modem in miniature */
9661 + int state;
9662 + /*! Digits to strip on outgoing numbers */
9663 + int stripmsd;
9664 + /*! ringer timeout */
9665 + int ringt;
9666 + /*! actual time of last ring */
9667 + time_t lastring;
9668 + /*! dtmf receive state/data */
9669 + char dtmfrx;
9670 +
9671 + char context[AST_MAX_EXTENSION];
9672 + /*! Multiple Subscriber Number we listen to (, seperated list) */
9673 + char incomingmsn[AST_MAX_EXTENSION];
9674 + /*! Prefix to Build CID */
9675 + char prefix[AST_MAX_EXTENSION];
9676 + /*! Caller ID if available */
9677 + char cid[AST_MAX_EXTENSION];
9678 + /*! Dialed Number if available */
9679 + char dnid[AST_MAX_EXTENSION];
9680 +
9681 + char accountcode[20];
9682 +
9683 + unsigned int callgroup;
9684 + unsigned int group;
9685 +
9686 + /*! default language */
9687 + char language[MAX_LANGUAGE];
9688 + /*! Static response buffer */
9689 + char response[256];
9690 +
9691 + int calledPartyIsISDN;
9692 + // this is an outgoing channel
9693 + int outgoing;
9694 + // use CLIR
9695 + int CLIR;
9696 + // are we doing early B3 connect on this interface?
9697 + int earlyB3;
9698 + // should we do early B3 on this interface?
9699 + int doB3;
9700 + // store plci here for the call that is onhold
9701 + int onholdPLCI;
9702 + // do software dtmf detection
9703 + int doDTMF;
9704 + // CAPI echo cancellation
9705 + int doEC;
9706 + int ecOption;
9707 + int ecTail;
9708 + // isdnmode ptp or ptm
9709 + int isdnmode;
9710 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
9711 + // deflect on circuitbusy
9712 + char deflect2[AST_MAX_EXTENSION];
9713 +#endif
9714 +
9715 + // not all codecs supply frames in nice 320 byte chunks
9716 + struct ast_smoother *smoother;
9717 + // ok, we stop to be nice and give them the lowest possible latency 130 samples * 2 = 260 bytes */
9718 +#ifdef CAPI_SYNC
9719 + int B3in;
9720 + ast_mutex_t lockB3in;
9721 +#endif
9722 +
9723 + // do ECHO SURPRESSION
9724 + int doES;
9725 +#ifdef CAPI_ES
9726 + short txavg[ECHO_TX_COUNT];
9727 + float rxmin;
9728 + float txmin;
9729 +#endif
9730 +#ifdef CAPI_GAIN
9731 + struct ast_capi_gains g;
9732 +#endif
9733 + float txgain;
9734 + float rxgain;
9735 + struct ast_dsp *vad;
9736 +
9737 +
9738 + struct capi_pipe *mypipe;
9739 + /*! Next channel in list */
9740 + struct ast_capi_pvt *next;
9741 +};
9742 +
9743 +
9744 +struct ast_capi_profile {
9745 + unsigned short ncontrollers;
9746 + unsigned short nbchannels;
9747 + unsigned char globaloptions;
9748 + unsigned char globaloptions2;
9749 + unsigned char globaloptions3;
9750 + unsigned char globaloptions4;
9751 + unsigned int b1protocols;
9752 + unsigned int b2protocols;
9753 + unsigned int b3protocols;
9754 + unsigned int reserved3[6];
9755 + unsigned int manufacturer[5];
9756 +};
9757 +
9758 +struct capi_pipe {
9759 + // lock
9760 + ast_mutex_t lock;
9761 +
9762 + // fd for writing to the channel
9763 + int fd;
9764 +
9765 + // PLCI and NCCI of the B3 CON
9766 + int PLCI;
9767 + int NCCI;
9768 + // pointer to the interface
9769 + struct ast_capi_pvt *i;
9770 + // pointer to the channel
9771 + struct ast_channel *c;
9772 + // next pipe
9773 + struct capi_pipe *next;
9774 +};
9775 +
9776 +struct ast_capi_controller {
9777 + // which controller is this?
9778 + int controller;
9779 + // how many bchans?
9780 + int nbchannels;
9781 + // free bchans
9782 + int nfreebchannels;
9783 + // DID
9784 + int isdnmode;
9785 + // features:
9786 + int dtmf;
9787 + int echocancel;
9788 + int sservices; // supplementray services
9789 + // supported sservices:
9790 + int holdretrieve;
9791 + int terminalportability;
9792 + int ECT;
9793 + int threePTY;
9794 + int CF;
9795 + int CD;
9796 + int MCID;
9797 + int CCBS;
9798 + int MWI;
9799 + int CCNR;
9800 + int CONF;
9801 +};
9802 +
9803 +
9804 +// ETSI 300 102-1 information element identifiers
9805 +#define CAPI_ETSI_IE_CAUSE 0x08;
9806 +#define CAPI_ETSI_IE_PROGRESS_INDICATOR 0x1e;
9807 +#define CAPI_ETSI_IE_CALLED_PARTY_NUMBER 0x70;
9808 +
9809 +// ETIS 300 102-1 message types
9810 +#define CAPI_ETSI_ALERTING 0x01;
9811 +#define CAPI_ETSI_SETUP_ACKKNOWLEDGE 0x0d;
9812 +#define CAPI_ETSI_DISCONNECT 0x45;
9813 +
9814 +// ETSI 300 102-1 Numbering Plans
9815 +#define CAPI_ETSI_NPLAN_NATIONAL 0x20
9816 +#define CAPI_ETSI_NPLAN_INTERNAT 0x10
9817 +
9818 +#endif
9819 diff -urN asterisk-1.2.7.1.orig/include/asterisk/chan_capi_app.h asterisk-1.2.7.1/include/asterisk/chan_capi_app.h
9820 --- asterisk-1.2.7.1.orig/include/asterisk/chan_capi_app.h 1970-01-01 01:00:00.000000000 +0100
9821 +++ asterisk-1.2.7.1/include/asterisk/chan_capi_app.h 2006-04-18 14:39:28.000000000 +0200
9822 @@ -0,0 +1,30 @@
9823 +/*
9824 + * (CAPI*)
9825 + *
9826 + * An implementation of Common ISDN API 2.0 for Asterisk
9827 + *
9828 + * include file for helper applications
9829 + *
9830 + * Copyright (C) 2002, 2003, 2004, Junghanns.NET GmbH
9831 + *
9832 + * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
9833 + *
9834 + * This program is free software and may be modified and
9835 + * distributed under the terms of the GNU Public License.
9836 + */
9837 +
9838 +#ifndef _ASTERISK_CAPI_IF_H
9839 +#define _ASTERISK_CAPI_IF_H
9840 +
9841 +// exported symbols from chan_capi
9842 +
9843 +// important things we need
9844 +extern unsigned ast_capi_ApplID;
9845 +extern unsigned ast_capi_MessageNumber;
9846 +extern int capidebug;
9847 +
9848 +extern int capi_call(struct ast_channel *c, char *idest, int timeout);
9849 +extern int capi_detect_dtmf(struct ast_channel *c, int flag);
9850 +extern MESSAGE_EXCHANGE_ERROR _capi_put_cmsg(_cmsg *CMSG);
9851 +
9852 +#endif
9853 diff -urN asterisk-1.2.7.1.orig/include/asterisk/channel.h asterisk-1.2.7.1/include/asterisk/channel.h
9854 --- asterisk-1.2.7.1.orig/include/asterisk/channel.h 2006-02-11 19:15:00.000000000 +0100
9855 +++ asterisk-1.2.7.1/include/asterisk/channel.h 2006-04-18 14:39:28.000000000 +0200
9856 @@ -86,6 +86,9 @@
9857 #ifndef _ASTERISK_CHANNEL_H
9858 #define _ASTERISK_CHANNEL_H
9859
9860 +/* Max length of the uniqueid */
9861 +#define AST_MAX_UNIQUEID 64
9862 +
9863 #include <unistd.h>
9864 #include <setjmp.h>
9865 #ifdef POLLCOMPAT
9866 @@ -380,7 +383,7 @@
9867 unsigned int fout;
9868
9869 /* Unique Channel Identifier */
9870 - char uniqueid[32];
9871 + char uniqueid[AST_MAX_UNIQUEID];
9872
9873 /* Why is the channel hanged up */
9874 int hangupcause;
9875 @@ -397,6 +400,12 @@
9876 /*! ISDN Transfer Capbility - AST_FLAG_DIGITAL is not enough */
9877 unsigned short transfercapability;
9878
9879 + /*! ISDN Low Layer Compatibility */
9880 + char lowlayercompat[16];
9881 +
9882 + /*! ISDN High Layer Compatibility */
9883 + char highlayercompat[4];
9884 +
9885 struct ast_frame *readq;
9886 int alertpipe[2];
9887 /*! Write translation path */
9888 @@ -533,6 +542,11 @@
9889 #define AST_STATE_MUTE (1 << 16)
9890 /*! @} */
9891
9892 +extern ast_mutex_t uniquelock;
9893 +
9894 +/*! \brief Change the state of a channel and the callerid of the calling channel*/
9895 +int ast_setstate_and_cid(struct ast_channel *chan, int state, char *cid_num, char *cid_name);
9896 +
9897 /*! \brief Change the state of a channel */
9898 int ast_setstate(struct ast_channel *chan, int state);
9899
9900 @@ -569,7 +583,7 @@
9901 * by the low level module
9902 * \return Returns an ast_channel on success, NULL on failure.
9903 */
9904 -struct ast_channel *ast_request(const char *type, int format, void *data, int *status);
9905 +struct ast_channel *ast_request(const char *type, int format, void *data, int *status, char *uniqueid);
9906
9907 /*!
9908 * \brief Request a channel of a given type, with data as optional information used
9909 @@ -584,9 +598,9 @@
9910 * \return Returns an ast_channel on success or no answer, NULL on failure. Check the value of chan->_state
9911 * to know if the call was answered or not.
9912 */
9913 -struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, const char *cidnum, const char *cidname);
9914 +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);
9915
9916 -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);
9917 +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);
9918
9919 /*!\brief Register a channel technology (a new channel driver)
9920 * Called by a channel module to register the kind of channels it supports.
9921 @@ -839,6 +853,10 @@
9922 /*--- ast_get_channel_by_exten_locked: Get channel by exten (and optionally context) and lock it */
9923 struct ast_channel *ast_get_channel_by_exten_locked(const char *exten, const char *context);
9924
9925 +/*! Get channel by uniqueid (locks channel) */
9926 +struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid);
9927 +
9928 +
9929 /*! Waits for a digit */
9930 /*!
9931 * \param c channel to wait for a digit on
9932 @@ -909,6 +927,9 @@
9933 p->owner pointer) that is affected by the change. The physical layer of the original
9934 channel is hung up. */
9935 int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone);
9936 +int ast_channel_masquerade_locked(struct ast_channel *original, struct ast_channel *clone);
9937 +
9938 +char *ast_alloc_uniqueid(void);
9939
9940 /*! Gives the string form of a given cause code */
9941 /*!
9942 diff -urN asterisk-1.2.7.1.orig/include/asterisk/devicestate.h asterisk-1.2.7.1/include/asterisk/devicestate.h
9943 --- asterisk-1.2.7.1.orig/include/asterisk/devicestate.h 2005-11-29 19:24:39.000000000 +0100
9944 +++ asterisk-1.2.7.1/include/asterisk/devicestate.h 2006-04-18 14:39:28.000000000 +0200
9945 @@ -42,7 +42,7 @@
9946 /*! Device is ringing */
9947 #define AST_DEVICE_RINGING 6
9948
9949 -typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data);
9950 +typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data, char *cid_num, char *cid_name);
9951
9952 /*! \brief Convert device state to text string for output
9953 * \param devstate Current device state
9954 @@ -84,7 +84,7 @@
9955 * callbacks for the changed extensions
9956 * Returns 0 on success, -1 on failure
9957 */
9958 -int ast_device_state_changed_literal(const char *device);
9959 +int ast_device_state_changed_literal(const char *device, const char *cid_num, const char *cid_name);
9960
9961 /*! \brief Registers a device state change callback
9962 * \param callback Callback
9963 diff -urN asterisk-1.2.7.1.orig/include/asterisk/features.h asterisk-1.2.7.1/include/asterisk/features.h
9964 --- asterisk-1.2.7.1.orig/include/asterisk/features.h 2005-11-29 19:24:39.000000000 +0100
9965 +++ asterisk-1.2.7.1/include/asterisk/features.h 2006-04-18 14:39:28.000000000 +0200
9966 @@ -45,6 +45,8 @@
9967 };
9968
9969
9970 +extern int ast_autoanswer_login(struct ast_channel *chan, void *data);
9971 +extern int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data);
9972
9973 /*! \brief Park a call and read back parked location
9974 * \param chan the channel to actually be parked
9975 @@ -68,11 +70,19 @@
9976 */
9977 extern int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *host, int timeout, int *extout);
9978
9979 +extern int ast_hold_call(struct ast_channel *chan, struct ast_channel *host);
9980 +extern int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *host);
9981 +extern int ast_retrieve_call(struct ast_channel *chan, char *uniqueid);
9982 +extern int ast_retrieve_call_to_death(char *uniqueid);
9983 +extern struct ast_channel *ast_get_holded_call(char *uniqueid);
9984 +
9985 /*! \brief Determine system parking extension
9986 * Returns the call parking extension for drivers that provide special
9987 call parking help */
9988 extern char *ast_parking_ext(void);
9989
9990 +extern char *ast_parking_con(void);
9991 +
9992 /*! \brief Determine system call pickup extension */
9993 extern char *ast_pickup_ext(void);
9994
9995 @@ -92,4 +102,12 @@
9996 \param feature the ast_call_feature object which was registered before*/
9997 extern void ast_unregister_feature(struct ast_call_feature *feature);
9998
9999 +/*! \brief find a feature by name
10000 + \param name of the feature to be returned */
10001 +extern struct ast_call_feature *ast_find_feature(char *name);
10002 +
10003 +/*! \brief find a builtin feature by name
10004 + \param name of the feature to be returned */
10005 +extern struct ast_call_feature *ast_find_builtin_feature(char *name);
10006 +
10007 #endif /* _AST_FEATURES_H */
10008 diff -urN asterisk-1.2.7.1.orig/include/asterisk/pbx.h asterisk-1.2.7.1/include/asterisk/pbx.h
10009 --- asterisk-1.2.7.1.orig/include/asterisk/pbx.h 2006-03-29 21:11:18.000000000 +0200
10010 +++ asterisk-1.2.7.1/include/asterisk/pbx.h 2006-04-18 14:39:28.000000000 +0200
10011 @@ -57,7 +57,7 @@
10012 AST_EXTENSION_BUSY = 1 << 1,
10013 /*! All devices UNAVAILABLE/UNREGISTERED */
10014 AST_EXTENSION_UNAVAILABLE = 1 << 2,
10015 - /*! All devices RINGING */
10016 + /*! One or more devices RINGING */
10017 AST_EXTENSION_RINGING = 1 << 3,
10018 };
10019
10020 @@ -80,7 +80,7 @@
10021 struct ast_ignorepat;
10022 struct ast_sw;
10023
10024 -typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data);
10025 +typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data, char *cid_num, char *cid_name);
10026
10027 /*! Data structure associated with a custom function */
10028 struct ast_custom_function {
10029 @@ -156,6 +156,8 @@
10030 */
10031 extern struct ast_app *pbx_findapp(const char *app);
10032
10033 +void *ast_pbx_run_app(void *data);
10034 +
10035 /*! executes an application */
10036 /*!
10037 * \param c channel to execute on
10038 @@ -563,11 +565,11 @@
10039
10040 /* Synchronously or asynchronously make an outbound call and send it to a
10041 particular extension */
10042 -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);
10043 +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);
10044
10045 /* Synchronously or asynchronously make an outbound call and send it to a
10046 particular application with given extension */
10047 -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);
10048 +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);
10049
10050 /* Evaluate a condition for non-falseness and return a boolean */
10051 int pbx_checkcondition(char *condition);
10052 @@ -659,7 +661,7 @@
10053 */
10054 void ast_func_write(struct ast_channel *chan, const char *in, const char *value);
10055
10056 -void ast_hint_state_changed(const char *device);
10057 +void ast_hint_state_changed(const char *device, char *cid_num, char *cid_name);
10058
10059 #if defined(__cplusplus) || defined(c_plusplus)
10060 }
10061 diff -urN asterisk-1.2.7.1.orig/include/asterisk/xlaw.h asterisk-1.2.7.1/include/asterisk/xlaw.h
10062 --- asterisk-1.2.7.1.orig/include/asterisk/xlaw.h 1970-01-01 01:00:00.000000000 +0100
10063 +++ asterisk-1.2.7.1/include/asterisk/xlaw.h 2006-04-18 14:39:28.000000000 +0200
10064 @@ -0,0 +1,1665 @@
10065 +#ifndef _ASTERISK_XLAW_H
10066 +#define _ASTERISK_XLAW_H
10067 +
10068 +#ifdef CAPI_ULAW
10069 +#define capiXLAW2INT(x) capiULAW2INT[x]
10070 +#define capiINT2XLAW(x) capiINT2ULAW[((unsigned short)x) >> 2]
10071 +#else
10072 +#define capiXLAW2INT(x) capiALAW2INT[x]
10073 +#define capiINT2XLAW(x) capiINT2ALAW[(x>>4)+4096]
10074 +#endif
10075 +
10076 +static unsigned char reversebits[256] =
10077 +{
10078 +0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
10079 +0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
10080 +0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
10081 +0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
10082 +0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
10083 +0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
10084 +0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
10085 +0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
10086 +0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
10087 +0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
10088 +0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
10089 +0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
10090 +0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
10091 +0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
10092 +0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
10093 +0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
10094 +0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
10095 +0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
10096 +0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
10097 +0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
10098 +0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
10099 +0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
10100 +0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
10101 +0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
10102 +0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
10103 +0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
10104 +0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
10105 +0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
10106 +0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
10107 +0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
10108 +0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
10109 +0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
10110 +};
10111 +
10112 +#ifdef CAPI_ULAW
10113 +static short capiULAW2INT[] =
10114 +{
10115 +0x8284, 0x7d7c, 0xf8a4, 0x075c, 0xe104, 0x1efc, 0xfe8c, 0x0174,
10116 +0xc184, 0x3e7c, 0xfc94, 0x036c, 0xf0c4, 0x0f3c, 0xff88, 0x0078,
10117 +0xa284, 0x5d7c, 0xfaa4, 0x055c, 0xe904, 0x16fc, 0xff0c, 0x00f4,
10118 +0xd184, 0x2e7c, 0xfd94, 0x026c, 0xf4c4, 0x0b3c, 0xffc8, 0x0038,
10119 +0x9284, 0x6d7c, 0xf9a4, 0x065c, 0xe504, 0x1afc, 0xfecc, 0x0134,
10120 +0xc984, 0x367c, 0xfd14, 0x02ec, 0xf2c4, 0x0d3c, 0xffa8, 0x0058,
10121 +0xb284, 0x4d7c, 0xfba4, 0x045c, 0xed04, 0x12fc, 0xff4c, 0x00b4,
10122 +0xd984, 0x267c, 0xfe14, 0x01ec, 0xf6c4, 0x093c, 0xffe8, 0x0018,
10123 +0x8a84, 0x757c, 0xf924, 0x06dc, 0xe304, 0x1cfc, 0xfeac, 0x0154,
10124 +0xc584, 0x3a7c, 0xfcd4, 0x032c, 0xf1c4, 0x0e3c, 0xff98, 0x0068,
10125 +0xaa84, 0x557c, 0xfb24, 0x04dc, 0xeb04, 0x14fc, 0xff2c, 0x00d4,
10126 +0xd584, 0x2a7c, 0xfdd4, 0x022c, 0xf5c4, 0x0a3c, 0xffd8, 0x0028,
10127 +0x9a84, 0x657c, 0xfa24, 0x05dc, 0xe704, 0x18fc, 0xfeec, 0x0114,
10128 +0xcd84, 0x327c, 0xfd54, 0x02ac, 0xf3c4, 0x0c3c, 0xffb8, 0x0048,
10129 +0xba84, 0x457c, 0xfc24, 0x03dc, 0xef04, 0x10fc, 0xff6c, 0x0094,
10130 +0xdd84, 0x227c, 0xfe54, 0x01ac, 0xf7c4, 0x083c, 0xfff8, 0x0008,
10131 +0x8684, 0x797c, 0xf8e4, 0x071c, 0xe204, 0x1dfc, 0xfe9c, 0x0164,
10132 +0xc384, 0x3c7c, 0xfcb4, 0x034c, 0xf144, 0x0ebc, 0xff90, 0x0070,
10133 +0xa684, 0x597c, 0xfae4, 0x051c, 0xea04, 0x15fc, 0xff1c, 0x00e4,
10134 +0xd384, 0x2c7c, 0xfdb4, 0x024c, 0xf544, 0x0abc, 0xffd0, 0x0030,
10135 +0x9684, 0x697c, 0xf9e4, 0x061c, 0xe604, 0x19fc, 0xfedc, 0x0124,
10136 +0xcb84, 0x347c, 0xfd34, 0x02cc, 0xf344, 0x0cbc, 0xffb0, 0x0050,
10137 +0xb684, 0x497c, 0xfbe4, 0x041c, 0xee04, 0x11fc, 0xff5c, 0x00a4,
10138 +0xdb84, 0x247c, 0xfe34, 0x01cc, 0xf744, 0x08bc, 0xfff0, 0x0010,
10139 +0x8e84, 0x717c, 0xf964, 0x069c, 0xe404, 0x1bfc, 0xfebc, 0x0144,
10140 +0xc784, 0x387c, 0xfcf4, 0x030c, 0xf244, 0x0dbc, 0xffa0, 0x0060,
10141 +0xae84, 0x517c, 0xfb64, 0x049c, 0xec04, 0x13fc, 0xff3c, 0x00c4,
10142 +0xd784, 0x287c, 0xfdf4, 0x020c, 0xf644, 0x09bc, 0xffe0, 0x0020,
10143 +0x9e84, 0x617c, 0xfa64, 0x059c, 0xe804, 0x17fc, 0xfefc, 0x0104,
10144 +0xcf84, 0x307c, 0xfd74, 0x028c, 0xf444, 0x0bbc, 0xffc0, 0x0040,
10145 +0xbe84, 0x417c, 0xfc64, 0x039c, 0xf004, 0x0ffc, 0xff7c, 0x0084,
10146 +0xdf84, 0x207c, 0xfe74, 0x018c, 0xf844, 0x07bc, 0x0000, 0x0000
10147 +};
10148 +
10149 +const unsigned char capiINT2ULAW[16384] = {
10150 +255,127,127,191,191,63,63,223,223,95,95,159,159,31,31,239,
10151 +239,111,111,175,175,47,47,207,207,79,79,143,143,15,15,247,
10152 +247,247,247,119,119,119,119,183,183,183,183,55,55,55,55,215,
10153 +215,215,215,87,87,87,87,151,151,151,151,23,23,23,23,231,
10154 +231,231,231,103,103,103,103,167,167,167,167,39,39,39,39,199,
10155 +199,199,199,71,71,71,71,135,135,135,135,7,7,7,7,251,
10156 +251,251,251,251,251,251,251,123,123,123,123,123,123,123,123,187,
10157 +187,187,187,187,187,187,187,59,59,59,59,59,59,59,59,219,
10158 +219,219,219,219,219,219,219,91,91,91,91,91,91,91,91,155,
10159 +155,155,155,155,155,155,155,27,27,27,27,27,27,27,27,235,
10160 +235,235,235,235,235,235,235,107,107,107,107,107,107,107,107,171,
10161 +171,171,171,171,171,171,171,43,43,43,43,43,43,43,43,203,
10162 +203,203,203,203,203,203,203,75,75,75,75,75,75,75,75,139,
10163 +139,139,139,139,139,139,139,11,11,11,11,11,11,11,11,243,
10164 +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,115,
10165 +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,179,
10166 +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,51,
10167 +51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,211,
10168 +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,83,
10169 +83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,147,
10170 +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,19,
10171 +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,227,
10172 +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,99,
10173 +99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,163,
10174 +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,35,
10175 +35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,195,
10176 +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,67,
10177 +67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,131,
10178 +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,3,
10179 +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,253,
10180 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
10181 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,125,
10182 +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
10183 +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,189,
10184 +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
10185 +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,61,
10186 +61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,
10187 +61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,221,
10188 +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
10189 +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,93,
10190 +93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,
10191 +93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,157,
10192 +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
10193 +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,29,
10194 +29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,
10195 +29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,237,
10196 +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,
10197 +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,109,
10198 +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
10199 +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,173,
10200 +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
10201 +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,45,
10202 +45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,
10203 +45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,205,
10204 +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
10205 +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,77,
10206 +77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
10207 +77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,141,
10208 +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
10209 +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,13,
10210 +13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
10211 +13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,245,
10212 +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
10213 +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
10214 +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
10215 +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,117,
10216 +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
10217 +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
10218 +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
10219 +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,181,
10220 +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
10221 +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
10222 +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
10223 +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,53,
10224 +53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
10225 +53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
10226 +53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
10227 +53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,213,
10228 +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
10229 +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
10230 +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
10231 +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,85,
10232 +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10233 +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10234 +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10235 +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,149,
10236 +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
10237 +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
10238 +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
10239 +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,21,
10240 +21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
10241 +21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
10242 +21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
10243 +21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,229,
10244 +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
10245 +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
10246 +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
10247 +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,101,
10248 +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
10249 +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
10250 +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
10251 +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,165,
10252 +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
10253 +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
10254 +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
10255 +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,37,
10256 +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
10257 +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
10258 +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
10259 +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,197,
10260 +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
10261 +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
10262 +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
10263 +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,69,
10264 +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
10265 +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
10266 +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
10267 +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,133,
10268 +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
10269 +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
10270 +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
10271 +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,5,
10272 +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
10273 +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
10274 +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
10275 +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,249,
10276 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
10277 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
10278 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
10279 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
10280 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
10281 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
10282 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
10283 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,121,
10284 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
10285 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
10286 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
10287 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
10288 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
10289 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
10290 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
10291 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,185,
10292 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
10293 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
10294 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
10295 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
10296 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
10297 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
10298 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
10299 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,57,
10300 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
10301 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
10302 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
10303 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
10304 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
10305 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
10306 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
10307 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,217,
10308 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
10309 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
10310 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
10311 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
10312 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
10313 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
10314 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
10315 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,89,
10316 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
10317 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
10318 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
10319 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
10320 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
10321 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
10322 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
10323 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,153,
10324 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
10325 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
10326 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
10327 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
10328 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
10329 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
10330 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
10331 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,25,
10332 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
10333 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
10334 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
10335 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
10336 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
10337 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
10338 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
10339 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,233,
10340 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
10341 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
10342 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
10343 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
10344 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
10345 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
10346 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
10347 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,105,
10348 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
10349 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
10350 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
10351 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
10352 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
10353 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
10354 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
10355 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,169,
10356 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
10357 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
10358 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
10359 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
10360 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
10361 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
10362 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
10363 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,41,
10364 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
10365 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
10366 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
10367 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
10368 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
10369 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
10370 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
10371 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,201,
10372 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
10373 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
10374 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
10375 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
10376 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
10377 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
10378 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
10379 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,73,
10380 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
10381 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
10382 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
10383 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
10384 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
10385 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
10386 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
10387 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,137,
10388 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
10389 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
10390 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
10391 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
10392 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
10393 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
10394 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
10395 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,9,
10396 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
10397 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
10398 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
10399 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
10400 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
10401 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
10402 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
10403 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,241,
10404 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10405 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10406 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10407 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10408 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10409 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10410 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10411 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10412 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10413 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10414 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10415 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10416 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10417 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10418 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10419 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,113,
10420 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10421 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10422 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10423 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10424 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10425 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10426 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10427 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10428 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10429 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10430 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10431 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10432 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10433 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10434 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10435 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,177,
10436 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10437 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10438 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10439 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10440 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10441 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10442 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10443 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10444 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10445 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10446 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10447 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10448 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10449 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10450 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10451 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,49,
10452 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10453 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10454 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10455 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10456 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10457 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10458 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10459 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10460 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10461 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10462 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10463 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10464 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10465 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10466 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10467 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,209,
10468 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10469 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10470 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10471 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10472 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10473 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10474 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10475 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10476 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10477 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10478 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10479 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10480 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10481 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10482 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10483 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,81,
10484 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10485 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10486 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10487 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10488 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10489 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10490 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10491 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10492 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10493 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10494 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10495 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10496 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10497 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10498 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10499 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,145,
10500 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10501 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10502 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10503 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10504 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10505 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10506 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10507 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10508 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10509 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10510 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10511 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10512 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10513 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10514 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10515 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,17,
10516 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
10517 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
10518 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
10519 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
10520 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
10521 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
10522 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
10523 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
10524 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
10525 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
10526 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
10527 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
10528 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
10529 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
10530 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
10531 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,225,
10532 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
10533 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
10534 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
10535 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
10536 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
10537 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
10538 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
10539 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
10540 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
10541 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
10542 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
10543 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
10544 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
10545 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
10546 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
10547 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,97,
10548 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
10549 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
10550 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
10551 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
10552 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
10553 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
10554 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
10555 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
10556 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
10557 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
10558 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
10559 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
10560 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
10561 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
10562 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
10563 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,161,
10564 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
10565 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
10566 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
10567 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
10568 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
10569 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
10570 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
10571 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
10572 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
10573 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
10574 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
10575 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
10576 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
10577 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
10578 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
10579 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,33,
10580 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
10581 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
10582 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
10583 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
10584 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
10585 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
10586 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
10587 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
10588 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
10589 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
10590 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
10591 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
10592 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
10593 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
10594 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
10595 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,193,
10596 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
10597 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
10598 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
10599 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
10600 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
10601 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
10602 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
10603 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
10604 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
10605 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
10606 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
10607 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
10608 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
10609 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
10610 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
10611 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,65,
10612 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
10613 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
10614 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
10615 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
10616 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
10617 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
10618 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
10619 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
10620 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
10621 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
10622 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
10623 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
10624 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
10625 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
10626 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
10627 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,129,
10628 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
10629 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
10630 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
10631 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
10632 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
10633 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
10634 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
10635 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
10636 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
10637 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
10638 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
10639 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
10640 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
10641 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
10642 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
10643 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,1,
10644 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
10645 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
10646 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
10647 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
10648 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
10649 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
10650 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
10651 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
10652 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
10653 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
10654 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
10655 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
10656 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
10657 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
10658 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
10659 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
10660 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
10661 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
10662 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10663 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10664 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10665 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10666 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10667 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10668 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10669 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10670 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10671 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10672 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10673 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10674 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10675 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10676 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10677 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10678 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10679 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10680 +64,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
10681 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
10682 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
10683 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
10684 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
10685 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
10686 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
10687 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
10688 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
10689 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
10690 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
10691 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
10692 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
10693 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
10694 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
10695 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
10696 +128,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10697 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10698 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10699 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10700 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10701 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10702 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10703 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10704 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10705 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10706 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10707 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10708 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10709 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10710 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10711 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10712 +64,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
10713 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
10714 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
10715 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
10716 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
10717 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
10718 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
10719 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
10720 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
10721 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
10722 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
10723 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
10724 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
10725 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
10726 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
10727 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
10728 +192,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
10729 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
10730 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
10731 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
10732 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
10733 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
10734 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
10735 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
10736 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
10737 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
10738 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
10739 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
10740 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
10741 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
10742 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
10743 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
10744 +32,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
10745 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
10746 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
10747 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
10748 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
10749 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
10750 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
10751 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
10752 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
10753 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
10754 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
10755 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
10756 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
10757 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
10758 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
10759 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
10760 +160,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
10761 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
10762 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
10763 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
10764 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
10765 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
10766 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
10767 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
10768 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
10769 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
10770 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
10771 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
10772 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
10773 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
10774 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
10775 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
10776 +96,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
10777 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
10778 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
10779 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
10780 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
10781 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
10782 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
10783 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
10784 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
10785 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
10786 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
10787 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
10788 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
10789 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
10790 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
10791 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
10792 +224,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
10793 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
10794 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
10795 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
10796 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
10797 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
10798 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
10799 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
10800 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
10801 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
10802 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
10803 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
10804 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
10805 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
10806 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
10807 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
10808 +16,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
10809 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
10810 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
10811 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
10812 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
10813 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
10814 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
10815 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
10816 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
10817 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
10818 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
10819 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
10820 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
10821 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
10822 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
10823 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
10824 +144,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
10825 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
10826 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
10827 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
10828 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
10829 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
10830 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
10831 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
10832 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
10833 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
10834 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
10835 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
10836 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
10837 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
10838 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
10839 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
10840 +80,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
10841 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
10842 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
10843 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
10844 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
10845 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
10846 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
10847 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
10848 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
10849 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
10850 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
10851 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
10852 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
10853 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
10854 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
10855 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
10856 +208,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10857 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10858 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10859 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10860 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10861 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10862 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10863 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10864 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10865 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10866 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10867 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10868 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10869 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10870 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10871 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10872 +48,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10873 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10874 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10875 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10876 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10877 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10878 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10879 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10880 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10881 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10882 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10883 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10884 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10885 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10886 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10887 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10888 +176,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10889 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10890 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10891 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10892 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10893 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10894 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10895 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10896 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10897 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10898 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10899 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10900 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10901 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10902 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10903 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10904 +112,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10905 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10906 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10907 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10908 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10909 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10910 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10911 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10912 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10913 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10914 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10915 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10916 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10917 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10918 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10919 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10920 +240,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
10921 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
10922 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
10923 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
10924 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
10925 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
10926 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
10927 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
10928 +8,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
10929 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
10930 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
10931 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
10932 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
10933 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
10934 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
10935 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
10936 +136,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
10937 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
10938 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
10939 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
10940 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
10941 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
10942 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
10943 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
10944 +72,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
10945 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
10946 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
10947 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
10948 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
10949 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
10950 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
10951 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
10952 +200,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
10953 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
10954 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
10955 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
10956 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
10957 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
10958 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
10959 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
10960 +40,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
10961 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
10962 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
10963 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
10964 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
10965 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
10966 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
10967 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
10968 +168,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
10969 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
10970 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
10971 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
10972 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
10973 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
10974 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
10975 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
10976 +104,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
10977 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
10978 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
10979 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
10980 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
10981 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
10982 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
10983 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
10984 +232,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
10985 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
10986 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
10987 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
10988 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
10989 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
10990 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
10991 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
10992 +24,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
10993 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
10994 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
10995 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
10996 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
10997 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
10998 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
10999 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
11000 +152,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11001 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11002 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11003 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11004 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11005 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11006 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11007 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11008 +88,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11009 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11010 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11011 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11012 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11013 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11014 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11015 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11016 +216,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11017 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11018 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11019 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11020 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11021 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11022 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11023 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11024 +56,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11025 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11026 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11027 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11028 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11029 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11030 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11031 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11032 +184,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11033 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11034 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11035 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11036 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11037 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11038 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11039 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11040 +120,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11041 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11042 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11043 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11044 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11045 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11046 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11047 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11048 +248,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11049 +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11050 +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11051 +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11052 +4,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11053 +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11054 +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11055 +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11056 +132,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11057 +68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11058 +68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11059 +68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11060 +68,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11061 +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11062 +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11063 +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11064 +196,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11065 +36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11066 +36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11067 +36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11068 +36,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11069 +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11070 +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11071 +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11072 +164,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11073 +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11074 +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11075 +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11076 +100,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11077 +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11078 +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11079 +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11080 +228,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11081 +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11082 +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11083 +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11084 +20,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11085 +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11086 +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11087 +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11088 +148,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11089 +84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11090 +84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11091 +84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11092 +84,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11093 +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11094 +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11095 +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11096 +212,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
11097 +52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
11098 +52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
11099 +52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
11100 +52,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
11101 +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
11102 +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
11103 +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
11104 +180,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
11105 +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
11106 +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
11107 +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
11108 +116,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
11109 +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
11110 +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
11111 +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
11112 +244,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
11113 +12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
11114 +12,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
11115 +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
11116 +140,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
11117 +76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
11118 +76,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
11119 +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
11120 +204,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
11121 +44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
11122 +44,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
11123 +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
11124 +172,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
11125 +108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
11126 +108,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
11127 +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
11128 +236,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
11129 +28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
11130 +28,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
11131 +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
11132 +156,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
11133 +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
11134 +92,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
11135 +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
11136 +220,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
11137 +60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
11138 +60,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
11139 +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
11140 +188,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
11141 +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
11142 +124,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
11143 +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
11144 +252,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
11145 +2,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,
11146 +130,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
11147 +66,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,
11148 +194,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
11149 +34,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,
11150 +162,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,
11151 +98,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,
11152 +226,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,
11153 +18,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,
11154 +146,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,
11155 +82,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,
11156 +210,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
11157 +50,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,
11158 +178,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
11159 +114,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,
11160 +242,10,10,10,10,10,10,10,10,138,138,138,138,138,138,138,
11161 +138,74,74,74,74,74,74,74,74,202,202,202,202,202,202,202,
11162 +202,42,42,42,42,42,42,42,42,170,170,170,170,170,170,170,
11163 +170,106,106,106,106,106,106,106,106,234,234,234,234,234,234,234,
11164 +234,26,26,26,26,26,26,26,26,154,154,154,154,154,154,154,
11165 +154,90,90,90,90,90,90,90,90,218,218,218,218,218,218,218,
11166 +218,58,58,58,58,58,58,58,58,186,186,186,186,186,186,186,
11167 +186,122,122,122,122,122,122,122,122,250,250,250,250,250,250,250,
11168 +250,6,6,6,6,134,134,134,134,70,70,70,70,198,198,198,
11169 +198,38,38,38,38,166,166,166,166,102,102,102,102,230,230,230,
11170 +230,22,22,22,22,150,150,150,150,86,86,86,86,214,214,214,
11171 +214,54,54,54,54,182,182,182,182,118,118,118,118,246,246,246,
11172 +246,14,14,142,142,78,78,206,206,46,46,174,174,110,110,238,
11173 +238,30,30,158,158,94,94,222,222,62,62,190,190,126,126,254,
11174 +};
11175 +#else
11176 +static short capiALAW2INT[] =
11177 +{
11178 + 0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4,
11179 + 0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74,
11180 + 0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4,
11181 + 0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64,
11182 + 0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4,
11183 + 0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4,
11184 + 0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4,
11185 + 0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4,
11186 + 0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64,
11187 + 0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34,
11188 + 0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844,
11189 + 0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24,
11190 + 0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64,
11191 + 0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4,
11192 + 0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964,
11193 + 0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4,
11194 + 0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24,
11195 + 0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94,
11196 + 0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924,
11197 + 0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94,
11198 + 0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24,
11199 + 0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14,
11200 + 0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24,
11201 + 0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14,
11202 + 0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4,
11203 + 0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54,
11204 + 0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4,
11205 + 0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64,
11206 + 0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4,
11207 + 0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4,
11208 + 0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4,
11209 + 0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4
11210 +};
11211 +
11212 +const unsigned char capiINT2ALAW[8192] = {
11213 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11214 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11215 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11216 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11217 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11218 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11219 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11220 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11221 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11222 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11223 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11224 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11225 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11226 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11227 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11228 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11229 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11230 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11231 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11232 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11233 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11234 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11235 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11236 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11237 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11238 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11239 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11240 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11241 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11242 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11243 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11244 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11245 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11246 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11247 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11248 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11249 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11250 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11251 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11252 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11253 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11254 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11255 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11256 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11257 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11258 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11259 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11260 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11261 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11262 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11263 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11264 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11265 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11266 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11267 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11268 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11269 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11270 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11271 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11272 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11273 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11274 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11275 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11276 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11277 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11278 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11279 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11280 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11281 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11282 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11283 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11284 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11285 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11286 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11287 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11288 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11289 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11290 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11291 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11292 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11293 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11294 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11295 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11296 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11297 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11298 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11299 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11300 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11301 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11302 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11303 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11304 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11305 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11306 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11307 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11308 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11309 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11310 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11311 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11312 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11313 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11314 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11315 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11316 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11317 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11318 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11319 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11320 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11321 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11322 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11323 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11324 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11325 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11326 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11327 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11328 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11329 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11330 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11331 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11332 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11333 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11334 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11335 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11336 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11337 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11338 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11339 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11340 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11341 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11342 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11343 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11344 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11345 + 212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11346 + 212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11347 + 212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11348 + 212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11349 + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11350 + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11351 + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11352 + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11353 + 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11354 + 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11355 + 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11356 + 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11357 + 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
11358 + 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
11359 + 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
11360 + 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
11361 + 244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
11362 + 244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
11363 + 244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
11364 + 244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
11365 + 52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
11366 + 52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
11367 + 52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
11368 + 52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
11369 + 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
11370 + 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
11371 + 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
11372 + 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
11373 + 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11374 + 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11375 + 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11376 + 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11377 + 196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11378 + 196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11379 + 196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11380 + 196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11381 + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11382 + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11383 + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11384 + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11385 + 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11386 + 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11387 + 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11388 + 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11389 + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11390 + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11391 + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11392 + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11393 + 228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11394 + 228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11395 + 228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11396 + 228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11397 + 36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11398 + 36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11399 + 36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11400 + 36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11401 + 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11402 + 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11403 + 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11404 + 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11405 + 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
11406 + 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
11407 + 220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
11408 + 220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
11409 + 28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
11410 + 28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
11411 + 156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
11412 + 156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
11413 + 124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
11414 + 124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
11415 + 252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
11416 + 252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
11417 + 60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
11418 + 60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
11419 + 188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
11420 + 188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
11421 + 76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
11422 + 76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
11423 + 204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
11424 + 204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
11425 + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
11426 + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
11427 + 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
11428 + 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
11429 + 108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
11430 + 108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
11431 + 236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
11432 + 236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
11433 + 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
11434 + 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
11435 + 172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
11436 + 172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
11437 + 80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11438 + 208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11439 + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11440 + 144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11441 + 112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11442 + 240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11443 + 48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11444 + 176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11445 + 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11446 + 192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11447 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11448 + 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11449 + 96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11450 + 224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11451 + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11452 + 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11453 + 88,88,88,88,88,88,88,88,216,216,216,216,216,216,216,216,
11454 + 24,24,24,24,24,24,24,24,152,152,152,152,152,152,152,152,
11455 + 120,120,120,120,120,120,120,120,248,248,248,248,248,248,248,248,
11456 + 56,56,56,56,56,56,56,56,184,184,184,184,184,184,184,184,
11457 + 72,72,72,72,72,72,72,72,200,200,200,200,200,200,200,200,
11458 + 8,8,8,8,8,8,8,8,136,136,136,136,136,136,136,136,
11459 + 104,104,104,104,104,104,104,104,232,232,232,232,232,232,232,232,
11460 + 40,40,40,40,40,40,40,40,168,168,168,168,168,168,168,168,
11461 + 86,86,86,86,214,214,214,214,22,22,22,22,150,150,150,150,
11462 + 118,118,118,118,246,246,246,246,54,54,54,54,182,182,182,182,
11463 + 70,70,70,70,198,198,198,198,6,6,6,6,134,134,134,134,
11464 + 102,102,102,102,230,230,230,230,38,38,38,38,166,166,166,166,
11465 + 94,94,222,222,30,30,158,158,126,126,254,254,62,62,190,190,
11466 + 78,78,206,206,14,14,142,142,110,110,238,238,46,46,174,174,
11467 + 82,210,18,146,114,242,50,178,66,194,2,130,98,226,34,162,
11468 + 90,218,26,154,122,250,58,186,74,202,10,138,106,234,42,170,
11469 + 171,43,235,107,139,11,203,75,187,59,251,123,155,27,219,91,
11470 + 163,35,227,99,131,3,195,67,179,51,243,115,147,19,211,83,
11471 + 175,175,47,47,239,239,111,111,143,143,15,15,207,207,79,79,
11472 + 191,191,63,63,255,255,127,127,159,159,31,31,223,223,95,95,
11473 + 167,167,167,167,39,39,39,39,231,231,231,231,103,103,103,103,
11474 + 135,135,135,135,7,7,7,7,199,199,199,199,71,71,71,71,
11475 + 183,183,183,183,55,55,55,55,247,247,247,247,119,119,119,119,
11476 + 151,151,151,151,23,23,23,23,215,215,215,215,87,87,87,87,
11477 + 169,169,169,169,169,169,169,169,41,41,41,41,41,41,41,41,
11478 + 233,233,233,233,233,233,233,233,105,105,105,105,105,105,105,105,
11479 + 137,137,137,137,137,137,137,137,9,9,9,9,9,9,9,9,
11480 + 201,201,201,201,201,201,201,201,73,73,73,73,73,73,73,73,
11481 + 185,185,185,185,185,185,185,185,57,57,57,57,57,57,57,57,
11482 + 249,249,249,249,249,249,249,249,121,121,121,121,121,121,121,121,
11483 + 153,153,153,153,153,153,153,153,25,25,25,25,25,25,25,25,
11484 + 217,217,217,217,217,217,217,217,89,89,89,89,89,89,89,89,
11485 + 161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11486 + 33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11487 + 225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11488 + 97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11489 + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11490 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11491 + 193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11492 + 65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11493 + 177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
11494 + 49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
11495 + 241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
11496 + 113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
11497 + 145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11498 + 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11499 + 209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
11500 + 81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
11501 + 173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
11502 + 173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
11503 + 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,
11504 + 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,
11505 + 237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,
11506 + 237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,
11507 + 109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
11508 + 109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
11509 + 141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
11510 + 141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
11511 + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
11512 + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
11513 + 205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
11514 + 205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
11515 + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
11516 + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
11517 + 189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
11518 + 189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
11519 + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,
11520 + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,
11521 + 253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
11522 + 253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
11523 + 125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
11524 + 125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
11525 + 157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
11526 + 157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
11527 + 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,
11528 + 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,
11529 + 221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
11530 + 221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
11531 + 93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,
11532 + 93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,
11533 + 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
11534 + 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
11535 + 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
11536 + 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
11537 + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
11538 + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
11539 + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
11540 + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
11541 + 229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
11542 + 229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
11543 + 229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
11544 + 229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
11545 + 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
11546 + 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
11547 + 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
11548 + 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
11549 + 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
11550 + 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
11551 + 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
11552 + 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
11553 + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
11554 + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
11555 + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
11556 + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
11557 + 197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
11558 + 197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
11559 + 197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
11560 + 197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
11561 + 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
11562 + 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
11563 + 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
11564 + 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
11565 + 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
11566 + 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
11567 + 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
11568 + 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
11569 + 53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
11570 + 53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
11571 + 53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
11572 + 53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
11573 + 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
11574 + 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
11575 + 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
11576 + 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
11577 + 117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
11578 + 117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
11579 + 117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
11580 + 117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
11581 + 149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
11582 + 149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
11583 + 149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
11584 + 149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
11585 + 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
11586 + 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
11587 + 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
11588 + 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
11589 + 213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
11590 + 213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
11591 + 213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
11592 + 213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
11593 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11594 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11595 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11596 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11597 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11598 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11599 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11600 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11601 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11602 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11603 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11604 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11605 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11606 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11607 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11608 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11609 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11610 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11611 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11612 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11613 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11614 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11615 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11616 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11617 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11618 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11619 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11620 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11621 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11622 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11623 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11624 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11625 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11626 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11627 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11628 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11629 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11630 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11631 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11632 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11633 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11634 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11635 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11636 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11637 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11638 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11639 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11640 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11641 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11642 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11643 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11644 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11645 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11646 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11647 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11648 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11649 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11650 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11651 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11652 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11653 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11654 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11655 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11656 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11657 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11658 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11659 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11660 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11661 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11662 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11663 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11664 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11665 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11666 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11667 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11668 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11669 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11670 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11671 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11672 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11673 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11674 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11675 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11676 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11677 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11678 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11679 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11680 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11681 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11682 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11683 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11684 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11685 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11686 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11687 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11688 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11689 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11690 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11691 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11692 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11693 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11694 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11695 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11696 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11697 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11698 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11699 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11700 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11701 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11702 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11703 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11704 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11705 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11706 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11707 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11708 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11709 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11710 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11711 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11712 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11713 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11714 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11715 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11716 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11717 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11718 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11719 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11720 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11721 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11722 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11723 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11724 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85
11725 +};
11726 +
11727 +#endif // CAPI_ULAW
11728 +#endif
11729 +
11730 diff -urN asterisk-1.2.7.1.orig/include/asterisk.h asterisk-1.2.7.1/include/asterisk.h
11731 --- asterisk-1.2.7.1.orig/include/asterisk.h 2005-11-30 04:37:37.000000000 +0100
11732 +++ asterisk-1.2.7.1/include/asterisk.h 2006-04-18 14:39:28.000000000 +0200
11733 @@ -36,6 +36,7 @@
11734 extern char ast_config_AST_PID[AST_CONFIG_MAX_PATH];
11735 extern char ast_config_AST_SOCKET[AST_CONFIG_MAX_PATH];
11736 extern char ast_config_AST_RUN_DIR[AST_CONFIG_MAX_PATH];
11737 +extern char ast_config_AST_SYMBOLIC_NAME[20];
11738 extern char ast_config_AST_CTL_PERMISSIONS[AST_CONFIG_MAX_PATH];
11739 extern char ast_config_AST_CTL_OWNER[AST_CONFIG_MAX_PATH];
11740 extern char ast_config_AST_CTL_GROUP[AST_CONFIG_MAX_PATH];
11741 diff -urN asterisk-1.2.7.1.orig/manager.c asterisk-1.2.7.1/manager.c
11742 --- asterisk-1.2.7.1.orig/manager.c 2006-02-11 19:15:00.000000000 +0100
11743 +++ asterisk-1.2.7.1/manager.c 2006-04-18 14:39:28.000000000 +0200
11744 @@ -11,6 +11,9 @@
11745 * the project provides a web site, mailing lists and IRC
11746 * channels for your use.
11747 *
11748 + * Copyright (C) 2003-2004, Junghanns.NET Gmbh
11749 + * Klaus-Peter Junghanns <kpj@junghanns.net>
11750 + *
11751 * This program is free software, distributed under the terms of
11752 * the GNU General Public License Version 2. See the LICENSE file
11753 * at the top of the source tree.
11754 @@ -62,6 +65,7 @@
11755 #include "asterisk/md5.h"
11756 #include "asterisk/acl.h"
11757 #include "asterisk/utils.h"
11758 +#include "asterisk/astdb.h"
11759
11760 struct fast_originate_helper {
11761 char tech[AST_MAX_MANHEADER_LEN];
11762 @@ -76,6 +80,8 @@
11763 char idtext[AST_MAX_MANHEADER_LEN];
11764 char account[AST_MAX_ACCOUNT_CODE];
11765 int priority;
11766 + int callingpres;
11767 + char uniqueid[64];
11768 struct ast_variable *vars;
11769 };
11770
11771 @@ -657,11 +663,17 @@
11772 {
11773 struct ast_channel *c = NULL;
11774 char *name = astman_get_header(m, "Channel");
11775 - if (ast_strlen_zero(name)) {
11776 - astman_send_error(s, m, "No channel specified");
11777 + char *uniqueid = astman_get_header(m, "Uniqueid");
11778 + if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
11779 + astman_send_error(s, m, "No channel or uniqueid specified");
11780 return 0;
11781 }
11782 - c = ast_get_channel_by_name_locked(name);
11783 + if (!ast_strlen_zero(uniqueid)) {
11784 + c = ast_get_channel_by_uniqueid_locked(uniqueid);
11785 + } else {
11786 + if (!ast_strlen_zero(name))
11787 + c = ast_get_channel_by_name_locked(name);
11788 + }
11789 if (!c) {
11790 astman_send_error(s, m, "No such channel");
11791 return 0;
11792 @@ -760,6 +772,7 @@
11793 }
11794
11795
11796 +
11797 /*! \brief action_status: Manager "status" command to show channels */
11798 /* Needs documentation... */
11799 static int action_status(struct mansession *s, struct message *m)
11800 @@ -866,32 +879,50 @@
11801 char *exten = astman_get_header(m, "Exten");
11802 char *context = astman_get_header(m, "Context");
11803 char *priority = astman_get_header(m, "Priority");
11804 + char *uniqueid = astman_get_header(m, "Uniqueid");
11805 + char *uniqueid2 = astman_get_header(m, "ExtraUniqueid");
11806 + char *exten2 = astman_get_header(m, "ExtraExten");
11807 + char *context2 = astman_get_header(m, "ExtraContext");
11808 + char *priority2 = astman_get_header(m, "ExtraPriority");
11809 struct ast_channel *chan, *chan2 = NULL;
11810 int pi = 0;
11811 + int pi2 = 0;
11812 int res;
11813
11814 - if (ast_strlen_zero(name)) {
11815 - astman_send_error(s, m, "Channel not specified");
11816 + if ((!name || ast_strlen_zero(name)) && (!uniqueid || ast_strlen_zero(uniqueid))) {
11817 + astman_send_error(s, m, "Channel or Uniqueid not specified");
11818 return 0;
11819 }
11820 if (!ast_strlen_zero(priority) && (sscanf(priority, "%d", &pi) != 1)) {
11821 astman_send_error(s, m, "Invalid priority\n");
11822 return 0;
11823 }
11824 - chan = ast_get_channel_by_name_locked(name);
11825 + if (uniqueid && (!ast_strlen_zero(uniqueid))) {
11826 + chan = ast_get_channel_by_uniqueid_locked(uniqueid);
11827 + } else {
11828 + chan = ast_get_channel_by_name_locked(name);
11829 + }
11830 if (!chan) {
11831 char buf[BUFSIZ];
11832 snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
11833 astman_send_error(s, m, buf);
11834 return 0;
11835 }
11836 - if (!ast_strlen_zero(name2))
11837 + if (!ast_strlen_zero(uniqueid2)) {
11838 + chan2 = ast_get_channel_by_uniqueid_locked(uniqueid2);
11839 + if (!ast_strlen_zero(priority2) && (sscanf(priority, "%d", &pi2) != 1)) {
11840 + astman_send_error(s, m, "Invalid priority2\n");
11841 + return 0;
11842 + }
11843 + } else {
11844 + if (!ast_strlen_zero(name2))
11845 chan2 = ast_get_channel_by_name_locked(name2);
11846 + }
11847 res = ast_async_goto(chan, context, exten, pi);
11848 if (!res) {
11849 - if (!ast_strlen_zero(name2)) {
11850 + if ((!ast_strlen_zero(name2)) || (!ast_strlen_zero(uniqueid2))){
11851 if (chan2)
11852 - res = ast_async_goto(chan2, context, exten, pi);
11853 + res = ast_async_goto(chan2, context2, exten2, pi2);
11854 else
11855 res = -1;
11856 if (!res)
11857 @@ -937,15 +968,15 @@
11858 struct ast_channel *chan = NULL;
11859
11860 if (!ast_strlen_zero(in->app)) {
11861 - res = ast_pbx_outgoing_app(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1,
11862 + res = ast_pbx_outgoing_app(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1, in->callingpres,
11863 !ast_strlen_zero(in->cid_num) ? in->cid_num : NULL,
11864 !ast_strlen_zero(in->cid_name) ? in->cid_name : NULL,
11865 - in->vars, in->account, &chan);
11866 + in->vars, in->account, &chan, in->uniqueid);
11867 } else {
11868 - res = ast_pbx_outgoing_exten(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1,
11869 + res = ast_pbx_outgoing_exten(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1, in->callingpres,
11870 !ast_strlen_zero(in->cid_num) ? in->cid_num : NULL,
11871 !ast_strlen_zero(in->cid_name) ? in->cid_name : NULL,
11872 - in->vars, in->account, &chan);
11873 + in->vars, in->account, &chan, in->uniqueid);
11874 }
11875 if (!res)
11876 manager_event(EVENT_FLAG_CALL,
11877 @@ -956,7 +987,7 @@
11878 "Exten: %s\r\n"
11879 "Reason: %d\r\n"
11880 "Uniqueid: %s\r\n",
11881 - in->idtext, in->tech, in->data, in->context, in->exten, reason, chan ? chan->uniqueid : "<null>");
11882 + in->idtext, in->tech, in->data, in->context, in->exten, reason, in->uniqueid ? in->uniqueid : (chan ? chan->uniqueid : "<null>"));
11883 else
11884 manager_event(EVENT_FLAG_CALL,
11885 "OriginateFailure",
11886 @@ -966,7 +997,7 @@
11887 "Exten: %s\r\n"
11888 "Reason: %d\r\n"
11889 "Uniqueid: %s\r\n",
11890 - in->idtext, in->tech, in->data, in->context, in->exten, reason, chan ? chan->uniqueid : "<null>");
11891 + in->idtext, in->tech, in->data, in->context, in->exten, reason, in->uniqueid ? in->uniqueid : (chan ? chan->uniqueid : "<null>"));
11892
11893 /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */
11894 if (chan)
11895 @@ -999,6 +1030,7 @@
11896 char *priority = astman_get_header(m, "Priority");
11897 char *timeout = astman_get_header(m, "Timeout");
11898 char *callerid = astman_get_header(m, "CallerID");
11899 + char *callingpres = astman_get_header(m, "CallingPres");
11900 char *account = astman_get_header(m, "Account");
11901 char *app = astman_get_header(m, "Application");
11902 char *appdata = astman_get_header(m, "Data");
11903 @@ -1007,12 +1039,15 @@
11904 struct ast_variable *vars = astman_get_variables(m);
11905 char *tech, *data;
11906 char *l=NULL, *n=NULL;
11907 + char *uniqueid;
11908 int pi = 0;
11909 + int cpresi = 0;
11910 int res;
11911 int to = 30000;
11912 int reason = 0;
11913 char tmp[256];
11914 char tmp2[256];
11915 + char idText[256] = "";
11916
11917 pthread_t th;
11918 pthread_attr_t attr;
11919 @@ -1028,6 +1063,10 @@
11920 astman_send_error(s, m, "Invalid timeout\n");
11921 return 0;
11922 }
11923 + if (!ast_strlen_zero(callingpres) && (sscanf(callingpres, "%d", &cpresi) != 1)) {
11924 + astman_send_error(s, m, "Invalid CallingPres\n");
11925 + return 0;
11926 + }
11927 ast_copy_string(tmp, name, sizeof(tmp));
11928 tech = tmp;
11929 data = strchr(tmp, '/');
11930 @@ -1048,6 +1087,7 @@
11931 if (ast_strlen_zero(l))
11932 l = NULL;
11933 }
11934 + uniqueid = ast_alloc_uniqueid();
11935 if (ast_true(async)) {
11936 struct fast_originate_helper *fast = malloc(sizeof(struct fast_originate_helper));
11937 if (!fast) {
11938 @@ -1068,8 +1108,10 @@
11939 ast_copy_string(fast->context, context, sizeof(fast->context));
11940 ast_copy_string(fast->exten, exten, sizeof(fast->exten));
11941 ast_copy_string(fast->account, account, sizeof(fast->account));
11942 + ast_copy_string(fast->uniqueid, uniqueid, sizeof(fast->uniqueid));
11943 fast->timeout = to;
11944 fast->priority = pi;
11945 + fast->callingpres = cpresi;
11946 pthread_attr_init(&attr);
11947 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11948 if (ast_pthread_create(&th, &attr, fast_originate, fast)) {
11949 @@ -1079,19 +1121,28 @@
11950 }
11951 }
11952 } else if (!ast_strlen_zero(app)) {
11953 - res = ast_pbx_outgoing_app(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
11954 + res = ast_pbx_outgoing_app(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, cpresi, l, n, vars, account, NULL, uniqueid);
11955 } else {
11956 if (exten && context && pi)
11957 - res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
11958 + res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, cpresi, l, n, vars, account, NULL, uniqueid);
11959 else {
11960 astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
11961 return 0;
11962 }
11963 }
11964 - if (!res)
11965 - astman_send_ack(s, m, "Originate successfully queued");
11966 - else
11967 + if (!res) {
11968 + if (id && !ast_strlen_zero(id)) {
11969 + snprintf(idText,256,"ActionID: %s\r\n",id);
11970 + }
11971 + ast_cli(s->fd, "Response: Success\r\n"
11972 + "%s"
11973 + "Message: Originate successfully queued\r\n"
11974 + "Uniqueid: %s\r\n"
11975 + "\r\n",
11976 + idText, uniqueid);
11977 + } else {
11978 astman_send_error(s, m, "Originate failed");
11979 + }
11980 return 0;
11981 }
11982
11983 @@ -1565,10 +1616,10 @@
11984 return 0;
11985 }
11986
11987 -static int manager_state_cb(char *context, char *exten, int state, void *data)
11988 +static int manager_state_cb(char *context, char *exten, int state, void *data, char *cid_num, char *cid_name)
11989 {
11990 /* Notify managers of change */
11991 - manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nStatus: %d\r\n", exten, context, state);
11992 + 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);
11993 return 0;
11994 }
11995
11996 diff -urN asterisk-1.2.7.1.orig/pbx/pbx_spool.c asterisk-1.2.7.1/pbx/pbx_spool.c
11997 --- asterisk-1.2.7.1.orig/pbx/pbx_spool.c 2006-02-11 19:15:00.000000000 +0100
11998 +++ asterisk-1.2.7.1/pbx/pbx_spool.c 2006-04-18 14:39:28.000000000 +0200
11999 @@ -259,11 +259,11 @@
12000 if (!ast_strlen_zero(o->app)) {
12001 if (option_verbose > 2)
12002 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);
12003 - 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);
12004 + 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);
12005 } else {
12006 if (option_verbose > 2)
12007 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);
12008 - 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);
12009 + 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);
12010 }
12011 if (res) {
12012 ast_log(LOG_NOTICE, "Call failed to go through, reason %d\n", reason);
12013 diff -urN asterisk-1.2.7.1.orig/pbx.c asterisk-1.2.7.1/pbx.c
12014 --- asterisk-1.2.7.1.orig/pbx.c 2006-04-13 17:56:35.000000000 +0200
12015 +++ asterisk-1.2.7.1/pbx.c 2006-04-18 14:39:28.000000000 +0200
12016 @@ -353,7 +353,8 @@
12017
12018 { "Hangup", pbx_builtin_hangup,
12019 "Hang up the calling channel",
12020 - " Hangup(): This application will hang up the calling channel.\n"
12021 + " Hangup(Cause): Unconditionally hangs up a given channel by returning -1 always.\n"
12022 + " If cause is given, it will set the hangup cause accordingly.\n"
12023 },
12024
12025 { "NoOp", pbx_builtin_noop,
12026 @@ -1880,7 +1881,7 @@
12027 return ast_extension_state2(e); /* Check all devices in the hint */
12028 }
12029
12030 -void ast_hint_state_changed(const char *device)
12031 +void ast_hint_state_changed(const char *device, char *cid_num, char *cid_name)
12032 {
12033 struct ast_hint *hint;
12034 struct ast_state_cb *cblist;
12035 @@ -1908,11 +1909,11 @@
12036
12037 /* For general callbacks */
12038 for (cblist = statecbs; cblist; cblist = cblist->next)
12039 - cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
12040 + cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
12041
12042 /* For extension callbacks */
12043 for (cblist = hint->callbacks; cblist; cblist = cblist->next)
12044 - cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
12045 + cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
12046
12047 hint->laststate = state;
12048 break;
12049 @@ -2153,7 +2154,7 @@
12050 /* Notify with -1 and remove all callbacks */
12051 cbprev = cblist;
12052 cblist = cblist->next;
12053 - cbprev->callback(list->exten->parent->name, list->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
12054 + cbprev->callback(list->exten->parent->name, list->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data, NULL, NULL);
12055 free(cbprev);
12056 }
12057 list->callbacks = NULL;
12058 @@ -3774,7 +3775,7 @@
12059 while (thiscb) {
12060 prevcb = thiscb;
12061 thiscb = thiscb->next;
12062 - prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data);
12063 + prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data, NULL, NULL);
12064 free(prevcb);
12065 }
12066 } else {
12067 @@ -4976,7 +4977,7 @@
12068 return 0; /* success */
12069 }
12070
12071 -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)
12072 +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)
12073 {
12074 struct ast_channel *chan;
12075 struct async_stat *as;
12076 @@ -4986,7 +4987,7 @@
12077
12078 if (sync) {
12079 LOAD_OH(oh);
12080 - chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
12081 + chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
12082 if (channel) {
12083 *channel = chan;
12084 if (chan)
12085 @@ -5088,7 +5089,7 @@
12086 goto outgoing_exten_cleanup;
12087 }
12088 memset(as, 0, sizeof(struct async_stat));
12089 - chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
12090 + chan = ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, uniqueid);
12091 if (channel) {
12092 *channel = chan;
12093 if (chan)
12094 @@ -5134,7 +5135,7 @@
12095 pthread_t t;
12096 };
12097
12098 -static void *ast_pbx_run_app(void *data)
12099 +void *ast_pbx_run_app(void *data)
12100 {
12101 struct app_tmp *tmp = data;
12102 struct ast_app *app;
12103 @@ -5150,7 +5151,7 @@
12104 return NULL;
12105 }
12106
12107 -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)
12108 +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)
12109 {
12110 struct ast_channel *chan;
12111 struct async_stat *as;
12112 @@ -5170,7 +5171,7 @@
12113 goto outgoing_app_cleanup;
12114 }
12115 if (sync) {
12116 - chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
12117 + chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
12118 if (chan) {
12119 if (chan->cdr) { /* check if the channel already has a cdr record, if not give it one */
12120 ast_log(LOG_WARNING, "%s already has a call record??\n", chan->name);
12121 @@ -5257,7 +5258,8 @@
12122 goto outgoing_app_cleanup;
12123 }
12124 memset(as, 0, sizeof(struct async_stat));
12125 - chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
12126 + chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
12127 +// chan = ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, uniqueid);
12128 if (!chan) {
12129 free(as);
12130 res = -1;
12131 @@ -5544,6 +5546,9 @@
12132 */
12133 static int pbx_builtin_hangup(struct ast_channel *chan, void *data)
12134 {
12135 + /* Copy the hangup cause as specified */
12136 + if (data)
12137 + chan->hangupcause = atoi(data);
12138 /* Just return non-zero and it will hang up */
12139 if (!chan->hangupcause)
12140 chan->hangupcause = AST_CAUSE_NORMAL_CLEARING;
12141 @@ -6200,6 +6205,9 @@
12142 return -1;
12143 }
12144 }
12145 + if (chan->_state != AST_STATE_UP) {
12146 + ast_answer(chan);
12147 + }
12148 return res = ast_say_number(chan, atoi((char *) tmp), "", chan->language, options);
12149 }
12150
12151 @@ -6207,8 +6215,12 @@
12152 {
12153 int res = 0;
12154
12155 - if (data)
12156 + if (data) {
12157 + if (chan->_state != AST_STATE_UP) {
12158 + ast_answer(chan);
12159 + }
12160 res = ast_say_digit_str(chan, (char *)data, "", chan->language);
12161 + }
12162 return res;
12163 }
12164
12165 @@ -6216,8 +6228,12 @@
12166 {
12167 int res = 0;
12168
12169 - if (data)
12170 + if (data) {
12171 + if (chan->_state != AST_STATE_UP) {
12172 + ast_answer(chan);
12173 + }
12174 res = ast_say_character_str(chan, (char *)data, "", chan->language);
12175 + }
12176 return res;
12177 }
12178
12179 @@ -6225,8 +6241,12 @@
12180 {
12181 int res = 0;
12182
12183 - if (data)
12184 + if (data) {
12185 + if (chan->_state != AST_STATE_UP) {
12186 + ast_answer(chan);
12187 + }
12188 res = ast_say_phonetic_str(chan, (char *)data, "", chan->language);
12189 + }
12190 return res;
12191 }
12192
12193 diff -urN asterisk-1.2.7.1.orig/res/Makefile asterisk-1.2.7.1/res/Makefile
12194 --- asterisk-1.2.7.1.orig/res/Makefile 2005-11-29 19:24:39.000000000 +0100
12195 +++ asterisk-1.2.7.1/res/Makefile 2006-04-18 14:39:28.000000000 +0200
12196 @@ -11,7 +11,7 @@
12197 # the GNU General Public License
12198 #
12199
12200 -MODS=res_indications.so res_monitor.so res_adsi.so res_agi.so res_features.so
12201 +MODS=res_indications.so res_monitor.so res_adsi.so res_agi.so res_features.so res_watchdog.so
12202
12203 ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/odbcinst.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/odbcinst.h),)
12204 ifneq (${OSARCH},FreeBSD)
12205 diff -urN asterisk-1.2.7.1.orig/res/res_agi.c asterisk-1.2.7.1/res/res_agi.c
12206 --- asterisk-1.2.7.1.orig/res/res_agi.c 2006-02-28 19:31:04.000000000 +0100
12207 +++ asterisk-1.2.7.1/res/res_agi.c 2006-04-18 14:39:28.000000000 +0200
12208 @@ -11,6 +11,9 @@
12209 * the project provides a web site, mailing lists and IRC
12210 * channels for your use.
12211 *
12212 + * Copyright (C) 2005 Junghanns.NET GmbH
12213 + * Klaus-Peter Junghanns <kpj@junghanns.net>
12214 + *
12215 * This program is free software, distributed under the terms of
12216 * the GNU General Public License Version 2. See the LICENSE file
12217 * at the top of the source tree.
12218 @@ -74,16 +77,19 @@
12219
12220 static char *app = "AGI";
12221
12222 +static char *xapp = "XAGI";
12223 +
12224 static char *eapp = "EAGI";
12225
12226 static char *deadapp = "DeadAGI";
12227
12228 static char *synopsis = "Executes an AGI compliant application";
12229 +static char *xsynopsis = "Executes an XAGI compliant application";
12230 static char *esynopsis = "Executes an EAGI compliant application";
12231 static char *deadsynopsis = "Executes AGI on a hungup channel";
12232
12233 static char *descrip =
12234 -" [E|Dead]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
12235 +" [E|Dead|X]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
12236 "program on a channel. AGI allows Asterisk to launch external programs\n"
12237 "written in any language to control a telephony channel, play audio,\n"
12238 "read DTMF digits, etc. by communicating with the AGI protocol on stdin\n"
12239 @@ -92,6 +98,8 @@
12240 " hangup, or 0 on non-hangup exit. \n"
12241 "Using 'EAGI' provides enhanced AGI, with incoming audio available out of band\n"
12242 "on file descriptor 3\n\n"
12243 +"Using 'XAGI' provides enhanced AGI, with incoming audio available out of band"
12244 +" on file descriptor 3 and outgoing audio available out of band on file descriptor 4\n\n"
12245 "Use the CLI command 'show agi' to list available agi commands\n";
12246
12247 static int agidebug = 0;
12248 @@ -220,13 +228,14 @@
12249 return 0;
12250 }
12251
12252 -static int launch_script(char *script, char *argv[], int *fds, int *efd, int *opid)
12253 +static int launch_script(char *script, char *argv[], int *fds, int *efd, int *efd2, int *opid)
12254 {
12255 char tmp[256];
12256 int pid;
12257 int toast[2];
12258 int fromast[2];
12259 int audio[2];
12260 + int audio2[2];
12261 int x;
12262 int res;
12263 sigset_t signal_set;
12264 @@ -271,6 +280,33 @@
12265 return -1;
12266 }
12267 }
12268 + if (efd2) {
12269 + if (pipe(audio2)) {
12270 + ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
12271 + close(fromast[0]);
12272 + close(fromast[1]);
12273 + close(toast[0]);
12274 + close(toast[1]);
12275 + close(audio[0]);
12276 + close(audio[1]);
12277 + return -1;
12278 + }
12279 + res = fcntl(audio2[0], F_GETFL);
12280 + if (res > -1)
12281 + res = fcntl(audio2[0], F_SETFL, res | O_NONBLOCK);
12282 + if (res < 0) {
12283 + ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
12284 + close(fromast[0]);
12285 + close(fromast[1]);
12286 + close(toast[0]);
12287 + close(toast[1]);
12288 + close(audio[0]);
12289 + close(audio[1]);
12290 + close(audio2[0]);
12291 + close(audio2[1]);
12292 + return -1;
12293 + }
12294 + }
12295 pid = fork();
12296 if (pid < 0) {
12297 ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
12298 @@ -285,15 +321,19 @@
12299 } else {
12300 close(STDERR_FILENO + 1);
12301 }
12302 + if (efd2) {
12303 + dup2(audio2[1], STDERR_FILENO + 2);
12304 + } else {
12305 + close(STDERR_FILENO + 2);
12306 + }
12307
12308 /* unblock important signal handlers */
12309 if (sigfillset(&signal_set) || pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
12310 ast_log(LOG_WARNING, "unable to unblock signals for AGI script: %s\n", strerror(errno));
12311 exit(1);
12312 }
12313 -
12314 /* Close everything but stdin/out/error */
12315 - for (x=STDERR_FILENO + 2;x<1024;x++)
12316 + for (x=STDERR_FILENO + 3;x<1024;x++)
12317 close(x);
12318
12319 /* Don't run AGI scripts with realtime priority -- it causes audio stutter */
12320 @@ -312,6 +352,9 @@
12321 if (efd) {
12322 *efd = audio[1];
12323 }
12324 + if (efd2) {
12325 + *efd2 = audio2[0];
12326 + }
12327 /* close what we're not using in the parent */
12328 close(toast[1]);
12329 close(fromast[0]);
12330 @@ -320,6 +363,9 @@
12331 /* [PHM 12/18/03] */
12332 close(audio[0]);
12333 }
12334 + if (efd2) {
12335 + close(audio2[1]);
12336 + }
12337
12338 *opid = pid;
12339 return 0;
12340 @@ -350,7 +396,7 @@
12341 fdprintf(fd, "agi_context: %s\n", chan->context);
12342 fdprintf(fd, "agi_extension: %s\n", chan->exten);
12343 fdprintf(fd, "agi_priority: %d\n", chan->priority);
12344 - fdprintf(fd, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
12345 + fdprintf(fd, "agi_enhanced: %d%s\n", enhanced, ".0");
12346
12347 /* User information */
12348 fdprintf(fd, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
12349 @@ -382,7 +428,7 @@
12350 return RESULT_SHOWUSAGE;
12351 if (sscanf(argv[3], "%d", &to) != 1)
12352 return RESULT_SHOWUSAGE;
12353 - res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl);
12354 + res = ast_waitfordigit_full(chan, to, agi->audio_out, agi->ctrl);
12355 fdprintf(agi->fd, "200 result=%d\n", res);
12356 if (res >= 0)
12357 return RESULT_SUCCESS;
12358 @@ -558,7 +604,7 @@
12359 else
12360 return RESULT_FAILURE;
12361 }
12362 - res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
12363 + res = ast_waitstream_full(chan, argv[3], agi->audio_out, agi->ctrl);
12364 /* this is to check for if ast_waitstream closed the stream, we probably are at
12365 * the end of the stream, return that amount, else check for the amount */
12366 sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length;
12367 @@ -618,7 +664,7 @@
12368 else
12369 return RESULT_FAILURE;
12370 }
12371 - res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
12372 + res = ast_waitstream_full(chan, argv[3], agi->audio_out, agi->ctrl);
12373 /* this is to check for if ast_waitstream closed the stream, we probably are at
12374 * the end of the stream, return that amount, else check for the amount */
12375 sample_offset = (chan->stream)?ast_tellstream(fs):max_length;
12376 @@ -630,7 +676,7 @@
12377
12378 /* If the user didnt press a key, wait for digitTimeout*/
12379 if (res == 0 ) {
12380 - res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl);
12381 + res = ast_waitfordigit_full(chan, timeout, agi->audio_out, agi->ctrl);
12382 /* Make sure the new result is in the escape digits of the GET OPTION */
12383 if ( !strchr(edigits,res) )
12384 res=0;
12385 @@ -657,7 +703,7 @@
12386 return RESULT_SHOWUSAGE;
12387 if (sscanf(argv[2], "%d", &num) != 1)
12388 return RESULT_SHOWUSAGE;
12389 - res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio, agi->ctrl);
12390 + res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio_out, agi->ctrl);
12391 if (res == 1)
12392 return RESULT_SUCCESS;
12393 fdprintf(agi->fd, "200 result=%d\n", res);
12394 @@ -677,7 +723,7 @@
12395 if (sscanf(argv[2], "%d", &num) != 1)
12396 return RESULT_SHOWUSAGE;
12397
12398 - res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
12399 + res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio_out, agi->ctrl);
12400 if (res == 1) /* New command */
12401 return RESULT_SUCCESS;
12402 fdprintf(agi->fd, "200 result=%d\n", res);
12403 @@ -694,7 +740,7 @@
12404 if (argc != 4)
12405 return RESULT_SHOWUSAGE;
12406
12407 - res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
12408 + res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio_out, agi->ctrl);
12409 if (res == 1) /* New command */
12410 return RESULT_SUCCESS;
12411 fdprintf(agi->fd, "200 result=%d\n", res);
12412 @@ -784,7 +830,7 @@
12413 if (argc != 4)
12414 return RESULT_SHOWUSAGE;
12415
12416 - res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
12417 + res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio_out, agi->ctrl);
12418 if (res == 1) /* New command */
12419 return RESULT_SUCCESS;
12420 fdprintf(agi->fd, "200 result=%d\n", res);
12421 @@ -811,7 +857,7 @@
12422 max = atoi(argv[4]);
12423 else
12424 max = 1024;
12425 - res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl);
12426 + res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio_out, agi->ctrl);
12427 if (res == 2) /* New command */
12428 return RESULT_SUCCESS;
12429 else if (res == 1)
12430 @@ -1849,7 +1895,12 @@
12431 int ms;
12432 int returnstatus = 0;
12433 struct ast_frame *f;
12434 + struct ast_frame fr;
12435 char buf[2048];
12436 + char audiobuf[2048];
12437 + int audiobytes;
12438 + int fds[2];
12439 + int enhanced = 0;
12440 FILE *readf;
12441 /* how many times we'll retry if ast_waitfor_nandfs will return without either
12442 channel or file descriptor in case select is interrupted by a system call (EINTR) */
12443 @@ -1863,10 +1914,22 @@
12444 return -1;
12445 }
12446 setlinebuf(readf);
12447 - setup_env(chan, request, agi->fd, (agi->audio > -1));
12448 + if (agi->audio_out > -1) {
12449 + enhanced = 1;
12450 + }
12451 + if (agi->audio_in > -1) {
12452 + enhanced++;
12453 + }
12454 + setup_env(chan, request, agi->fd, enhanced);
12455 + fds[0] = agi->ctrl;
12456 + fds[1] = agi->audio_in;
12457 for (;;) {
12458 ms = -1;
12459 - c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
12460 + if (agi->audio_in > -1) {
12461 + c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, fds, 2, NULL, &outfd, &ms);
12462 + } else {
12463 + c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
12464 + }
12465 if (c) {
12466 retry = RETRY;
12467 /* Idle the channel until we get a command */
12468 @@ -1877,13 +1940,24 @@
12469 break;
12470 } else {
12471 /* If it's voice, write it to the audio pipe */
12472 - if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) {
12473 + if ((agi->audio_out > -1) && (f->frametype == AST_FRAME_VOICE)) {
12474 /* Write, ignoring errors */
12475 - write(agi->audio, f->data, f->datalen);
12476 + write(agi->audio_out, f->data, f->datalen);
12477 }
12478 ast_frfree(f);
12479 }
12480 } else if (outfd > -1) {
12481 + if ((agi->audio_in > -1) && (outfd == agi->audio_in)) {
12482 + audiobytes = read(agi->audio_in, audiobuf, sizeof(audiobuf));
12483 + if (audiobytes > 0) {
12484 + // ast_log(LOG_NOTICE, "read %d bytes of audio\n", audiobytes);
12485 + fr.frametype = AST_FRAME_VOICE;
12486 + fr.subclass = AST_FORMAT_SLINEAR;
12487 + fr.datalen = audiobytes;
12488 + fr.data = audiobuf;
12489 + ast_write(chan, &fr);
12490 + }
12491 + } else {
12492 retry = RETRY;
12493 if (!fgets(buf, sizeof(buf), readf)) {
12494 /* Program terminated */
12495 @@ -1905,6 +1979,7 @@
12496 if ((returnstatus < 0) || (returnstatus == AST_PBX_KEEPALIVE)) {
12497 break;
12498 }
12499 + }
12500 } else {
12501 if (--retry <= 0) {
12502 ast_log(LOG_WARNING, "No channel, no fd?\n");
12503 @@ -2011,6 +2086,7 @@
12504 int argc = 0;
12505 int fds[2];
12506 int efd = -1;
12507 + int efd2 = -1;
12508 int pid;
12509 char *stringp;
12510 AGI agi;
12511 @@ -2036,15 +2112,18 @@
12512 }
12513 }
12514 #endif
12515 - res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, &pid);
12516 + res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, (enhanced == 2) ? &efd2 : NULL, &pid);
12517 if (!res) {
12518 agi.fd = fds[1];
12519 agi.ctrl = fds[0];
12520 - agi.audio = efd;
12521 + agi.audio_out = efd;
12522 + agi.audio_in = efd2;
12523 res = run_agi(chan, argv[0], &agi, pid, dead);
12524 close(fds[1]);
12525 if (efd > -1)
12526 close(efd);
12527 + if (efd2 > -1)
12528 + close(efd2);
12529 }
12530 LOCAL_USER_REMOVE(u);
12531 return res;
12532 @@ -2078,6 +2157,35 @@
12533 return res;
12534 }
12535
12536 +static int xagi_exec(struct ast_channel *chan, void *data)
12537 +{
12538 + int readformat, writeformat;
12539 + int res;
12540 +
12541 + if (chan->_softhangup)
12542 + ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
12543 + readformat = chan->readformat;
12544 + if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
12545 + ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
12546 + return -1;
12547 + }
12548 + writeformat = chan->writeformat;
12549 + if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
12550 + ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
12551 + return -1;
12552 + }
12553 + res = agi_exec_full(chan, data, 2, 0);
12554 + if (!res) {
12555 + if (ast_set_read_format(chan, readformat)) {
12556 + ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat));
12557 + }
12558 + if (ast_set_write_format(chan, writeformat)) {
12559 + ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(writeformat));
12560 + }
12561 + }
12562 + return res;
12563 +}
12564 +
12565 static int deadagi_exec(struct ast_channel *chan, void *data)
12566 {
12567 return agi_exec_full(chan, data, 0, 1);
12568 @@ -2107,6 +2215,7 @@
12569 ast_cli_unregister(&dumpagihtml);
12570 ast_cli_unregister(&cli_debug);
12571 ast_cli_unregister(&cli_no_debug);
12572 + ast_unregister_application(xapp);
12573 ast_unregister_application(eapp);
12574 ast_unregister_application(deadapp);
12575 return ast_unregister_application(app);
12576 @@ -2120,6 +2229,7 @@
12577 ast_cli_register(&cli_no_debug);
12578 ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
12579 ast_register_application(eapp, eagi_exec, esynopsis, descrip);
12580 + ast_register_application(xapp, xagi_exec, xsynopsis, descrip);
12581 return ast_register_application(app, agi_exec, synopsis, descrip);
12582 }
12583
12584 diff -urN asterisk-1.2.7.1.orig/res/res_features.c asterisk-1.2.7.1/res/res_features.c
12585 --- asterisk-1.2.7.1.orig/res/res_features.c 2006-04-10 19:29:51.000000000 +0200
12586 +++ asterisk-1.2.7.1/res/res_features.c 2006-04-18 14:39:28.000000000 +0200
12587 @@ -11,6 +11,10 @@
12588 * the project provides a web site, mailing lists and IRC
12589 * channels for your use.
12590 *
12591 + * Copyright (C) 2004, Junghanns.NET GmbH
12592 + *
12593 + * Klaus-Peter Junghanns <kpj@junghanns.net>
12594 + *
12595 * This program is free software, distributed under the terms of
12596 * the GNU General Public License Version 2. See the LICENSE file
12597 * at the top of the source tree.
12598 @@ -56,6 +60,7 @@
12599 #include "asterisk/utils.h"
12600 #include "asterisk/adsi.h"
12601 #include "asterisk/monitor.h"
12602 +#include "asterisk/indications.h"
12603
12604 #ifdef __AST_DEBUG_MALLOC
12605 static void FREE(void *ptr)
12606 @@ -73,6 +78,7 @@
12607 #define AST_MAX_WATCHERS 256
12608
12609 static char *parkedcall = "ParkedCall";
12610 +static char *holdedcall = "HoldedCall";
12611
12612 /* No more than 45 seconds parked before you do something with them */
12613 static int parkingtime = DEFAULT_PARK_TIME;
12614 @@ -132,6 +138,20 @@
12615 "into the dialplan, although you should include the 'parkedcalls'\n"
12616 "context.\n";
12617
12618 +static char *autoanswerlogin = "AutoanswerLogin";
12619 +
12620 +static char *synopsis3 = "Log in for autoanswer";
12621 +
12622 +static char *descrip3 = "AutoanswerLogin(exten):"
12623 +"Used to login to the autoanswer application for an extension.\n";
12624 +
12625 +static char *autoanswer = "Autoanswer";
12626 +
12627 +static char *synopsis4 = "Autoanswer a call";
12628 +
12629 +static char *descrip4 = "Autoanswer(exten):"
12630 +"Used to autoanswer a call for an extension.\n";
12631 +
12632 static struct ast_app *monitor_app=NULL;
12633 static int monitor_ok=1;
12634
12635 @@ -150,12 +170,51 @@
12636 struct parkeduser *next;
12637 };
12638
12639 +struct holdeduser {
12640 + struct ast_channel *chan;
12641 + struct timeval start;
12642 + int parkingnum;
12643 + int cref;
12644 + int tei;
12645 + /* Where to go if our parking time expires */
12646 + char context[AST_MAX_EXTENSION];
12647 + char exten[AST_MAX_EXTENSION];
12648 + int priority;
12649 + int parkingtime;
12650 + char uniqueid[AST_MAX_UNIQUEID];
12651 + char uniqueidpeer[AST_MAX_UNIQUEID];
12652 + struct holdeduser *next;
12653 +};
12654 +
12655 +/* auto answer user */
12656 +struct aauser {
12657 + struct ast_channel *chan;
12658 + struct timeval start;
12659 + /* waiting on this extension/context */
12660 + char exten[AST_MAX_EXTENSION];
12661 + char context[AST_MAX_EXTENSION];
12662 + int priority;
12663 + int notquiteyet;
12664 + struct aauser *next;
12665 +};
12666 +
12667 +
12668 +static struct aauser *aalot;
12669 +AST_MUTEX_DEFINE_STATIC(autoanswer_lock);
12670 +static pthread_t autoanswer_thread;
12671 +
12672 static struct parkeduser *parkinglot;
12673
12674 +static struct holdeduser *holdlist;
12675 +
12676 AST_MUTEX_DEFINE_STATIC(parking_lock);
12677
12678 +AST_MUTEX_DEFINE_STATIC(holding_lock);
12679 +
12680 static pthread_t parking_thread;
12681
12682 +static pthread_t holding_thread;
12683 +
12684 STANDARD_LOCAL_USER;
12685
12686 LOCAL_USER_DECL;
12687 @@ -165,6 +224,12 @@
12688 return parking_ext;
12689 }
12690
12691 +char *ast_parking_con(void)
12692 +{
12693 + return parking_con;
12694 +}
12695 +
12696 +
12697 char *ast_pickup_ext(void)
12698 {
12699 return pickup_ext;
12700 @@ -362,10 +427,11 @@
12701 "Timeout: %ld\r\n"
12702 "CallerID: %s\r\n"
12703 "CallerIDName: %s\r\n"
12704 + "Unqiueid: %s\r\n\r\n"
12705 ,pu->parkingnum, pu->chan->name, peer ? peer->name : ""
12706 ,(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL)
12707 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
12708 - ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
12709 + ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
12710 );
12711
12712 if (peer) {
12713 @@ -418,7 +484,8 @@
12714 ast_copy_string(chan->context, rchan->context, sizeof(chan->context));
12715 ast_copy_string(chan->exten, rchan->exten, sizeof(chan->exten));
12716 chan->priority = rchan->priority;
12717 -
12718 + /* might be dirty but we want trackable channels */
12719 + strncpy(chan->uniqueid, rchan->uniqueid, sizeof(chan->uniqueid) - 1);
12720 /* Make the masq execute */
12721 f = ast_read(chan);
12722 if (f)
12723 @@ -906,7 +973,7 @@
12724 }
12725
12726 /* find a feature by name */
12727 -static struct ast_call_feature *find_feature(char *name)
12728 +struct ast_call_feature *ast_find_feature(char *name)
12729 {
12730 struct ast_call_feature *tmp;
12731
12732 @@ -916,10 +983,21 @@
12733 break;
12734 }
12735 AST_LIST_UNLOCK(&feature_list);
12736 -
12737 return tmp;
12738 }
12739
12740 +struct ast_call_feature *ast_find_builtin_feature(char *name)
12741 +{
12742 + int x = 0;
12743 +
12744 + for (x = 0; x < FEATURES_COUNT; x++) {
12745 + if (!strcasecmp(name, builtin_features[x].sname)) {
12746 + return &builtin_features[x];
12747 + }
12748 + }
12749 + return NULL;
12750 +}
12751 +
12752 /* exec an app by feature */
12753 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
12754 {
12755 @@ -1014,7 +1092,7 @@
12756 return res;
12757
12758 while ((tok = strsep(&tmp, "#")) != NULL) {
12759 - feature = find_feature(tok);
12760 + feature = ast_find_feature(tok);
12761
12762 if (feature) {
12763 /* Feature is up for consideration */
12764 @@ -1064,7 +1142,7 @@
12765
12766 /* while we have a feature */
12767 while (NULL != (tok = strsep(&tmp, "#"))) {
12768 - if ((feature = find_feature(tok))) {
12769 + if ((feature = ast_find_feature(tok))) {
12770 if (ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
12771 if (ast_test_flag(feature, AST_FEATURE_FLAG_CALLER))
12772 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
12773 @@ -1089,7 +1167,7 @@
12774 struct ast_frame *f = NULL;
12775 int res = 0, ready = 0;
12776
12777 - if ((chan = ast_request(type, format, data, &cause))) {
12778 + if ((chan = ast_request(type, format, data, &cause, NULL))) {
12779 ast_set_callerid(chan, cid_num, cid_name, cid_num);
12780 ast_channel_inherit_variables(caller, chan);
12781 if (!ast_call(chan, data, timeout)) {
12782 @@ -1541,9 +1619,10 @@
12783 "Channel: %s\r\n"
12784 "CallerID: %s\r\n"
12785 "CallerIDName: %s\r\n"
12786 + "Uniqueid: %s\r\n\r\n"
12787 ,pu->parkingnum, pu->chan->name
12788 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
12789 - ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
12790 + ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
12791 );
12792
12793 if (option_verbose > 1)
12794 @@ -1586,9 +1665,10 @@
12795 "Channel: %s\r\n"
12796 "CallerID: %s\r\n"
12797 "CallerIDName: %s\r\n"
12798 + "Uniqueid: %s\r\n\r\n"
12799 ,pu->parkingnum, pu->chan->name
12800 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
12801 - ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
12802 + ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
12803 );
12804
12805 /* There's a problem, hang them up*/
12806 @@ -1675,6 +1755,280 @@
12807 return res;
12808 }
12809
12810 +int ast_hold_call(struct ast_channel *chan, struct ast_channel *peer)
12811 +{
12812 + /* We put the user in the parking list, then wake up the parking thread to be sure it looks
12813 + after these channels too */
12814 + struct holdeduser *pu;
12815 + pu = malloc(sizeof(struct holdeduser));
12816 + if (pu) {
12817 + memset(pu, 0, sizeof(pu));
12818 + ast_mutex_lock(&holding_lock);
12819 + chan->appl = "Holded Call";
12820 + chan->data = NULL;
12821 +
12822 + pu->chan = chan;
12823 + strncpy(pu->uniqueid, chan->uniqueid, sizeof(pu->uniqueid));
12824 + strncpy(pu->uniqueidpeer, peer->uniqueid, sizeof(pu->uniqueidpeer));
12825 + /* Start music on hold */
12826 + ast_moh_start(pu->chan, NULL);
12827 + gettimeofday(&pu->start, NULL);
12828 + pu->next = holdlist;
12829 + holdlist = pu;
12830 + ast_mutex_unlock(&holding_lock);
12831 + /* Wake up the (presumably select()ing) thread */
12832 + pthread_kill(holding_thread, SIGURG);
12833 +
12834 + manager_event(EVENT_FLAG_CALL, "HoldedCall",
12835 + "Channel1: %s\r\n"
12836 + "Channel2: %s\r\n"
12837 + "Uniqueid1: %s\r\n"
12838 + "Uniqueid2: %s\r\n"
12839 + ,pu->chan->name, peer->name, pu->chan->uniqueid, peer->uniqueid);
12840 +
12841 + } else {
12842 + ast_log(LOG_WARNING, "Out of memory\n");
12843 + return -1;
12844 + }
12845 + return 0;
12846 +}
12847 +
12848 +int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *peer)
12849 +{
12850 + struct ast_channel *chan;
12851 + struct ast_frame *f;
12852 + /* Make a new, fake channel that we'll use to masquerade in the real one */
12853 + chan = ast_channel_alloc(0);
12854 + if (chan) {
12855 + /* Let us keep track of the channel name */
12856 + snprintf(chan->name, sizeof (chan->name), "Onhold/%s",rchan->name);
12857 + /* Make formats okay */
12858 + chan->readformat = rchan->readformat;
12859 + chan->writeformat = rchan->writeformat;
12860 + ast_channel_masquerade(chan, rchan);
12861 + /* Setup the extensions and such */
12862 + strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
12863 + strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
12864 + chan->priority = rchan->priority;
12865 + /* this might be dirty, but we need to preserve the uniqueid */
12866 + strncpy(chan->uniqueid, rchan->uniqueid, sizeof(chan->uniqueid) - 1);
12867 + /* Make the masq execute */
12868 + f = ast_read(chan);
12869 + if (f)
12870 + ast_frfree(f);
12871 + ast_hold_call(chan, peer);
12872 + return -1;
12873 + } else {
12874 + ast_log(LOG_WARNING, "Unable to create holded channel\n");
12875 + return -1;
12876 + }
12877 + return 0;
12878 +}
12879 +
12880 +int ast_retrieve_call(struct ast_channel *chan, char *uniqueid)
12881 +{
12882 + int res=-1, dres=-1;
12883 + struct ast_channel *peer=NULL;
12884 + struct ast_bridge_config config;
12885 +
12886 + peer = ast_get_holded_call(uniqueid);
12887 +
12888 + /* JK02: it helps to answer the channel if not already up */
12889 + if (chan->_state != AST_STATE_UP) {
12890 + ast_answer(chan);
12891 + }
12892 +
12893 + if (peer) {
12894 + ast_mutex_unlock(&peer->lock);
12895 + ast_moh_stop(peer);
12896 + res = ast_channel_make_compatible(chan, peer);
12897 + if (res < 0) {
12898 + ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
12899 + ast_hangup(peer);
12900 + return -1;
12901 + }
12902 + /* This runs sorta backwards, since we give the incoming channel control, as if it
12903 + were the person called. */
12904 + if (option_verbose > 2)
12905 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to holded call %s\n", chan->name, peer->name);
12906 +
12907 + memset(&config,0,sizeof(struct ast_bridge_config));
12908 + ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
12909 + ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
12910 + config.timelimit = 0;
12911 + config.play_warning = 0;
12912 + config.warning_freq = 0;
12913 + config.warning_sound=NULL;
12914 + res = ast_bridge_call(chan,peer,&config);
12915 +
12916 + /* Simulate the PBX hanging up */
12917 + if (res != AST_PBX_NO_HANGUP_PEER)
12918 + ast_hangup(peer);
12919 + return res;
12920 + } else {
12921 + /* XXX Play a message XXX */
12922 + dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
12923 + if (!dres)
12924 + dres = ast_waitstream(chan, "");
12925 + else {
12926 + ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
12927 + dres = 0;
12928 + }
12929 + }
12930 + return res;
12931 +}
12932 +
12933 +int ast_retrieve_call_to_death(char *uniqueid)
12934 +{
12935 + int res=-1;
12936 + struct ast_channel *peer=NULL;
12937 +
12938 + peer = ast_get_holded_call(uniqueid);
12939 +
12940 + if (peer) {
12941 + res=0;
12942 + if (option_verbose > 2)
12943 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
12944 + ast_mutex_unlock(&peer->lock);
12945 + ast_hangup(peer);
12946 + } else {
12947 + ast_log(LOG_WARNING, "Could not find channel with uniqueid %s to retrieve.\n", uniqueid);
12948 + }
12949 + return res;
12950 +}
12951 +
12952 +struct ast_channel *ast_get_holded_call(char *uniqueid)
12953 +{
12954 + int res=-1;
12955 + struct ast_channel *peer=NULL;
12956 + struct holdeduser *pu, *pl=NULL;
12957 +
12958 + ast_mutex_lock(&holding_lock);
12959 + pu = holdlist;
12960 + while(pu) {
12961 + if (!strncmp(uniqueid,pu->uniqueid,sizeof(pu->uniqueid))) {
12962 + if (pl)
12963 + pl->next = pu->next;
12964 + else
12965 + holdlist = pu->next;
12966 + break;
12967 + }
12968 + pl = pu;
12969 + pu = pu->next;
12970 + }
12971 + ast_mutex_unlock(&holding_lock);
12972 + if (pu) {
12973 + peer = ast_get_channel_by_uniqueid_locked(pu->uniqueid);
12974 + free(pu);
12975 + if (peer) {
12976 + res=0;
12977 + if (option_verbose > 2)
12978 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
12979 + ast_moh_stop(peer);
12980 + return peer;
12981 + } else {
12982 + if (option_verbose > 2)
12983 + ast_verbose(VERBOSE_PREFIX_3 "Could not find channel with uniqueid %s.\n", uniqueid);
12984 + return NULL;
12985 + }
12986 + } else {
12987 + ast_log(LOG_WARNING, "Could not find held channel with uniqueid %s to retrieve.\n", uniqueid);
12988 + }
12989 + return NULL;
12990 +}
12991 +
12992 +/* this is our autmagically service thread that keeps channels onhold happy */
12993 +static void *do_holding_thread(void *ignore)
12994 +{
12995 + int ms, tms, max;
12996 + struct holdeduser *pu, *pl, *pt = NULL;
12997 + struct timeval tv;
12998 + struct ast_frame *f;
12999 + int x;
13000 + fd_set rfds, efds;
13001 + fd_set nrfds, nefds;
13002 + FD_ZERO(&rfds);
13003 + FD_ZERO(&efds);
13004 + for (;;) {
13005 + ms = -1;
13006 + max = -1;
13007 + ast_mutex_lock(&holding_lock);
13008 + pl = NULL;
13009 + pu = holdlist;
13010 + gettimeofday(&tv, NULL);
13011 + FD_ZERO(&nrfds);
13012 + FD_ZERO(&nefds);
13013 + while(pu) {
13014 + tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
13015 + for (x=0;x<AST_MAX_FDS;x++) {
13016 + if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
13017 + /* if (FD_ISSET(pu->chan->fds[x], &efds))
13018 + pu->chan->exception = 1; */
13019 + pu->chan->fdno = x;
13020 + /* See if they need servicing */
13021 + f = ast_read(pu->chan);
13022 + if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
13023 + /* There's a problem, hang them up*/
13024 + if (option_verbose > 1)
13025 + ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being onhold\n", pu->chan->name);
13026 + ast_hangup(pu->chan);
13027 + /* find the corresponding channel and hang them up too! */
13028 + /* but only if it is not bridged yet! */
13029 + /* And take them out of the parking lot */
13030 + if (pl)
13031 + pl->next = pu->next;
13032 + else
13033 + holdlist = pu->next;
13034 + pt = pu;
13035 + pu = pu->next;
13036 + free(pt);
13037 + break;
13038 + } else {
13039 + /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
13040 + ast_frfree(f);
13041 + goto std; /* XXX Ick: jumping into an else statement??? XXX */
13042 + }
13043 + }
13044 + }
13045 + if (x >= AST_MAX_FDS) {
13046 +std: for (x=0;x<AST_MAX_FDS;x++) {
13047 + /* Keep this one for next one */
13048 + if (pu->chan->fds[x] > -1) {
13049 + FD_SET(pu->chan->fds[x], &nrfds);
13050 + FD_SET(pu->chan->fds[x], &nefds);
13051 + if (pu->chan->fds[x] > max)
13052 + max = pu->chan->fds[x];
13053 + }
13054 + }
13055 + /* Keep track of our longest wait */
13056 + if ((tms < ms) || (ms < 0))
13057 + ms = tms;
13058 + pl = pu;
13059 + pu = pu->next;
13060 + }
13061 + }
13062 + ast_mutex_unlock(&holding_lock);
13063 + rfds = nrfds;
13064 + efds = nefds;
13065 + tv.tv_sec = ms / 1000;
13066 + tv.tv_usec = (ms % 1000) * 1000;
13067 + /* Wait for something to happen */
13068 + ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
13069 + pthread_testcancel();
13070 + }
13071 + return NULL; /* Never reached */
13072 +}
13073 +
13074 +static int retrieve_call_exec(struct ast_channel *chan, void *data) {
13075 + int res=0;
13076 + struct localuser *u;
13077 + char *uniqueid = (char *)data;
13078 + LOCAL_USER_ADD(u);
13079 + res = ast_retrieve_call(chan, uniqueid);
13080 + LOCAL_USER_REMOVE(u);
13081 + return res;
13082 +}
13083 +
13084 static int park_exec(struct ast_channel *chan, void *data)
13085 {
13086 int res=0;
13087 @@ -1723,9 +2077,10 @@
13088 "From: %s\r\n"
13089 "CallerID: %s\r\n"
13090 "CallerIDName: %s\r\n"
13091 + "Uniqueid: %s\r\n\r\n"
13092 ,pu->parkingnum, pu->chan->name, chan->name
13093 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
13094 - ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
13095 + ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
13096 );
13097
13098 free(pu);
13099 @@ -1893,12 +2248,13 @@
13100 "Timeout: %ld\r\n"
13101 "CallerID: %s\r\n"
13102 "CallerIDName: %s\r\n"
13103 + "Uniqueid: %s\r\n"
13104 "%s"
13105 "\r\n"
13106 ,cur->parkingnum, cur->chan->name
13107 ,(long)cur->start.tv_sec + (long)(cur->parkingtime/1000) - (long)time(NULL)
13108 ,(cur->chan->cid.cid_num ? cur->chan->cid.cid_num : "")
13109 - ,(cur->chan->cid.cid_name ? cur->chan->cid.cid_name : "")
13110 + ,(cur->chan->cid.cid_name ? cur->chan->cid.cid_name : ""), cur->chan->uniqueid
13111 ,idText);
13112
13113 cur = cur->next;
13114 @@ -1914,6 +2270,386 @@
13115 return RESULT_SUCCESS;
13116 }
13117
13118 +static int handle_autoanswer(int fd, int argc, char *argv[])
13119 +{
13120 + struct aauser *cur;
13121 +
13122 + ast_cli(fd, "%25s %10s %15s \n", "Channel"
13123 + , "Extension", "Context");
13124 +
13125 + ast_mutex_lock(&autoanswer_lock);
13126 +
13127 + cur=aalot;
13128 + while(cur) {
13129 + ast_cli(fd, "%25s %10s %15s\n",cur->chan->name, cur->exten, cur->context);
13130 +
13131 + cur = cur->next;
13132 + }
13133 +
13134 + ast_mutex_unlock(&autoanswer_lock);
13135 +
13136 + return RESULT_SUCCESS;
13137 +}
13138 +static char showautoanswer_help[] =
13139 +"Usage: show autoanswer\n"
13140 +" Lists currently logged in autoanswr channels.\n";
13141 +
13142 +static struct ast_cli_entry showautoanswer =
13143 +{ { "show", "autoanswer", NULL }, handle_autoanswer, "Lists autoanswer channels", showautoanswer_help };
13144 +
13145 +int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data)
13146 +{
13147 + struct ast_channel *chan;
13148 + struct ast_frame *f;
13149 + /* Make a new, fake channel that we'll use to masquerade in the real one */
13150 + chan = ast_channel_alloc(0);
13151 + if (chan) {
13152 + /* Let us keep track of the channel name */
13153 + snprintf(chan->name, sizeof (chan->name), "Autoanswer/%s",rchan->name);
13154 + /* Make formats okay */
13155 + chan->readformat = rchan->readformat;
13156 + chan->writeformat = rchan->writeformat;
13157 + ast_channel_masquerade(chan, rchan);
13158 + /* Setup the extensions and such */
13159 + strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
13160 + strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
13161 + chan->priority = rchan->priority;
13162 + /* Make the masq execute */
13163 + f = ast_read(chan);
13164 + if (f)
13165 + ast_frfree(f);
13166 + ast_autoanswer_login(chan, data);
13167 + } else {
13168 + ast_log(LOG_WARNING, "Unable to create aa channel\n");
13169 + return -1;
13170 + }
13171 + return 0;
13172 +}
13173 +
13174 +static int autoanswer_login_exec(struct ast_channel *chan, void *data)
13175 +{
13176 + int res=0;
13177 + struct localuser *u;
13178 + LOCAL_USER_ADD(u);
13179 + if (!data) {
13180 + ast_log(LOG_WARNING, "AutoanswerLogin requires an argument (extension number)\n");
13181 + return -1;
13182 + }
13183 + res = ast_masq_autoanswer_login(chan, data);
13184 + LOCAL_USER_REMOVE(u);
13185 + return res;
13186 +}
13187 +
13188 +int ast_autoanswer_login(struct ast_channel *chan, void *data)
13189 +{
13190 + /* We put the user in the parking list, then wake up the parking thread to be sure it looks
13191 + after these channels too */
13192 + struct ast_context *con;
13193 + char exten[AST_MAX_EXTENSION];
13194 + struct aauser *pu,*pl = NULL;
13195 + char *s, *stringp, *aacontext, *aaexten = NULL;
13196 +
13197 + s = ast_strdupa((void *) data);
13198 + stringp=s;
13199 + aacontext = strsep(&stringp, "|");
13200 + aaexten = strsep(&stringp, "|");
13201 + if (!aaexten) {
13202 + aaexten = aacontext;
13203 + aacontext = NULL;
13204 + }
13205 + if (!aaexten) {
13206 + ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
13207 + return -1;
13208 + } else {
13209 + if (!aacontext) {
13210 + aacontext = "default";
13211 + }
13212 + }
13213 +
13214 + ast_mutex_lock(&autoanswer_lock);
13215 + pu = aalot;
13216 + while(pu) {
13217 + if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
13218 + if (pl)
13219 + pl->next = pu->next;
13220 + else
13221 + aalot = pu->next;
13222 + break;
13223 + }
13224 + pl = pu;
13225 + pu = pu->next;
13226 + }
13227 + ast_mutex_unlock(&autoanswer_lock);
13228 + if (pu) {
13229 + ast_log(LOG_NOTICE, "Logout old Channel %s for %s@%s.\n",pu->chan->name, pu->exten, pu->context);
13230 + manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
13231 + "Channel: %s\r\n"
13232 + "Uniqueid: %s\r\n"
13233 + "Context: %s\r\n"
13234 + "Exten: %s\r\n"
13235 + ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
13236 + ast_hangup(pu->chan);
13237 + free(pu);
13238 + }
13239 + pu = malloc(sizeof(struct aauser));
13240 + if (pu) {
13241 + memset(pu, 0, sizeof(pu));
13242 + ast_mutex_lock(&autoanswer_lock);
13243 + chan->appl = "Autoanswer";
13244 + chan->data = NULL;
13245 +
13246 + pu->chan = chan;
13247 + if (chan->_state != AST_STATE_UP) {
13248 + ast_answer(chan);
13249 + }
13250 +
13251 + /* Start music on hold */
13252 + ast_moh_start(pu->chan, NULL);
13253 + gettimeofday(&pu->start, NULL);
13254 + strncpy(pu->exten, aaexten, sizeof(pu->exten)-1);
13255 + strncpy(pu->context, aacontext, sizeof(pu->exten)-1);
13256 + pu->next = aalot;
13257 + aalot = pu;
13258 + con = ast_context_find(aacontext);
13259 + if (!con) {
13260 + con = ast_context_create(NULL,aacontext, registrar);
13261 + if (!con) {
13262 + ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", aacontext);
13263 + }
13264 + }
13265 + if (con) {
13266 + snprintf(exten, sizeof(exten), "%s", aaexten);
13267 + ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)data), free, registrar);
13268 + }
13269 +
13270 + ast_mutex_unlock(&autoanswer_lock);
13271 + /* Wake up the (presumably select()ing) thread */
13272 + pthread_kill(autoanswer_thread, SIGURG);
13273 + if (option_verbose > 1)
13274 + ast_verbose(VERBOSE_PREFIX_2 "Autoanswer login from %s for %s@%s.\n", pu->chan->name, pu->exten, pu->context);
13275 + manager_event(EVENT_FLAG_CALL, "AutoanswerLogin",
13276 + "Channel: %s\r\n"
13277 + "Uniqueid: %s\r\n"
13278 + "Context: %s\r\n"
13279 + "Exten: %s\r\n"
13280 + ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
13281 +
13282 + return 0;
13283 + } else {
13284 + ast_log(LOG_WARNING, "Out of memory\n");
13285 + return -1;
13286 + }
13287 + return 0;
13288 +}
13289 +
13290 +static void *do_autoanswer_thread(void *ignore)
13291 +{
13292 + int ms, tms, max;
13293 + struct ast_context *con;
13294 + char exten[AST_MAX_EXTENSION];
13295 + struct aauser *pu, *pl, *pt = NULL;
13296 + struct timeval tv;
13297 + struct ast_frame *f;
13298 + int x;
13299 + fd_set rfds, efds;
13300 + fd_set nrfds, nefds;
13301 + FD_ZERO(&rfds);
13302 + FD_ZERO(&efds);
13303 + for (;;) {
13304 + ms = -1;
13305 + max = -1;
13306 + ast_mutex_lock(&autoanswer_lock);
13307 + pl = NULL;
13308 + pu = aalot;
13309 + gettimeofday(&tv, NULL);
13310 + FD_ZERO(&nrfds);
13311 + FD_ZERO(&nefds);
13312 + while(pu) {
13313 + tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
13314 + for (x=0;x<AST_MAX_FDS;x++) {
13315 + if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
13316 +/* if (FD_ISSET(pu->chan->fds[x], &efds))
13317 + pu->chan->exception = 1; */
13318 + pu->chan->fdno = x;
13319 + /* See if they need servicing */
13320 + f = ast_read(pu->chan);
13321 + if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
13322 + /* There's a problem, hang them up*/
13323 + if (option_verbose > 1)
13324 + ast_verbose(VERBOSE_PREFIX_2 "%s logged out of autoanswer app\n", pu->chan->name);
13325 + manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
13326 + "Channel: %s\r\n"
13327 + "Uniqueid: %s\r\n"
13328 + "Context: %s\r\n"
13329 + "Exten: %s\r\n"
13330 + ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
13331 + ast_hangup(pu->chan);
13332 + con = ast_context_find(pu->context);
13333 + if (con) {
13334 + snprintf(exten, sizeof(exten), "%s", pu->exten);
13335 + if (ast_context_remove_extension2(con, exten, 1, registrar))
13336 + ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
13337 + } else {
13338 + ast_log(LOG_WARNING, "Whoa, no %s context?\n", pu->exten);
13339 + }
13340 + /* And take them out of the parking lot */
13341 + if (pl)
13342 + pl->next = pu->next;
13343 + else
13344 + aalot = pu->next;
13345 + pt = pu;
13346 + pu = pu->next;
13347 + free(pt);
13348 + break;
13349 + } else {
13350 + /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
13351 + ast_frfree(f);
13352 + goto std; /* XXX Ick: jumping into an else statement??? XXX */
13353 + }
13354 + }
13355 + }
13356 + if (x >= AST_MAX_FDS) {
13357 +std: for (x=0;x<AST_MAX_FDS;x++) {
13358 + /* Keep this one for next one */
13359 + if (pu->chan->fds[x] > -1) {
13360 + FD_SET(pu->chan->fds[x], &nrfds);
13361 + FD_SET(pu->chan->fds[x], &nefds);
13362 + if (pu->chan->fds[x] > max)
13363 + max = pu->chan->fds[x];
13364 + }
13365 + }
13366 + /* Keep track of our longest wait */
13367 + if ((tms < ms) || (ms < 0))
13368 + ms = tms;
13369 + pl = pu;
13370 + pu = pu->next;
13371 + }
13372 + }
13373 + ast_mutex_unlock(&autoanswer_lock);
13374 + rfds = nrfds;
13375 + efds = nefds;
13376 + tv.tv_sec = ms / 1000;
13377 + tv.tv_usec = (ms % 1000) * 1000;
13378 + /* Wait for something to happen */
13379 + ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
13380 + pthread_testcancel();
13381 + }
13382 + return NULL; /* Never reached */
13383 +}
13384 +
13385 +static int autoanswer_exec(struct ast_channel *chan, void *data)
13386 +{
13387 + int res=0;
13388 + struct localuser *u;
13389 + struct ast_channel *peer=NULL;
13390 + struct aauser *pu, *pl=NULL;
13391 + struct ast_bridge_config config;
13392 + char *s, *stringp, *aacontext, *aaexten = NULL;
13393 + char datastring[80];
13394 +
13395 + if (!data) {
13396 + ast_log(LOG_WARNING, "Autoanswer requires an argument (extension number)\n");
13397 + return -1;
13398 + }
13399 + s = ast_strdupa((void *) data);
13400 + stringp=s;
13401 + aacontext = strsep(&stringp, "|");
13402 + aaexten = strsep(&stringp, "|");
13403 + if (!aaexten) {
13404 + aaexten = aacontext;
13405 + aacontext = NULL;
13406 + }
13407 + if (!aaexten) {
13408 + ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
13409 + return -1;
13410 + } else {
13411 + if (!aacontext) {
13412 + aacontext = "default";
13413 + }
13414 + }
13415 +
13416 + LOCAL_USER_ADD(u);
13417 + ast_mutex_lock(&autoanswer_lock);
13418 + pu = aalot;
13419 + while(pu) {
13420 + if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
13421 + if (pl)
13422 + pl->next = pu->next;
13423 + else
13424 + aalot = pu->next;
13425 + break;
13426 + }
13427 + pl = pu;
13428 + pu = pu->next;
13429 + }
13430 + ast_mutex_unlock(&autoanswer_lock);
13431 + if (pu) {
13432 + peer = pu->chan;
13433 + free(pu);
13434 + pu = NULL;
13435 + }
13436 + /* JK02: it helps to answer the channel if not already up */
13437 + if (chan->_state != AST_STATE_UP) {
13438 + ast_answer(chan);
13439 + }
13440 +
13441 + if (peer) {
13442 + ast_moh_stop(peer);
13443 + /* Play a courtesy beep in the callED channel to prefix the bridge connecting */
13444 + if (!ast_strlen_zero(courtesytone)) {
13445 + if (!ast_streamfile(peer, courtesytone, peer->language)) {
13446 + if (ast_waitstream(peer, "") < 0) {
13447 + ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
13448 + ast_hangup(peer);
13449 + return -1;
13450 + }
13451 + }
13452 + }
13453 +
13454 + res = ast_channel_make_compatible(chan, peer);
13455 + if (res < 0) {
13456 + ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
13457 + ast_hangup(peer);
13458 + return -1;
13459 + }
13460 + /* This runs sorta backwards, since we give the incoming channel control, as if it
13461 + were the person called. */
13462 + if (option_verbose > 2)
13463 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s autoanswered %s\n", peer->name, chan->name);
13464 + manager_event(EVENT_FLAG_CALL, "Autoanswer",
13465 + "Channel: %s\r\n"
13466 + "Uniqueid: %s\r\n"
13467 + "Channel2: %s\r\n"
13468 + "Uniqueid2: %s\r\n"
13469 + "Context: %s\r\n"
13470 + "Exten: %s\r\n"
13471 + ,chan->name, chan->uniqueid, peer->name, peer->uniqueid, aacontext, aaexten);
13472 +
13473 +
13474 + memset(&config,0,sizeof(struct ast_bridge_config));
13475 + ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
13476 + ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
13477 + config.timelimit = 0;
13478 + config.play_warning = 0;
13479 + config.warning_freq = 0;
13480 + config.warning_sound=NULL;
13481 + res = ast_bridge_call(chan,peer,&config);
13482 +
13483 + if (option_verbose > 2)
13484 + ast_verbose(VERBOSE_PREFIX_3 "returning from bridge %s\n", peer->name);
13485 + /* relogin */
13486 + snprintf(datastring, sizeof(datastring) - 1, "%s|%s", aacontext, aaexten);
13487 + ast_autoanswer_login(peer, datastring);
13488 + return res;
13489 + } else {
13490 + if (option_verbose > 2)
13491 + ast_verbose(VERBOSE_PREFIX_3 "Nobody logged in for autoanswer %s@%s\n", aaexten, aacontext);
13492 + res = -1;
13493 + }
13494 + LOCAL_USER_REMOVE(u);
13495 + return res;
13496 +}
13497 +
13498
13499 int ast_pickup_call(struct ast_channel *chan)
13500 {
13501 @@ -2068,7 +2804,7 @@
13502 }
13503
13504 {
13505 - struct ast_call_feature *feature=find_feature(var->name);
13506 + struct ast_call_feature *feature = ast_find_feature(var->name);
13507 int mallocd=0;
13508
13509 if (!feature) {
13510 @@ -2144,14 +2880,22 @@
13511 if ((res = load_config()))
13512 return res;
13513 ast_cli_register(&showparked);
13514 + ast_cli_register(&showautoanswer);
13515 ast_cli_register(&showfeatures);
13516 ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
13517 + ast_pthread_create(&holding_thread, NULL, do_holding_thread, NULL);
13518 res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
13519 if (!res)
13520 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
13521 if (!res) {
13522 ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" );
13523 }
13524 + res = ast_register_application(holdedcall, retrieve_call_exec, synopsis, descrip);
13525 + ast_pthread_create(&autoanswer_thread, NULL, do_autoanswer_thread, NULL);
13526 + if (!res)
13527 + res = ast_register_application(autoanswerlogin, autoanswer_login_exec, synopsis3, descrip3);
13528 + if (!res)
13529 + res = ast_register_application(autoanswer, autoanswer_exec, synopsis4, descrip4);
13530 return res;
13531 }
13532
13533 @@ -2162,7 +2906,11 @@
13534
13535 ast_manager_unregister("ParkedCalls");
13536 ast_cli_unregister(&showfeatures);
13537 + ast_cli_unregister(&showautoanswer);
13538 ast_cli_unregister(&showparked);
13539 + ast_unregister_application(autoanswer);
13540 + ast_unregister_application(autoanswerlogin);
13541 + ast_unregister_application(holdedcall);
13542 ast_unregister_application(parkcall);
13543 return ast_unregister_application(parkedcall);
13544 }
13545 diff -urN asterisk-1.2.7.1.orig/res/res_watchdog.c asterisk-1.2.7.1/res/res_watchdog.c
13546 --- asterisk-1.2.7.1.orig/res/res_watchdog.c 1970-01-01 01:00:00.000000000 +0100
13547 +++ asterisk-1.2.7.1/res/res_watchdog.c 2006-04-24 09:39:12.000000000 +0200
13548 @@ -0,0 +1,149 @@
13549 +/*
13550 + * Asterisk -- A telephony toolkit for Linux.
13551 + *
13552 + * Resource to make watchdogs happy
13553 + *
13554 + * Copyright (C) 2005, Junghanns.NET GmbH
13555 + *
13556 + * Klaus-Peter Junghanns <kpj@junghanns.net>
13557 + *
13558 + * This program is free software, distributed under the terms of
13559 + * the GNU General Public License
13560 + */
13561 +
13562 +#include <stdlib.h>
13563 +#include <errno.h>
13564 +#include <unistd.h>
13565 +#include <string.h>
13566 +#include <stdlib.h>
13567 +#include <stdio.h>
13568 +#include <sys/time.h>
13569 +#include <sys/signal.h>
13570 +#include <netinet/in.h>
13571 +#include <asterisk/lock.h>
13572 +#include <asterisk/file.h>
13573 +#include <asterisk/logger.h>
13574 +#include <asterisk/channel.h>
13575 +#include <asterisk/pbx.h>
13576 +#include <asterisk/options.h>
13577 +#include <asterisk/module.h>
13578 +#include <asterisk/translate.h>
13579 +#include <asterisk/say.h>
13580 +#include <asterisk/features.h>
13581 +#include <asterisk/musiconhold.h>
13582 +#include <asterisk/config.h>
13583 +#include <asterisk/cli.h>
13584 +#include <asterisk/manager.h>
13585 +#include <asterisk/utils.h>
13586 +#include <asterisk/adsi.h>
13587 +
13588 +static struct watchdog_pvt *watchdogs = NULL;
13589 +
13590 +STANDARD_LOCAL_USER;
13591 +
13592 +LOCAL_USER_DECL;
13593 +
13594 +typedef struct watchdog_pvt {
13595 + char device[80];
13596 + int fd;
13597 + int type;
13598 + int interval;
13599 + pthread_t watchdog_thread;
13600 + struct watchdog_pvt *next;
13601 +} watchdog_pvt;
13602 +
13603 +static void *do_watchdog_thread(void *data) {
13604 + struct watchdog_pvt *woof = (struct watchdog_pvt *)data;
13605 + for (;;) {
13606 + if (woof->fd) {
13607 + write(woof->fd, "PING\n", 1);
13608 + }
13609 + usleep(woof->interval * 1000);
13610 + }
13611 + return NULL;
13612 +}
13613 +
13614 +
13615 +int load_module(void)
13616 +{
13617 + int res = 0;
13618 + char *cat, *utype, *udevice, *uinterval;
13619 + struct ast_config *cfg;
13620 + struct watchdog_pvt *woof = NULL;
13621 +
13622 + cfg = ast_config_load("watchdog.conf");
13623 + if (cfg) {
13624 + cat = ast_category_browse(cfg, NULL);
13625 + while(cat) {
13626 + cat = ast_category_browse(cfg, cat);
13627 + utype = ast_variable_retrieve(cfg, cat, "type");
13628 + if (utype) {
13629 + ast_log(LOG_NOTICE, "type = %s\n", utype);
13630 + }
13631 + udevice = ast_variable_retrieve(cfg, cat, "device");
13632 + if (udevice) {
13633 + ast_log(LOG_NOTICE, "device = %s\n", udevice);
13634 + }
13635 + uinterval = ast_variable_retrieve(cfg, cat, "interval");
13636 + if (uinterval) {
13637 + ast_log(LOG_NOTICE, "interval = %s\n", uinterval);
13638 + }
13639 + if (uinterval && udevice && utype) {
13640 + woof = malloc(sizeof(struct watchdog_pvt));
13641 + if (!woof) {
13642 + ast_log(LOG_ERROR, "unable to malloc!\n");
13643 + return -1;
13644 + }
13645 + memset(woof, 0x0, sizeof(struct watchdog_pvt));
13646 + strncpy(woof->device, udevice, sizeof(woof->device) - 1);
13647 +
13648 + woof->interval = atoi(uinterval);;
13649 + woof->next = watchdogs;
13650 + watchdogs = woof;
13651 + woof->fd = open(woof->device, O_WRONLY | O_SYNC);
13652 + if (woof->fd) {
13653 + if (!strncmp(utype, "isdnguard", sizeof(utype))) {
13654 + woof->type = 1;
13655 + write(woof->fd, "START\n", 6);
13656 + }
13657 + ast_pthread_create(&woof->watchdog_thread, NULL, do_watchdog_thread, woof);
13658 + } else {
13659 + ast_log(LOG_WARNING, "error opening watchdog device %s !\n", woof->device);
13660 + }
13661 + }
13662 + }
13663 + ast_config_destroy(cfg);
13664 + }
13665 + return res;
13666 +}
13667 +
13668 +
13669 +int unload_module(void)
13670 +{
13671 + struct watchdog_pvt *dogs, *woof;
13672 + STANDARD_HANGUP_LOCALUSERS;
13673 + dogs = watchdogs;
13674 + while (dogs) {
13675 + pthread_cancel(dogs->watchdog_thread);
13676 + close(dogs->fd);
13677 + woof = dogs->next;
13678 + free(dogs);
13679 + dogs = woof;
13680 + }
13681 + return 0;
13682 +}
13683 +
13684 +char *description(void)
13685 +{
13686 + return "Watchdog Resource";
13687 +}
13688 +
13689 +int usecount(void)
13690 +{
13691 + return 1;
13692 +}
13693 +
13694 +char *key()
13695 +{
13696 + return ASTERISK_GPL_KEY;
13697 +}
13698 diff -urN asterisk-1.2.7.1.orig/rtp.c asterisk-1.2.7.1/rtp.c
13699 --- asterisk-1.2.7.1.orig/rtp.c 2006-03-15 19:07:06.000000000 +0100
13700 +++ asterisk-1.2.7.1/rtp.c 2006-04-18 14:39:28.000000000 +0200
13701 @@ -442,6 +442,11 @@
13702 struct rtpPayloadType rtpPT;
13703
13704 len = sizeof(sin);
13705 +
13706 + /* XXX SYMPTON CURE, DIRTY FIX, CHECK, BEGIN */
13707 + if (!rtp)
13708 + return &null_frame;
13709 + /* XXX SYMPTON CURE, DIRTY FIX, CHECK, END */
13710
13711 /* Cache where the header will go */
13712 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,