]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/asterisk-1.2.4-ipfire-bristuff-0.3.0-PRE-1l.patch
HinzugefĆ¼gt:
[ipfire-2.x.git] / src / patches / asterisk-1.2.4-ipfire-bristuff-0.3.0-PRE-1l.patch
1 diff -urN asterisk-1.2.4.orig/.version asterisk-1.2.4/.version
2 --- asterisk-1.2.4.orig/.version 2006-01-31 04:55:50.000000000 +0100
3 +++ asterisk-1.2.4/.version 2006-01-31 09:41:43.000000000 +0100
4 @@ -1 +1 @@
5 -1.2.4
6 +1.2.4-BRIstuffed-0.3.0-PRE-1l-for-ipfire
7 diff -urN asterisk-1.2.4.orig/HARDWARE asterisk-1.2.4/HARDWARE
8 --- asterisk-1.2.4.orig/HARDWARE 2005-11-29 19:24:39.000000000 +0100
9 +++ asterisk-1.2.4/HARDWARE 2006-01-31 09:41:43.000000000 +0100
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 + * quadGSM PCI ISDN - 4 channel GSM interface
26 +
27 Non-zaptel compatible hardware
28 ==============================
29
30 diff -urN asterisk-1.2.4.orig/LICENSE asterisk-1.2.4/LICENSE
31 --- asterisk-1.2.4.orig/LICENSE 2005-11-29 19:24:39.000000000 +0100
32 +++ asterisk-1.2.4/LICENSE 2006-01-31 09:41:43.000000000 +0100
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.4.orig/Makefile asterisk-1.2.4/Makefile
46 --- asterisk-1.2.4.orig/Makefile 2005-12-05 07:47:51.000000000 +0100
47 +++ asterisk-1.2.4/Makefile 2006-01-31 09:41:43.000000000 +0100
48 @@ -759,6 +759,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.4.orig/README asterisk-1.2.4/README
59 --- asterisk-1.2.4.orig/README 2005-11-29 19:24:39.000000000 +0100
60 +++ asterisk-1.2.4/README 2006-01-31 09:41:43.000000000 +0100
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.4.orig/README.chan_capi asterisk-1.2.4/README.chan_capi
71 --- asterisk-1.2.4.orig/README.chan_capi 1970-01-01 01:00:00.000000000 +0100
72 +++ asterisk-1.2.4/README.chan_capi 2006-01-31 09:41:43.000000000 +0100
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.4.orig/agi/Makefile asterisk-1.2.4/agi/Makefile
221 --- asterisk-1.2.4.orig/agi/Makefile 2005-11-29 19:24:39.000000000 +0100
222 +++ asterisk-1.2.4/agi/Makefile 2006-01-31 09:41:43.000000000 +0100
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+=
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.4.orig/agi/xagi-test.c asterisk-1.2.4/agi/xagi-test.c
242 --- asterisk-1.2.4.orig/agi/xagi-test.c 1970-01-01 01:00:00.000000000 +0100
243 +++ asterisk-1.2.4/agi/xagi-test.c 2006-01-31 09:41:43.000000000 +0100
244 @@ -0,0 +1,176 @@
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 NULL;
325 + }
326 + astresp[strlen(astresp) - 1] = '\0';
327 + fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
328 + return astresp;
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 + int bytes = 0;
347 + static char astresp[256];
348 + char audiobuf[4096];
349 + for (;;) {
350 + FD_ZERO(&fds);
351 + FD_SET(STDIN_FILENO, &fds);
352 + FD_SET(AUDIO_FILENO_IN, &fds);
353 + /* Wait for *some* sort of I/O */
354 + res = select(AUDIO_FILENO_IN + 1, &fds, NULL, NULL, NULL);
355 + if (res < 0) {
356 + fprintf(stderr, "Error in select: %s\n", strerror(errno));
357 + return NULL;
358 + }
359 + if (FD_ISSET(STDIN_FILENO, &fds)) {
360 + fgets(astresp, sizeof(astresp), stdin);
361 + if (feof(stdin)) {
362 + fprintf(stderr, "Got hungup on apparently\n");
363 + return NULL;
364 + }
365 + astresp[strlen(astresp) - 1] = '\0';
366 + fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
367 + return astresp;
368 + }
369 + if (FD_ISSET(AUDIO_FILENO_IN, &fds)) {
370 + res = read(AUDIO_FILENO_IN, audiobuf, sizeof(audiobuf));
371 + /* drop it, like it's hot */
372 + }
373 + }
374 +
375 +}
376 +
377 +static char *run_command(char *command)
378 +{
379 + fprintf(stdout, "%s\n", command);
380 + return wait_result();
381 +}
382 +
383 +
384 +static int run_script(void)
385 +{
386 + char *res;
387 + res = run_command("STREAM FILE demo-echotest \"\"");
388 + if (!res) {
389 + fprintf(stderr, "Failed to execute command\n");
390 + return -1;
391 + }
392 + app_echo();
393 + return 0;
394 +}
395 +
396 +int main(int argc, char *argv[])
397 +{
398 + char *tmp;
399 + int ver = 0;
400 + int subver = 0;
401 + /* Setup stdin/stdout for line buffering */
402 + setlinebuf(stdin);
403 + setlinebuf(stdout);
404 + if (read_environment()) {
405 + fprintf(stderr, "Failed to read environment: %s\n", strerror(errno));
406 + exit(1);
407 + }
408 + tmp = getenv("agi_enhanced");
409 + if (tmp) {
410 + if (sscanf(tmp, "%d.%d", &ver, &subver) != 2)
411 + ver = 0;
412 + }
413 + if (ver < 2) {
414 + fprintf(stderr, "No XAGI services available. Use XAGI, not AGI or EAGI\n");
415 + exit(1);
416 + }
417 + if (run_script())
418 + return -1;
419 + exit(0);
420 +}
421 diff -urN asterisk-1.2.4.orig/apps/Makefile asterisk-1.2.4/apps/Makefile
422 --- asterisk-1.2.4.orig/apps/Makefile 2005-11-29 19:24:39.000000000 +0100
423 +++ asterisk-1.2.4/apps/Makefile 2006-01-31 09:41:43.000000000 +0100
424 @@ -28,8 +28,15 @@
425 app_test.so app_forkcdr.so app_math.so app_realtime.so \
426 app_dumpchan.so app_waitforsilence.so app_while.so app_setrdnis.so \
427 app_md5.so app_readfile.so app_chanspy.so app_settransfercapability.so \
428 + app_pickup.so app_segfault.so app_callingpres.so app_devstate.so \
429 app_dictate.so app_externalivr.so app_directed_pickup.so \
430 - app_mixmonitor.so app_stack.so
431 + app_mixmonitor.so app_stack.so
432 +
433 +
434 +ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/capi20.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/capi20.h),)
435 + APPS+= app_capiNoES.so app_capiCD.so app_capiECT.so
436 +endif
437 +
438
439 #
440 # Obsolete things...
441 diff -urN asterisk-1.2.4.orig/apps/app_callingpres.c asterisk-1.2.4/apps/app_callingpres.c
442 --- asterisk-1.2.4.orig/apps/app_callingpres.c 1970-01-01 01:00:00.000000000 +0100
443 +++ asterisk-1.2.4/apps/app_callingpres.c 2006-01-31 09:41:43.000000000 +0100
444 @@ -0,0 +1,70 @@
445 +/*
446 + * An application to change the CallingPresentation for an Asterisk channel.
447 + *
448 + * Copyright (C) 2005 Junghanns.NET GmbH
449 + * Klaus-Peter Junghanns <kpj@junghanns.net>
450 + *
451 + * This program is free software, distributed under the terms of
452 + * the GNU General Public License.
453 + *
454 + */
455 +
456 +#include <stdlib.h>
457 +#include <unistd.h>
458 +#include <string.h>
459 +#include <stdio.h>
460 +#include <asterisk/lock.h>
461 +#include <asterisk/file.h>
462 +#include <asterisk/logger.h>
463 +#include <asterisk/channel.h>
464 +#include <asterisk/pbx.h>
465 +#include <asterisk/module.h>
466 +
467 +static char *synopsis_callingpres = "Change the presentation for the callerid";
468 +static char *descrip_callingpres = "Callingpres(number): Changes the presentation for the callerid. Should be called before placing an outgoing call\n";
469 +static char *app_callingpres = "CallingPres";
470 +STANDARD_LOCAL_USER;
471 +LOCAL_USER_DECL;
472 +
473 +
474 +static int change_callingpres(struct ast_channel *chan, void *data)
475 +{
476 + int mode = 0;
477 + struct localuser *u;
478 + LOCAL_USER_ADD(u);
479 + if (data) {
480 + mode = atoi((char *)data);
481 + chan->cid.cid_pres = mode;
482 + } else
483 + ast_log(LOG_NOTICE, "Application %s requres an argument: %s(number)\n", app_callingpres,app_callingpres);
484 + LOCAL_USER_REMOVE(u);
485 + return 0;
486 +}
487 +
488 +int unload_module(void)
489 +{
490 + STANDARD_HANGUP_LOCALUSERS;
491 + return ast_unregister_application(app_callingpres);
492 +}
493 +
494 +int load_module(void)
495 +{
496 + return ast_register_application(app_callingpres, change_callingpres, synopsis_callingpres, descrip_callingpres);
497 +}
498 +
499 +char *description(void)
500 +{
501 + return descrip_callingpres;
502 +}
503 +
504 +int usecount(void)
505 +{
506 + int res;
507 + STANDARD_USECOUNT(res);
508 + return res;
509 +}
510 +
511 +char *key()
512 +{
513 + return ASTERISK_GPL_KEY;
514 +}
515 diff -urN asterisk-1.2.4.orig/apps/app_capiCD.c asterisk-1.2.4/apps/app_capiCD.c
516 --- asterisk-1.2.4.orig/apps/app_capiCD.c 1970-01-01 01:00:00.000000000 +0100
517 +++ asterisk-1.2.4/apps/app_capiCD.c 2006-01-31 09:41:43.000000000 +0100
518 @@ -0,0 +1,172 @@
519 +/*
520 + * (CAPI*)
521 + *
522 + * An implementation of Common ISDN API 2.0 for Asterisk
523 + *
524 + * Call Deflection, inspired by capircvd by Alexander Brickwedde
525 + *
526 + * Copyright (C) 2002,2003,2004,2005 Junghanns.NET GmbH
527 + *
528 + * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
529 + *
530 + * This program is free software and may be modified and
531 + * distributed under the terms of the GNU Public License.
532 + */
533 +
534 +#include <stdlib.h>
535 +#include <unistd.h>
536 +#include <string.h>
537 +#include <stdio.h>
538 +#include <linux/capi.h>
539 +#include <capi20.h>
540 +
541 +#include <asterisk/file.h>
542 +#include <asterisk/logger.h>
543 +#include <asterisk/channel.h>
544 +#include <asterisk/pbx.h>
545 +#include <asterisk/module.h>
546 +#include <asterisk/chan_capi.h>
547 +#include <asterisk/chan_capi_app.h>
548 +
549 +
550 +
551 +static char *tdesc = "(CAPI*) Call Deflection, the magic thing.";
552 +static char *app = "capiCD";
553 +static char *synopsis = "call deflection";
554 +
555 +STANDARD_LOCAL_USER;
556 +
557 +LOCAL_USER_DECL;
558 +
559 +static int capiCD_exec(struct ast_channel *chan, void *data)
560 +{
561 + struct ast_capi_pvt *i = chan->tech_pvt;
562 + MESSAGE_EXCHANGE_ERROR Info;
563 + _cmsg CMSG;
564 + char bchaninfo[1];
565 + char fac[60];
566 + int res=0;
567 + int ms=3000;
568 + struct localuser *u;
569 +
570 + if (!data) {
571 + ast_log(LOG_WARNING, "cd requires an argument (destination phone number)\n");
572 + return -1;
573 + }
574 + LOCAL_USER_ADD(u);
575 + /* Do our thing here */
576 +
577 + if ((i->state == CAPI_STATE_CONNECTED) || (i->state == CAPI_STATE_BCONNECTED)) {
578 + ast_log(LOG_ERROR, "call deflection does not work with calls that are already connected!\n");
579 + LOCAL_USER_REMOVE(u);
580 + return -1;
581 + }
582 + // wait until the channel is alerting, so we dont drop the call and interfer with msgs
583 + while ((ms > 0) && (i->state != CAPI_STATE_ALERTING)) {
584 + sleep(100);
585 + ms -= 100;
586 + }
587 +
588 + // make sure we hang up correctly
589 + i->state = CAPI_STATE_CONNECTPENDING;
590 +
591 + fac[0]=0; // len
592 + fac[1]=0; //len
593 + fac[2]=0x01; // Use D-Chan
594 + fac[3]=0; // Keypad len
595 + fac[4]=31; // user user data? len = 31 = 29 + 2
596 + fac[5]=0x1c; // magic?
597 + fac[6]=0x1d; // strlen destination + 18 = 29
598 + fac[7]=0x91; // ..
599 + fac[8]=0xA1;
600 + fac[9]=0x1A; // strlen destination + 15 = 26
601 + fac[10]=0x02;
602 + fac[11]=0x01;
603 + fac[12]=0x70;
604 + fac[13]=0x02;
605 + fac[14]=0x01;
606 + fac[15]=0x0d;
607 + fac[16]=0x30;
608 + fac[17]=0x12; // strlen destination + 7 = 18
609 + fac[18]=0x30; // ...hm 0x30
610 + fac[19]=0x0d; // strlen destination + 2
611 + fac[20]=0x80; // CLIP
612 + fac[21]=0x0b; // strlen destination
613 + fac[22]=0x01; // destination start
614 + fac[23]=0x01; //
615 + fac[24]=0x01; //
616 + fac[25]=0x01; //
617 + fac[26]=0x01; //
618 + fac[27]=0x01; //
619 + fac[28]=0x01; //
620 + fac[29]=0x01; //
621 + fac[30]=0x01; //
622 + fac[31]=0x01; //
623 + fac[32]=0x01; //
624 + fac[33]=0x01; // 0x1 = sending complete
625 + fac[34]=0x01;
626 + fac[35]=0x01;
627 +
628 + memcpy((unsigned char *)fac+22,data,strlen(data));
629 + fac[22+strlen(data)]=0x01; // fill with 0x01 if number is only 6 numbers (local call)
630 + fac[23+strlen(data)]=0x01;
631 + fac[24+strlen(data)]=0x01;
632 + fac[25+strlen(data)]=0x01;
633 + fac[26+strlen(data)]=0x01;
634 +
635 + fac[6]=18+strlen(data);
636 + fac[9]=15+strlen(data);
637 + fac[17]=7+strlen(data);
638 + fac[19]=2+strlen(data);
639 + fac[21]=strlen(data);
640 +
641 + bchaninfo[0] = 0x1;
642 + INFO_REQ_HEADER(&CMSG,ast_capi_ApplID,ast_capi_MessageNumber++,0);
643 + INFO_REQ_CONTROLLER(&CMSG) = i->controller;
644 + INFO_REQ_PLCI(&CMSG) = i->PLCI;
645 + INFO_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char*)bchaninfo; // use D-Channel
646 + INFO_REQ_KEYPADFACILITY(&CMSG) = 0;
647 + INFO_REQ_USERUSERDATA(&CMSG) = 0;
648 + INFO_REQ_FACILITYDATAARRAY(&CMSG) = (unsigned char*) fac + 4;
649 +
650 + if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
651 + ast_log(LOG_ERROR,"Error sending INFO_REQ\n");
652 + return Info;
653 + } else {
654 + if (capidebug) {
655 + // ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(&CMSG));
656 + ast_log(LOG_NOTICE,"sent INFO_REQ PLCI = %#x\n",i->PLCI);
657 + }
658 + }
659 +
660 + LOCAL_USER_REMOVE(u);
661 + return res;
662 +}
663 +
664 +int unload_module(void)
665 +{
666 + STANDARD_HANGUP_LOCALUSERS;
667 + return ast_unregister_application(app);
668 +}
669 +
670 +int load_module(void)
671 +{
672 + return ast_register_application(app, capiCD_exec,synopsis,tdesc);
673 +}
674 +
675 +char *description(void)
676 +{
677 + return tdesc;
678 +}
679 +
680 +int usecount(void)
681 +{
682 + int res;
683 + STANDARD_USECOUNT(res);
684 + return res;
685 +}
686 +
687 +char *key()
688 +{
689 + return ASTERISK_GPL_KEY;
690 +}
691 diff -urN asterisk-1.2.4.orig/apps/app_capiECT.c asterisk-1.2.4/apps/app_capiECT.c
692 --- asterisk-1.2.4.orig/apps/app_capiECT.c 1970-01-01 01:00:00.000000000 +0100
693 +++ asterisk-1.2.4/apps/app_capiECT.c 2006-01-31 09:41:43.000000000 +0100
694 @@ -0,0 +1,210 @@
695 +/*
696 + * (CAPI*)
697 + *
698 + * An implementation of Common ISDN API 2.0 for Asterisk
699 + *
700 + * ECT transfer the held call
701 + *
702 + * Copyright (C) 2002,2003,2004,2005 Junghanns.NET GmbH
703 + *
704 + * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
705 + *
706 + * This program is free software and may be modified and
707 + * distributed under the terms of the GNU Public License.
708 + */
709 +
710 +#include <stdlib.h>
711 +#include <unistd.h>
712 +#include <string.h>
713 +#include <stdio.h>
714 +#include <linux/capi.h>
715 +#include <capi20.h>
716 +#include <asterisk/file.h>
717 +#include <asterisk/logger.h>
718 +#include <asterisk/channel.h>
719 +#include <asterisk/pbx.h>
720 +#include <asterisk/module.h>
721 +#include <asterisk/say.h>
722 +#include <asterisk/chan_capi.h>
723 +#include <asterisk/chan_capi_app.h>
724 +
725 +
726 +static char *tdesc = "(CAPI*) ECT";
727 +static char *app = "capiECT";
728 +static char *synopsis = "transfer the call that is on hold";
729 +
730 +STANDARD_LOCAL_USER;
731 +
732 +LOCAL_USER_DECL;
733 +
734 +
735 +static int capiECT_exec(struct ast_channel *chan, void *data)
736 +{
737 + struct ast_capi_pvt *i = chan->tech_pvt;
738 + MESSAGE_EXCHANGE_ERROR Info;
739 + _cmsg CMSG;
740 + unsigned char fac[8];
741 + int res=0;
742 + struct localuser *u;
743 + char *ecodes = "*#";
744 +
745 + if (!data) {
746 + ast_log(LOG_WARNING, "ECT requires an argument (destination phone number)\n");
747 + return -1;
748 + }
749 + LOCAL_USER_ADD(u);
750 + /* Do our thing here */
751 + if (i->onholdPLCI <= 0) {
752 + ast_log(LOG_WARNING, "no call on hold that could be transfered\n");
753 + return -1;
754 + }
755 +
756 + ast_log(LOG_NOTICE,"ECT to %s\n",(char *)data);
757 + capi_call(chan,data,0);
758 +
759 + while ((i->state != CAPI_STATE_BCONNECTED) && (i->onholdPLCI != 0)) {
760 + usleep(10000);
761 + }
762 +
763 +
764 + if (i->state == CAPI_STATE_BCONNECTED) {
765 + ast_log(LOG_NOTICE,"call was answered\n");
766 +
767 + capi_detect_dtmf(chan,1);
768 +
769 + // put the stuff to play announcement message here ---> <-----
770 + res = ast_say_digit_str(chan,i->cid,ecodes,chan->language);
771 + if ( res == '#') {
772 + ast_log(LOG_NOTICE,"res = %d\n",res);
773 + // user pressed #, hangup
774 + // first the holded user
775 +// ast_exec("capiRETRIEVE",chan);
776 +
777 + DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
778 + DISCONNECT_REQ_PLCI(&CMSG) = i->onholdPLCI;
779 +
780 + if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
781 + ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",i->onholdPLCI);
782 + } else {
783 + ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",i->onholdPLCI);
784 + }
785 +
786 + // then the destination
787 +
788 + DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
789 + DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
790 +
791 + if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
792 + ast_log(LOG_NOTICE, "error sending DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
793 + } else {
794 + ast_log(LOG_NOTICE, "sent DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
795 + }
796 +
797 + // wait for the B3 layer to go down
798 + while (i->state != CAPI_STATE_CONNECTED) {
799 + usleep(10000);
800 + }
801 +
802 + DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
803 + DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
804 +
805 + if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
806 + ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
807 + } else {
808 + ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
809 + }
810 +
811 +
812 + LOCAL_USER_REMOVE(u);
813 + return -1;
814 +
815 + } else {
816 + // now drop the bchannel
817 + DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
818 + DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
819 +
820 + if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
821 + ast_log(LOG_NOTICE, "error sending DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
822 + } else {
823 + ast_log(LOG_NOTICE, "sent DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
824 + }
825 +
826 + // wait for the B3 layer to go down
827 + while (i->state != CAPI_STATE_CONNECTED) {
828 + usleep(10000);
829 + }
830 + }
831 + }
832 +
833 + // the caller onhold hungup or died away, drop the answered call
834 + if (i->onholdPLCI == 0) {
835 + DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
836 + DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
837 +
838 + if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
839 + ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
840 + } else {
841 + ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
842 + }
843 + return -1;
844 + }
845 +
846 + ast_log(LOG_NOTICE,"onholdPLCI = %d\n",i->onholdPLCI);
847 +
848 +
849 + fac[0] = 7; // len
850 + fac[1] = 0x06; // ECT (function)
851 + fac[2] = 0x00;
852 + fac[3] = 4; //len //sservice specific parameter , cstruct
853 + fac[4] = (i->onholdPLCI << 8 ) >> 8;
854 + fac[5] = i->onholdPLCI >> 8;
855 + fac[6] = 0;
856 + fac[7] = 0;
857 +
858 + FACILITY_REQ_HEADER(&CMSG,ast_capi_ApplID,ast_capi_MessageNumber++,0);
859 + FACILITY_REQ_CONTROLLER(&CMSG) = i->controller;
860 + FACILITY_REQ_PLCI(&CMSG) = i->onholdPLCI;
861 + FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 0x0003; // sservices
862 + FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = (unsigned char *)&fac;
863 +
864 + if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
865 + ast_log(LOG_ERROR,"Error sending FACILITY_REQ\n");
866 + return Info;
867 + } else {
868 + ast_log(LOG_NOTICE,"sent FACILITY_REQ PLCI = %#x (%#x %#x) onholdPLCI = %#x\n ",i->PLCI,fac[4],fac[5],i->onholdPLCI);
869 + ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(&CMSG));
870 + }
871 +
872 +// i->outgoing = -1; // incoming + outgoing, this is a magic channel :)
873 +
874 + LOCAL_USER_REMOVE(u);
875 + return res;
876 +}
877 +
878 +int unload_module(void)
879 +{
880 + STANDARD_HANGUP_LOCALUSERS;
881 + return ast_unregister_application(app);
882 +}
883 +
884 +int load_module(void)
885 +{
886 + return ast_register_application(app, capiECT_exec,synopsis,tdesc);
887 +}
888 +
889 +char *description(void)
890 +{
891 + return tdesc;
892 +}
893 +
894 +int usecount(void)
895 +{
896 + int res;
897 + STANDARD_USECOUNT(res);
898 + return res;
899 +}
900 +
901 +char *key()
902 +{
903 + return ASTERISK_GPL_KEY;
904 +}
905 diff -urN asterisk-1.2.4.orig/apps/app_capiNoES.c asterisk-1.2.4/apps/app_capiNoES.c
906 --- asterisk-1.2.4.orig/apps/app_capiNoES.c 1970-01-01 01:00:00.000000000 +0100
907 +++ asterisk-1.2.4/apps/app_capiNoES.c 2006-01-31 09:41:43.000000000 +0100
908 @@ -0,0 +1,96 @@
909 +/*
910 + * (CAPI*)
911 + *
912 + * An implementation of Common ISDN API 2.0 for Asterisk
913 + *
914 + * Disable echo suppression (useful for fax and voicemail!)
915 + *
916 + * Copyright (C) 2004,2005 Junghanns.NET GmbH
917 + *
918 + * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
919 + *
920 + * This program is free software and may be modified and
921 + * distributed under the terms of the GNU Public License.
922 + */
923 +
924 +#include <stdlib.h>
925 +#include <unistd.h>
926 +#include <string.h>
927 +#include <stdio.h>
928 +#include <linux/capi.h>
929 +#include <capi20.h>
930 +
931 +#include <asterisk/file.h>
932 +#include <asterisk/logger.h>
933 +#include <asterisk/channel.h>
934 +#include <asterisk/pbx.h>
935 +#include <asterisk/module.h>
936 +#include <asterisk/chan_capi_app.h>
937 +
938 +
939 +
940 +#ifdef CAPI_ES
941 +static char *tdesc = "(CAPI*) No Echo Suppression.";
942 +static char *app = "capiNoES";
943 +static char *synopsis = "Disable Echo Suppression";
944 +#else
945 +static char *tdesc = "(CAPI*) No Echo Suppression at all!";
946 +static char *app = "capiNoES";
947 +static char *synopsis = "Bogus Application";
948 +#endif
949 +STANDARD_LOCAL_USER;
950 +
951 +LOCAL_USER_DECL;
952 +
953 +static int capiNoES_exec(struct ast_channel *chan, void *data)
954 +{
955 + int res=0;
956 + struct localuser *u;
957 + LOCAL_USER_ADD(u);
958 +
959 +#ifdef CAPI_ES
960 + if (strcasecmp("CAPI",chan->type) == 0) {
961 +#ifdef CVS_HEAD
962 + struct ast_capi_pvt *i = chan->tech_pvt;
963 +#else
964 + struct ast_capi_pvt *i = chan->pvt->pvt;
965 +#endif
966 + if (i->doES == 1) {
967 + i->doES = 0;
968 + }
969 + } else {
970 + ast_log(LOG_WARNING, "capiNoES only works on CAPI channels, check your extensions.conf!\n");
971 + }
972 +#endif
973 +
974 + LOCAL_USER_REMOVE(u);
975 + return res;
976 +}
977 +
978 +int unload_module(void)
979 +{
980 + STANDARD_HANGUP_LOCALUSERS;
981 + return ast_unregister_application(app);
982 +}
983 +
984 +int load_module(void)
985 +{
986 + return ast_register_application(app, capiNoES_exec,synopsis,tdesc);
987 +}
988 +
989 +char *description(void)
990 +{
991 + return tdesc;
992 +}
993 +
994 +int usecount(void)
995 +{
996 + int res;
997 + STANDARD_USECOUNT(res);
998 + return res;
999 +}
1000 +
1001 +char *key()
1002 +{
1003 + return ASTERISK_GPL_KEY;
1004 +}
1005 diff -urN asterisk-1.2.4.orig/apps/app_chanisavail.c asterisk-1.2.4/apps/app_chanisavail.c
1006 --- asterisk-1.2.4.orig/apps/app_chanisavail.c 2005-11-29 19:24:39.000000000 +0100
1007 +++ asterisk-1.2.4/apps/app_chanisavail.c 2006-01-31 09:41:43.000000000 +0100
1008 @@ -118,7 +118,7 @@
1009 snprintf(trychan, sizeof(trychan), "%s/%s",cur,number);
1010 status = inuse = ast_device_state(trychan);
1011 }
1012 - if ((inuse <= 1) && (tempchan = ast_request(tech, chan->nativeformats, number, &status))) {
1013 + if ((inuse <= 1) && (tempchan = ast_request(tech, chan->nativeformats, number, &status, NULL))) {
1014 pbx_builtin_setvar_helper(chan, "AVAILCHAN", tempchan->name);
1015 /* Store the originally used channel too */
1016 snprintf(tmp, sizeof(tmp), "%s/%s", tech, number);
1017 diff -urN asterisk-1.2.4.orig/apps/app_devstate.c asterisk-1.2.4/apps/app_devstate.c
1018 --- asterisk-1.2.4.orig/apps/app_devstate.c 1970-01-01 01:00:00.000000000 +0100
1019 +++ asterisk-1.2.4/apps/app_devstate.c 2006-01-31 09:41:43.000000000 +0100
1020 @@ -0,0 +1,219 @@
1021 +/*
1022 + * Devstate application
1023 + *
1024 + * Since we like the snom leds so much, a little app to
1025 + * light the lights on the snom on demand ....
1026 + *
1027 + * Copyright (C) 2005, Druid Software
1028 + *
1029 + * This program is free software, distributed under the terms of
1030 + * the GNU General Public License
1031 + */
1032 +
1033 +#include <stdlib.h>
1034 +#include <unistd.h>
1035 +#include <string.h>
1036 +#include <stdio.h>
1037 +#include <asterisk/lock.h>
1038 +#include <asterisk/file.h>
1039 +#include <asterisk/logger.h>
1040 +#include <asterisk/channel.h>
1041 +#include <asterisk/pbx.h>
1042 +#include <asterisk/module.h>
1043 +#include <asterisk/astdb.h>
1044 +#include <asterisk/utils.h>
1045 +#include <asterisk/cli.h>
1046 +#include <asterisk/manager.h>
1047 +#include <asterisk/devicestate.h>
1048 +
1049 +
1050 +static char type[] = "DS";
1051 +static char tdesc[] = "Application for sending device state messages";
1052 +
1053 +static char app[] = "Devstate";
1054 +
1055 +static char synopsis[] = "Generate a device state change event given the input parameters";
1056 +
1057 +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";
1058 +
1059 +static char devstate_cli_usage[] =
1060 +"Usage: devstate device state\n"
1061 +" Generate a device state change event given the input parameters.\n Mainly used for lighting the LEDs on the snoms.\n";
1062 +
1063 +static int devstate_cli(int fd, int argc, char *argv[]);
1064 +static struct ast_cli_entry cli_dev_state =
1065 + { { "devstate", NULL }, devstate_cli, "Set the device state on one of the \"pseudo devices\".", devstate_cli_usage };
1066 +
1067 +STANDARD_LOCAL_USER;
1068 +
1069 +LOCAL_USER_DECL;
1070 +
1071 +
1072 +static int devstate_cli(int fd, int argc, char *argv[])
1073 +{
1074 + char devName[128];
1075 + if ((argc != 3) && (argc != 4))
1076 + return RESULT_SHOWUSAGE;
1077 +
1078 + if (ast_db_put("DEVSTATES", argv[1], argv[2]))
1079 + {
1080 + ast_log(LOG_DEBUG, "ast_db_put failed\n");
1081 + }
1082 + snprintf(devName, sizeof(devName), "DS/%s", argv[1]);
1083 + if (argc == 4) {
1084 + ast_log(LOG_NOTICE, "devname %s cid %s\n", devName, argv[3]);
1085 + ast_device_state_changed_literal(devName, argv[3], NULL);
1086 + } else {
1087 + ast_device_state_changed_literal(devName, NULL, NULL);
1088 + }
1089 + return RESULT_SUCCESS;
1090 +}
1091 +
1092 +static int devstate_exec(struct ast_channel *chan, void *data)
1093 +{
1094 + struct localuser *u;
1095 + char *device, *state, *info;
1096 + char devName[128];
1097 + if (!(info = ast_strdupa(data))) {
1098 + ast_log(LOG_WARNING, "Unable to dupe data :(\n");
1099 + return -1;
1100 + }
1101 + LOCAL_USER_ADD(u);
1102 +
1103 + device = info;
1104 + state = strchr(info, '|');
1105 + if (state) {
1106 + *state = '\0';
1107 + state++;
1108 + }
1109 + else
1110 + {
1111 + ast_log(LOG_DEBUG, "No state argument supplied\n");
1112 + return -1;
1113 + }
1114 +
1115 + if (ast_db_put("DEVSTATES", device, state))
1116 + {
1117 + ast_log(LOG_DEBUG, "ast_db_put failed\n");
1118 + }
1119 +
1120 + snprintf(devName, sizeof(devName), "DS/%s", device);
1121 + ast_device_state_changed_literal(devName, NULL, NULL);
1122 +
1123 + LOCAL_USER_REMOVE(u);
1124 + return 0;
1125 +}
1126 +
1127 +
1128 +static int ds_devicestate(void *data)
1129 +{
1130 + char *dest = data;
1131 + char stateStr[16];
1132 + if (ast_db_get("DEVSTATES", dest, stateStr, sizeof(stateStr)))
1133 + {
1134 + ast_log(LOG_DEBUG, "ds_devicestate couldnt get state in astdb\n");
1135 + return 0;
1136 + }
1137 + else
1138 + {
1139 + ast_log(LOG_DEBUG, "ds_devicestate dev=%s returning state %d\n",
1140 + dest, atoi(stateStr));
1141 + return (atoi(stateStr));
1142 + }
1143 +}
1144 +
1145 +static struct ast_channel_tech devstate_tech = {
1146 + .type = type,
1147 + .description = tdesc,
1148 + .capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
1149 + .devicestate = ds_devicestate,
1150 + .requester = NULL,
1151 + .send_digit = NULL,
1152 + .send_text = NULL,
1153 + .call = NULL,
1154 + .hangup = NULL,
1155 + .answer = NULL,
1156 + .read = NULL,
1157 + .write = NULL,
1158 + .bridge = NULL,
1159 + .exception = NULL,
1160 + .indicate = NULL,
1161 + .fixup = NULL,
1162 + .setoption = NULL,
1163 +};
1164 +
1165 +static char mandescr_devstate[] =
1166 +"Description: Put a value into astdb\n"
1167 +"Variables: \n"
1168 +" Family: ...\n"
1169 +" Key: ...\n"
1170 +" Value: ...\n";
1171 +
1172 +static int action_devstate(struct mansession *s, struct message *m)
1173 +{
1174 + char *devstate = astman_get_header(m, "Devstate");
1175 + char *value = astman_get_header(m, "Value");
1176 + char *id = astman_get_header(m,"ActionID");
1177 + char devName[128];
1178 +
1179 + if (!strlen(devstate)) {
1180 + astman_send_error(s, m, "No Devstate specified");
1181 + return 0;
1182 + }
1183 + if (!strlen(value)) {
1184 + astman_send_error(s, m, "No Value specified");
1185 + return 0;
1186 + }
1187 +
1188 + if (!ast_db_put("DEVSTATES", devstate, value)) {
1189 + snprintf(devName, sizeof(devName), "DS/%s", devstate);
1190 + ast_device_state_changed(devName);
1191 + ast_cli(s->fd, "Response: Success\r\n");
1192 + } else {
1193 + ast_log(LOG_DEBUG, "ast_db_put failed\n");
1194 + ast_cli(s->fd, "Response: Failed\r\n");
1195 + }
1196 + if (id && !ast_strlen_zero(id))
1197 + ast_cli(s->fd, "ActionID: %s\r\n",id);
1198 + ast_cli(s->fd, "\r\n");
1199 + return 0;
1200 +}
1201 +
1202 +int load_module(void)
1203 +{
1204 + if (ast_channel_register(&devstate_tech)) {
1205 + ast_log(LOG_DEBUG, "Unable to register channel class %s\n", type);
1206 + return -1;
1207 + }
1208 + ast_cli_register(&cli_dev_state);
1209 + ast_manager_register2( "Devstate", EVENT_FLAG_CALL, action_devstate, "Change a device state", mandescr_devstate );
1210 + return ast_register_application(app, devstate_exec, synopsis, descrip);
1211 +}
1212 +
1213 +int unload_module(void)
1214 +{
1215 + int res = 0;
1216 + STANDARD_HANGUP_LOCALUSERS;
1217 + ast_manager_unregister( "Devstate");
1218 + ast_cli_unregister(&cli_dev_state);
1219 + res = ast_unregister_application(app);
1220 + ast_channel_unregister(&devstate_tech);
1221 + return res;
1222 +}
1223 +
1224 +char *description(void)
1225 +{
1226 + return tdesc;
1227 +}
1228 +
1229 +int usecount(void)
1230 +{
1231 + int res;
1232 + STANDARD_USECOUNT(res);
1233 + return res;
1234 +}
1235 +
1236 +char *key()
1237 +{
1238 + return ASTERISK_GPL_KEY;
1239 +}
1240 diff -urN asterisk-1.2.4.orig/apps/app_dial.c asterisk-1.2.4/apps/app_dial.c
1241 --- asterisk-1.2.4.orig/apps/app_dial.c 2006-01-25 02:50:52.000000000 +0100
1242 +++ asterisk-1.2.4/apps/app_dial.c 2006-01-31 09:41:43.000000000 +0100
1243 @@ -11,6 +11,10 @@
1244 * the project provides a web site, mailing lists and IRC
1245 * channels for your use.
1246 *
1247 + * Copyright (C) 2004, Junghanns.NET GmbH
1248 + *
1249 + * Klaus-Peter Junghanns <kpj@junghanns.net>
1250 + *
1251 * This program is free software, distributed under the terms of
1252 * the GNU General Public License Version 2. See the LICENSE file
1253 * at the top of the source tree.
1254 @@ -113,7 +117,8 @@
1255 " context may be specified. Otherwise, the current extension is used.\n"
1256 " h - Allow the called party to hang up by sending the '*' DTMF digit.\n"
1257 " H - Allow the calling party to hang up by hitting the '*' DTMF digit.\n"
1258 -" j - Jump to priority n+101 if all of the requested channels were busy.\n"
1259 +" j - Jump to priority n+101 if the called party was busy.\n"
1260 +" Jump to priority n+201 if all of the requested channels were busy.\n"
1261 " L(x[:y][:z]) - Limit the call to 'x' ms. Play a warning when 'y' ms are\n"
1262 " left. Repeat the warning every 'z' ms. The following special\n"
1263 " variables can be used with this option:\n"
1264 @@ -158,8 +163,11 @@
1265 " family/key is not specified.\n"
1266 " r - Indicate ringing to the calling party. Pass no audio to the calling\n"
1267 " party until the called channel has answered.\n"
1268 +" R - indicate ringing to the calling party when the called party indicates\n"
1269 +" ringing, pass no audio until answered.\n"
1270 " S(x) - Hang up the call after 'x' seconds *after* the called party has\n"
1271 -" answered the call.\n"
1272 +" answered the call.\n"
1273 +" c - callback initiation, ring once and hangup.\n"
1274 " t - Allow the called party to transfer the calling party by sending the\n"
1275 " DTMF sequence defined in features.conf.\n"
1276 " T - Allow the calling party to transfer the called party by sending the\n"
1277 @@ -210,6 +218,8 @@
1278 OPT_CALLEE_MONITOR = (1 << 21),
1279 OPT_CALLER_MONITOR = (1 << 22),
1280 OPT_GOTO = (1 << 23),
1281 + OPT_NOINBAND = (1 << 24),
1282 + OPT_CALLBACK_INIT = (1 << 25),
1283 } dial_exec_option_flags;
1284
1285 #define DIAL_STILLGOING (1 << 30)
1286 @@ -248,6 +258,8 @@
1287 AST_APP_OPTION('p', OPT_SCREENING),
1288 AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
1289 AST_APP_OPTION('r', OPT_RINGBACK),
1290 + AST_APP_OPTION('R', OPT_NOINBAND),
1291 + AST_APP_OPTION('c', OPT_CALLBACK_INIT),
1292 AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
1293 AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
1294 AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
1295 @@ -383,7 +395,7 @@
1296 char *context = NULL;
1297 char cidname[AST_MAX_EXTENSION];
1298
1299 - single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK));
1300 + single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK | OPT_NOINBAND));
1301
1302 if (single) {
1303 /* Turn off hold music, etc */
1304 @@ -462,7 +474,7 @@
1305 if (option_verbose > 2)
1306 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
1307 /* Setup parameters */
1308 - o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
1309 + o->chan = ast_request(tech, in->nativeformats, stuff, &cause, NULL);
1310 if (!o->chan)
1311 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
1312 } else {
1313 @@ -916,17 +928,24 @@
1314 }
1315
1316 if( privdb_val == AST_PRIVACY_DENY ) {
1317 + ast_copy_string(status, "NOANSWER", sizeof(status));
1318 ast_verbose( VERBOSE_PREFIX_3 "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
1319 res=0;
1320 goto out;
1321 }
1322 else if( privdb_val == AST_PRIVACY_KILL ) {
1323 - ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
1324 + ast_copy_string(status, "DONTCALL", sizeof(status));
1325 + if (option_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
1326 + ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
1327 + }
1328 res = 0;
1329 goto out; /* Is this right? */
1330 }
1331 else if( privdb_val == AST_PRIVACY_TORTURE ) {
1332 - ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 301);
1333 + ast_copy_string(status, "TORTURE", sizeof(status));
1334 + if (option_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
1335 + ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 301);
1336 + }
1337 res = 0;
1338 goto out; /* is this right??? */
1339
1340 @@ -1005,7 +1024,7 @@
1341 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
1342 }
1343 /* Request the peer */
1344 - tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
1345 + tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause, NULL);
1346 if (!tmp->chan) {
1347 /* If we can't, just go on to the next call */
1348 ast_log(LOG_NOTICE, "Unable to create channel of type '%s' (cause %d - %s)\n", tech, cause, ast_cause2str(cause));
1349 @@ -1036,7 +1055,7 @@
1350 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
1351 ast_hangup(tmp->chan);
1352 /* Setup parameters */
1353 - tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
1354 + tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause, NULL);
1355 if (!tmp->chan)
1356 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
1357 } else {
1358 @@ -1155,8 +1174,11 @@
1359 ast_indicate(chan, AST_CONTROL_RINGING);
1360 sentringing++;
1361 }
1362 - } else
1363 + } else {
1364 strcpy(status, "CHANUNAVAIL");
1365 + /* See if there is a special message */
1366 + ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
1367 + }
1368
1369 time(&start_time);
1370 peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, ast_test_flag(&opts, OPT_PRIORITY_JUMP), &result);
1371 @@ -1285,6 +1307,8 @@
1372 opt_args[OPT_ARG_PRIVACY], privcid);
1373 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_DENY);
1374 }
1375 + ast_copy_string(status, "NOANSWER", sizeof(status));
1376 +
1377 if (ast_test_flag(&opts, OPT_MUSICBACK)) {
1378 ast_moh_stop(chan);
1379 } else if (ast_test_flag(&opts, OPT_RINGBACK)) {
1380 diff -urN asterisk-1.2.4.orig/apps/app_directed_pickup.c asterisk-1.2.4/apps/app_directed_pickup.c
1381 --- asterisk-1.2.4.orig/apps/app_directed_pickup.c 2005-12-20 18:34:00.000000000 +0100
1382 +++ asterisk-1.2.4/apps/app_directed_pickup.c 2006-01-31 09:41:43.000000000 +0100
1383 @@ -41,7 +41,7 @@
1384 #include "asterisk/app.h"
1385
1386 static const char *tdesc = "Directed Call Pickup Application";
1387 -static const char *app = "Pickup";
1388 +static const char *app = "DPickup";
1389 static const char *synopsis = "Directed Call Pickup";
1390 static const char *descrip =
1391 " Pickup(extension[@context]): This application can pickup any ringing channel\n"
1392 diff -urN asterisk-1.2.4.orig/apps/app_meetme.c asterisk-1.2.4/apps/app_meetme.c
1393 --- asterisk-1.2.4.orig/apps/app_meetme.c 2006-01-18 22:02:06.000000000 +0100
1394 +++ asterisk-1.2.4/apps/app_meetme.c 2006-01-31 09:41:43.000000000 +0100
1395 @@ -454,7 +454,7 @@
1396 ast_copy_string(cnf->pin, pin, sizeof(cnf->pin));
1397 ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin));
1398 cnf->markedusers = 0;
1399 - cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo", NULL);
1400 + cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo", NULL, NULL);
1401 if (cnf->chan) {
1402 cnf->fd = cnf->chan->fds[0]; /* for use by conf_play() */
1403 } else {
1404 @@ -822,8 +822,9 @@
1405 char exitcontext[AST_MAX_CONTEXT] = "";
1406 char recordingtmp[AST_MAX_EXTENSION] = "";
1407 int dtmf;
1408 + int dyna_buff = CONF_SIZE;
1409 ZT_BUFFERINFO bi;
1410 - char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
1411 + char __buf[ZT_MAX_BUF_SPACE / ZT_DEFAULT_NUM_BUFS + AST_FRIENDLY_OFFSET];
1412 char *buf = __buf + AST_FRIENDLY_OFFSET;
1413
1414 if (!user) {
1415 @@ -986,7 +987,7 @@
1416 }
1417 /* Setup buffering information */
1418 memset(&bi, 0, sizeof(bi));
1419 - bi.bufsize = CONF_SIZE/2;
1420 + bi.bufsize = dyna_buff / 2;
1421 bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
1422 bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
1423 bi.numbufs = audio_buffers;
1424 @@ -1271,6 +1272,14 @@
1425 f = ast_read(c);
1426 if (!f)
1427 break;
1428 + if (f->datalen && f->datalen != dyna_buff) {
1429 + ast_log(LOG_NOTICE, "Audio bytes: %d Buffer size: %d\n", f->datalen, dyna_buff);
1430 + if (f->datalen < ZT_MAX_BUF_SPACE/audio_buffers) { /* skip too large frame to avoid overflow */
1431 + dyna_buff = f->datalen;
1432 + close(fd);
1433 + goto zapretry;
1434 + }
1435 + }
1436 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) {
1437 if (user->talk.actual)
1438 ast_frame_adjust_volume(f, user->talk.actual);
1439 @@ -1500,7 +1509,7 @@
1440 }
1441 ast_frfree(f);
1442 } else if (outfd > -1) {
1443 - res = read(outfd, buf, CONF_SIZE);
1444 + res = read(outfd, buf, dyna_buff);
1445 if (res > 0) {
1446 memset(&fr, 0, sizeof(fr));
1447 fr.frametype = AST_FRAME_VOICE;
1448 diff -urN asterisk-1.2.4.orig/apps/app_milliwatt.c asterisk-1.2.4/apps/app_milliwatt.c
1449 --- asterisk-1.2.4.orig/apps/app_milliwatt.c 2006-01-19 05:17:45.000000000 +0100
1450 +++ asterisk-1.2.4/apps/app_milliwatt.c 2006-01-31 09:41:43.000000000 +0100
1451 @@ -74,20 +74,28 @@
1452 {
1453 struct ast_frame wf;
1454 unsigned char buf[AST_FRIENDLY_OFFSET + 640];
1455 + const int maxsamples = (sizeof (buf) - AST_FRIENDLY_OFFSET) / sizeof (buf[0]);
1456 int i,*indexp = (int *) data;
1457
1458 - if (len + AST_FRIENDLY_OFFSET > sizeof(buf))
1459 - {
1460 - ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",(int)(sizeof(buf) - AST_FRIENDLY_OFFSET),len);
1461 - len = sizeof(buf) - AST_FRIENDLY_OFFSET;
1462 - }
1463 + /* Instead of len, use samples, because channel.c generator_force
1464 + * generate(chan, tmp, 0, 160) ignores len. In any case, len is
1465 + * a multiple of samples, given by number of samples times bytes per
1466 + * sample. In the case of ulaw, len = samples. for signed linear
1467 + * len = 2 * samples */
1468 +
1469 + if (samples > maxsamples)
1470 + {
1471 + ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n", maxsamples, samples);
1472 + samples = maxsamples;
1473 + }
1474 + len = samples * sizeof (buf[0]);
1475 wf.frametype = AST_FRAME_VOICE;
1476 wf.subclass = AST_FORMAT_ULAW;
1477 wf.offset = AST_FRIENDLY_OFFSET;
1478 wf.mallocd = 0;
1479 wf.data = buf + AST_FRIENDLY_OFFSET;
1480 wf.datalen = len;
1481 - wf.samples = wf.datalen;
1482 + wf.samples = samples;
1483 wf.src = "app_milliwatt";
1484 wf.delivery.tv_sec = 0;
1485 wf.delivery.tv_usec = 0;
1486 diff -urN asterisk-1.2.4.orig/apps/app_page.c asterisk-1.2.4/apps/app_page.c
1487 --- asterisk-1.2.4.orig/apps/app_page.c 2005-12-02 01:51:15.000000000 +0100
1488 +++ asterisk-1.2.4/apps/app_page.c 2006-01-31 09:41:43.000000000 +0100
1489 @@ -85,7 +85,7 @@
1490 {
1491 struct calloutdata *cd = data;
1492 ast_pbx_outgoing_app(cd->tech, AST_FORMAT_SLINEAR, cd->resource, 30000,
1493 - "MeetMe", cd->meetmeopts, NULL, 0, cd->cidnum, cd->cidname, cd->variables, NULL);
1494 + "MeetMe", cd->meetmeopts, NULL, 0, 0, cd->cidnum, cd->cidname, cd->variables, NULL, NULL);
1495 free(cd);
1496 return NULL;
1497 }
1498 diff -urN asterisk-1.2.4.orig/apps/app_parkandannounce.c asterisk-1.2.4/apps/app_parkandannounce.c
1499 --- asterisk-1.2.4.orig/apps/app_parkandannounce.c 2005-11-29 19:24:39.000000000 +0100
1500 +++ asterisk-1.2.4/apps/app_parkandannounce.c 2006-01-31 09:41:43.000000000 +0100
1501 @@ -183,7 +183,7 @@
1502
1503 memset(&oh, 0, sizeof(oh));
1504 oh.parent_channel = chan;
1505 - dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->cid.cid_num, chan->cid.cid_name, &oh);
1506 + dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, 0, chan->cid.cid_num, chan->cid.cid_name, &oh, NULL);
1507
1508 if(dchan) {
1509 if(dchan->_state == AST_STATE_UP) {
1510 diff -urN asterisk-1.2.4.orig/apps/app_pickup.c asterisk-1.2.4/apps/app_pickup.c
1511 --- asterisk-1.2.4.orig/apps/app_pickup.c 1970-01-01 01:00:00.000000000 +0100
1512 +++ asterisk-1.2.4/apps/app_pickup.c 2006-01-31 09:41:43.000000000 +0100
1513 @@ -0,0 +1,319 @@
1514 +/*
1515 + * Asterisk -- A telephony toolkit for Linux.
1516 + *
1517 + * Pickup, channel independent call pickup
1518 + *
1519 + * Copyright (C) 2004, Junghanns.NET GmbH
1520 + *
1521 + * Klaus-Peter Junghanns <kpj@junghanns.net>
1522 + *
1523 + * Copyright (C) 2004, Florian Overkamp <florian@obsimref.com>
1524 + *
1525 + * This program is free software, distributed under the terms of
1526 + * the GNU General Public License
1527 + */
1528 +
1529 +#include <stdlib.h>
1530 +#include <unistd.h>
1531 +#include <string.h>
1532 +#include <stdio.h>
1533 +#include <signal.h>
1534 +#include <pthread.h>
1535 +#include <asterisk/lock.h>
1536 +#include <asterisk/file.h>
1537 +#include <asterisk/logger.h>
1538 +#include <asterisk/channel.h>
1539 +#include <asterisk/pbx.h>
1540 +#include <asterisk/module.h>
1541 +#include <asterisk/features.h>
1542 +#include <asterisk/options.h>
1543 +
1544 +
1545 +static char *tdesc = "PickUp/PickDown/Steal/PickupChan/StealChan";
1546 +
1547 +static char *app = "PickUp";
1548 +
1549 +static char *synopsis = "Channel independent call pickup.";
1550 +
1551 +static char *descrip =
1552 +" PickDown([group]): Tries to pickup the first ringing channel with callgroup == group.\n"
1553 +" If called without the group argument, the pickupgroup of the channel will be used.\n";
1554 +
1555 +static char *app2 = "Steal";
1556 +
1557 +static char *synopsis2 = "Channel independent call stealing. Just like pickup but for answered channels.";
1558 +
1559 +static char *descrip2 =
1560 +" Steal([group]): Tries to steal the first bridged channel with callgroup == group.\n"
1561 +" If called without the group argument, the pickupgroup of the channel will be used.\n";
1562 +
1563 +static char *app3 = "PickDown";
1564 +
1565 +static char *synopsis3 = "Channel independent call pickdown.";
1566 +
1567 +static char *descrip3 =
1568 +" PickDown([group]): Tries to hangup the first ringing channel with callgroup == group.\n"
1569 +" If called without the group argument, the pickupgroup of the channel will be used.\n";
1570 +
1571 +static char *app4 = "PickupChan";
1572 +
1573 +static char *synopsis4 = "Channel independent call pickup.";
1574 +
1575 +static char *descrip4 =
1576 +" PickupChan(Technology/resource[&Technology2/resource2...]): Tries to pickup the first ringing channel in the parameter list.\n";
1577 +
1578 +static char *app5 = "StealChan";
1579 +
1580 +static char *synopsis5 = "Channel independent call stealing. Just like pickup but for answered channels.";
1581 +
1582 +static char *descrip5 =
1583 +" StealChan(Technology/resource[&Technology2/resource2...]): Tries to steal the first ringing channel in the parameter list.\n";
1584 +
1585 +STANDARD_LOCAL_USER;
1586 +
1587 +LOCAL_USER_DECL;
1588 +
1589 +static int my_pickup_call(struct ast_channel *chan, unsigned int pickupgroup, int chanstate, int bridge) {
1590 + struct ast_channel *cur;
1591 + int res = -1;
1592 + cur = ast_channel_walk_locked(NULL);
1593 + while(cur) {
1594 + if ((cur != chan) &&
1595 + (pickupgroup & cur->callgroup) &&
1596 + (cur->_state == chanstate)) {
1597 + break;
1598 + }
1599 + ast_mutex_unlock(&cur->lock);
1600 + cur = ast_channel_walk_locked(cur);
1601 + }
1602 + if (cur) {
1603 + if(option_verbose > 2) {
1604 + if (chanstate == AST_STATE_RINGING) {
1605 + if (bridge == 1) {
1606 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
1607 + } else {
1608 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
1609 + }
1610 + } else {
1611 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
1612 + }
1613 + }
1614 + if (bridge == 1) {
1615 + if (chan->_state != AST_STATE_UP) {
1616 + ast_answer(chan);
1617 + }
1618 + if (ast_channel_masquerade(cur, chan)) {
1619 + ast_log(LOG_ERROR, "unable to masquerade\n");
1620 + }
1621 + ast_mutex_unlock(&cur->lock);
1622 + ast_mutex_unlock(&chan->lock);
1623 + } else {
1624 + cur->_softhangup = AST_SOFTHANGUP_DEV;
1625 + ast_mutex_unlock(&cur->lock);
1626 + }
1627 + } else {
1628 + if(option_verbose > 2) {
1629 + ast_verbose(VERBOSE_PREFIX_3 "No channel found %d.\n",pickupgroup);
1630 + }
1631 + }
1632 + return res;
1633 +}
1634 +
1635 +static int my_pickup_channel(struct ast_channel *chan, void *data, int chanstate, int bridge) {
1636 + struct ast_channel *cur;
1637 + char channels[256];
1638 + char evalchan[256];
1639 + char *endptr;
1640 + int res = -1;
1641 + cur = ast_channel_walk_locked(NULL);
1642 + strncpy(channels, (char *)data, sizeof(channels) - 1);
1643 + while(cur) {
1644 + if ((cur != chan) &&
1645 + (cur->_state == chanstate)) {
1646 + /* This call is a candidate (correct ringstate and not ourselves), now check if the channel is in our list */
1647 + strncpy(evalchan, (char *)cur->name, sizeof(evalchan) - 1);
1648 + /* strip the subchannel tag */
1649 + endptr = strrchr(evalchan, '-');
1650 + if(endptr) {
1651 + *endptr = '\0';
1652 + }
1653 + endptr = strrchr(evalchan, '/');
1654 + if(endptr) {
1655 + *endptr = '\0';
1656 + }
1657 + /* check for each of the members if they match (probably a stristr will do ?) */
1658 + /* if we match the code, break */
1659 + if(strstr(channels, evalchan) != NULL) {
1660 + ast_verbose(VERBOSE_PREFIX_1 "Nice channel, I'll take it: %s\n",evalchan);
1661 + break;
1662 + }
1663 + }
1664 + ast_mutex_unlock(&cur->lock);
1665 + cur = ast_channel_walk_locked(cur);
1666 + }
1667 + if (cur) {
1668 + if(option_verbose > 2) {
1669 + if (chanstate == AST_STATE_RINGING) {
1670 + if (bridge == 1) {
1671 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
1672 + } else {
1673 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
1674 + }
1675 + } else {
1676 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
1677 + }
1678 + }
1679 + if (bridge == 1) {
1680 + if (chan->_state != AST_STATE_UP) {
1681 + ast_answer(chan);
1682 + }
1683 + if (ast_channel_masquerade(cur, chan)) {
1684 + ast_log(LOG_ERROR, "unable to masquerade\n");
1685 + }
1686 + ast_mutex_unlock(&cur->lock);
1687 + ast_mutex_unlock(&chan->lock);
1688 + } else {
1689 + cur->_softhangup = AST_SOFTHANGUP_DEV;
1690 + ast_mutex_unlock(&cur->lock);
1691 + }
1692 + } else {
1693 + if(option_verbose > 2) {
1694 + ast_verbose(VERBOSE_PREFIX_3 "No channel found %s.\n",channels);
1695 + }
1696 + }
1697 + return res;
1698 +}
1699 +
1700 +
1701 +static int pickup_exec(struct ast_channel *chan, void *data)
1702 +{
1703 + int res=0;
1704 + unsigned int pickupgroup=0;
1705 + struct localuser *u;
1706 + if (!data || !strlen(data)) {
1707 + pickupgroup = chan->pickupgroup;
1708 + } else {
1709 + pickupgroup = ast_get_group(data);
1710 + }
1711 + LOCAL_USER_ADD(u);
1712 + if (!res) {
1713 + res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 1);
1714 + }
1715 + if (res > 0)
1716 + res = 0;
1717 + LOCAL_USER_REMOVE(u);
1718 + return res;
1719 +}
1720 +
1721 +static int steal_exec(struct ast_channel *chan, void *data)
1722 +{
1723 + int res=0;
1724 + unsigned int pickupgroup=0;
1725 + struct localuser *u;
1726 + if (!data || !strlen(data)) {
1727 + pickupgroup = chan->pickupgroup;
1728 + } else {
1729 + pickupgroup = ast_get_group(data);
1730 + }
1731 + LOCAL_USER_ADD(u);
1732 + if (!res) {
1733 + res = my_pickup_call(chan, pickupgroup, AST_STATE_UP, 1);
1734 + }
1735 + if (res > 0)
1736 + res = 0;
1737 + LOCAL_USER_REMOVE(u);
1738 + return res;
1739 +}
1740 +
1741 +static int pickdown_exec(struct ast_channel *chan, void *data)
1742 +{
1743 + int res=0;
1744 + unsigned int pickupgroup=0;
1745 + struct localuser *u;
1746 + if (!data || !strlen(data)) {
1747 + pickupgroup = chan->pickupgroup;
1748 + } else {
1749 + pickupgroup = ast_get_group(data);
1750 + }
1751 + LOCAL_USER_ADD(u);
1752 + if (!res) {
1753 + res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 0);
1754 + }
1755 + if (res > 0)
1756 + res = 0;
1757 + LOCAL_USER_REMOVE(u);
1758 + return res;
1759 +}
1760 +
1761 +static int pickupchan_exec(struct ast_channel *chan, void *data) {
1762 + int res=0;
1763 + struct localuser *u;
1764 + if (!data) {
1765 + ast_log(LOG_WARNING, "PickupChan requires an argument (technology1/number1&technology2/number2...)\n");
1766 + return -1;
1767 + }
1768 + LOCAL_USER_ADD(u);
1769 + if (!res) {
1770 + res = my_pickup_channel(chan, data, AST_STATE_RINGING, 1);
1771 + }
1772 + if (res > 0)
1773 + res = 0;
1774 + LOCAL_USER_REMOVE(u);
1775 + return res;
1776 +}
1777 +
1778 +static int stealchan_exec(struct ast_channel *chan, void *data)
1779 +{
1780 + int res=0;
1781 + struct localuser *u;
1782 + if (!data) {
1783 + ast_log(LOG_WARNING, "StealChan requires an argument (technology1/number1&technology2/number2...)\n");
1784 + return -1;
1785 + }
1786 +
1787 + LOCAL_USER_ADD(u);
1788 + if (!res) {
1789 + res = my_pickup_channel(chan, data, AST_STATE_UP, 1);
1790 + }
1791 + if (res > 0)
1792 + res = 0;
1793 + LOCAL_USER_REMOVE(u);
1794 + return res;
1795 +}
1796 +
1797 +
1798 +int unload_module(void)
1799 +{
1800 + STANDARD_HANGUP_LOCALUSERS;
1801 + ast_unregister_application(app5);
1802 + ast_unregister_application(app4);
1803 + ast_unregister_application(app3);
1804 + ast_unregister_application(app2);
1805 + return ast_unregister_application(app);
1806 +}
1807 +
1808 +int load_module(void)
1809 +{
1810 + ast_register_application(app5, stealchan_exec, synopsis5, descrip5);
1811 + ast_register_application(app4, pickupchan_exec, synopsis4, descrip4);
1812 + ast_register_application(app3, pickdown_exec, synopsis3, descrip3);
1813 + ast_register_application(app2, steal_exec, synopsis2, descrip2);
1814 + return ast_register_application(app, pickup_exec, synopsis, descrip);
1815 +}
1816 +
1817 +char *description(void)
1818 +{
1819 + return tdesc;
1820 +}
1821 +
1822 +int usecount(void)
1823 +{
1824 + int res;
1825 + STANDARD_USECOUNT(res);
1826 + return res;
1827 +}
1828 +
1829 +char *key()
1830 +{
1831 + return ASTERISK_GPL_KEY;
1832 +}
1833 diff -urN asterisk-1.2.4.orig/apps/app_queue.c asterisk-1.2.4/apps/app_queue.c
1834 --- asterisk-1.2.4.orig/apps/app_queue.c 2006-01-22 20:03:53.000000000 +0100
1835 +++ asterisk-1.2.4/apps/app_queue.c 2006-01-31 09:41:43.000000000 +0100
1836 @@ -501,7 +501,7 @@
1837 return NULL;
1838 }
1839
1840 -static int statechange_queue(const char *dev, int state, void *ign)
1841 +static int statechange_queue(const char *dev, int state, void *ign, char *cid_num, char *cid_name)
1842 {
1843 /* Avoid potential for deadlocks by spawning a new thread to handle
1844 the event */
1845 @@ -1386,7 +1386,7 @@
1846 location = "";
1847
1848 /* Request the peer */
1849 - tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status);
1850 + tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status, NULL);
1851 if (!tmp->chan) { /* If we can't, just go on to the next call */
1852 #if 0
1853 ast_log(LOG_NOTICE, "Unable to create channel of type '%s' for Queue\n", cur->tech);
1854 @@ -1692,7 +1692,7 @@
1855 if (option_verbose > 2)
1856 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
1857 /* Setup parameters */
1858 - o->chan = ast_request(tech, in->nativeformats, stuff, &status);
1859 + o->chan = ast_request(tech, in->nativeformats, stuff, &status, NULL);
1860 if (status != o->oldstatus)
1861 update_dial_status(qe->parent, o->member, status);
1862 if (!o->chan) {
1863 diff -urN asterisk-1.2.4.orig/apps/app_readfile.c asterisk-1.2.4/apps/app_readfile.c
1864 --- asterisk-1.2.4.orig/apps/app_readfile.c 2005-11-29 19:24:39.000000000 +0100
1865 +++ asterisk-1.2.4/apps/app_readfile.c 2006-01-31 09:41:43.000000000 +0100
1866 @@ -40,7 +40,7 @@
1867 #include "asterisk/app.h"
1868 #include "asterisk/module.h"
1869
1870 -static char *tdesc = "Stores output of file into a variable";
1871 +static char *tdesc = "Stores content of file into a variable";
1872
1873 static char *app_readfile = "ReadFile";
1874
1875 diff -urN asterisk-1.2.4.orig/apps/app_segfault.c asterisk-1.2.4/apps/app_segfault.c
1876 --- asterisk-1.2.4.orig/apps/app_segfault.c 1970-01-01 01:00:00.000000000 +0100
1877 +++ asterisk-1.2.4/apps/app_segfault.c 2006-01-31 09:41:43.000000000 +0100
1878 @@ -0,0 +1,75 @@
1879 +/*
1880 + * Segfault application
1881 + *
1882 + * An application to provoke a segmentation fault from the dialplan.
1883 + * (I know what you are thinking now...., but since Asterisk is too stable...
1884 + * I needed something to test my failover switches.)
1885 + *
1886 + * Copyright (C) 2005 Junghanns.NET GmbH
1887 + * Klaus-Peter Junghanns <kpj@junghanns.net>
1888 + *
1889 + * This program is free software, distributed under the terms of
1890 + * the GNU General Public License. THIS APPLICATION _WILL_ CRASH YOUR
1891 + * ASTERISK SERVER SO OF COURSE THERE IS NOT LIABILITY FOR NOTHING!
1892 + */
1893 +
1894 +#include <stdlib.h>
1895 +#include <unistd.h>
1896 +#include <string.h>
1897 +#include <stdio.h>
1898 +#include <asterisk/lock.h>
1899 +#include <asterisk/file.h>
1900 +#include <asterisk/logger.h>
1901 +#include <asterisk/channel.h>
1902 +#include <asterisk/pbx.h>
1903 +#include <asterisk/module.h>
1904 +
1905 +static char *tdesc = "Application for crashing Asterisk with a segmentation fault";
1906 +
1907 +static char *app = "Segfault";
1908 +
1909 +static char *synopsis = "This application will crash Asterisk with a segmentation fault.";
1910 +
1911 +static char *descrip =
1912 +" Segfault(): Crash with a segfault. Never returns nufin.\n";
1913 +
1914 +STANDARD_LOCAL_USER;
1915 +
1916 +LOCAL_USER_DECL;
1917 +
1918 +static int segfault_exec(struct ast_channel *chan, void *data)
1919 +{
1920 + struct localuser *u;
1921 + LOCAL_USER_ADD(u);
1922 + ((char *)0)[0] = 0;
1923 + LOCAL_USER_REMOVE(u);
1924 + return 0;
1925 +}
1926 +
1927 +int unload_module(void)
1928 +{
1929 + STANDARD_HANGUP_LOCALUSERS;
1930 + return ast_unregister_application(app);
1931 +}
1932 +
1933 +int load_module(void)
1934 +{
1935 + return ast_register_application(app, segfault_exec, synopsis, descrip);
1936 +}
1937 +
1938 +char *description(void)
1939 +{
1940 + return tdesc;
1941 +}
1942 +
1943 +int usecount(void)
1944 +{
1945 + int res;
1946 + STANDARD_USECOUNT(res);
1947 + return res;
1948 +}
1949 +
1950 +char *key()
1951 +{
1952 + return ASTERISK_GPL_KEY;
1953 +}
1954 diff -urN asterisk-1.2.4.orig/apps/app_sms.c asterisk-1.2.4/apps/app_sms.c
1955 --- asterisk-1.2.4.orig/apps/app_sms.c 2005-12-26 19:19:12.000000000 +0100
1956 +++ asterisk-1.2.4/apps/app_sms.c 2006-01-31 09:41:43.000000000 +0100
1957 @@ -1179,32 +1179,31 @@
1958 {
1959 struct ast_frame f = { 0 };
1960 unsigned char waste[AST_FRIENDLY_OFFSET];
1961 +#define MAXSAMPLES (800)
1962 #ifdef OUTALAW
1963 - unsigned char buf[800];
1964 + unsigned char buf[MAXSAMPLES];
1965 #else
1966 - signed short buf[800];
1967 + signed short buf[MAXSAMPLES];
1968 #endif
1969 +#define SAMPLE2LEN (sizeof (buf[0]))
1970 sms_t *h = data;
1971 int i;
1972
1973 - if (len > sizeof (buf)) {
1974 - ast_log (LOG_WARNING, "Only doing %d bytes (%d bytes requested)\n", (int)(sizeof (buf) / sizeof (signed short)), len);
1975 - len = sizeof (buf);
1976 -#ifdef OUTALAW
1977 - samples = len;
1978 -#else
1979 - samples = len / 2;
1980 -#endif
1981 + if (samples > MAXSAMPLES) {
1982 + ast_log (LOG_WARNING, "Only doing %d samples (%d requested)\n",
1983 + MAXSAMPLES, samples);
1984 + samples = MAXSAMPLES;
1985 }
1986 - waste[0] = 0; /* make compiler happy */
1987 + len = samples * SAMPLE2LEN;
1988 +
1989 + waste[0] = 0; /* make compiler happy */
1990 f.frametype = AST_FRAME_VOICE;
1991 #ifdef OUTALAW
1992 f.subclass = AST_FORMAT_ALAW;
1993 - f.datalen = samples;
1994 #else
1995 f.subclass = AST_FORMAT_SLINEAR;
1996 - f.datalen = samples * 2;
1997 #endif
1998 + f.datalen = len;
1999 f.offset = AST_FRIENDLY_OFFSET;
2000 f.mallocd = 0;
2001 f.data = buf;
2002 @@ -1256,6 +1255,8 @@
2003 return -1;
2004 }
2005 return 0;
2006 +#undef SAMPLE2LEN
2007 +#undef MAXSAMPLES
2008 }
2009
2010 static void sms_process (sms_t * h, int samples, signed short *data)
2011 diff -urN asterisk-1.2.4.orig/apps/app_zapras.c asterisk-1.2.4/apps/app_zapras.c
2012 --- asterisk-1.2.4.orig/apps/app_zapras.c 2005-11-29 19:24:39.000000000 +0100
2013 +++ asterisk-1.2.4/apps/app_zapras.c 2006-01-31 09:41:43.000000000 +0100
2014 @@ -182,7 +182,7 @@
2015 }
2016 }
2017 /* Throw back into audio mode */
2018 - x = 1;
2019 + x = 0;
2020 ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
2021
2022 /* Restore saved values */
2023 diff -urN asterisk-1.2.4.orig/asterisk.c asterisk-1.2.4/asterisk.c
2024 --- asterisk-1.2.4.orig/asterisk.c 2006-01-24 23:55:32.000000000 +0100
2025 +++ asterisk-1.2.4/asterisk.c 2006-01-31 09:41:43.000000000 +0100
2026 @@ -221,6 +221,7 @@
2027 char ast_config_AST_CTL_OWNER[AST_CONFIG_MAX_PATH] = "\0";
2028 char ast_config_AST_CTL_GROUP[AST_CONFIG_MAX_PATH] = "\0";
2029 char ast_config_AST_CTL[AST_CONFIG_MAX_PATH] = "asterisk.ctl";
2030 +char ast_config_AST_SYMBOLIC_NAME[20];
2031
2032 static char *_argv[256];
2033 static int shuttingdown = 0;
2034 @@ -1878,6 +1879,7 @@
2035 ast_copy_string(ast_config_AST_PID, AST_PID, sizeof(ast_config_AST_PID));
2036 ast_copy_string(ast_config_AST_SOCKET, AST_SOCKET, sizeof(ast_config_AST_SOCKET));
2037 ast_copy_string(ast_config_AST_RUN_DIR, AST_RUN_DIR, sizeof(ast_config_AST_RUN_DIR));
2038 + ast_copy_string(ast_config_AST_SYMBOLIC_NAME, AST_SYMBOLIC_NAME, sizeof(ast_config_AST_SYMBOLIC_NAME));
2039
2040 /* no asterisk.conf? no problem, use buildtime config! */
2041 if (!cfg) {
2042 @@ -1916,6 +1918,8 @@
2043 ast_copy_string(ast_config_AST_RUN_DIR, v->value, sizeof(ast_config_AST_RUN_DIR));
2044 } else if (!strcasecmp(v->name, "astmoddir")) {
2045 ast_copy_string(ast_config_AST_MODULE_DIR, v->value, sizeof(ast_config_AST_MODULE_DIR));
2046 + } else if (!strcasecmp(v->name, "uniquename")) {
2047 + strncpy(ast_config_AST_SYMBOLIC_NAME,v->value,sizeof(ast_config_AST_SYMBOLIC_NAME));
2048 }
2049 v = v->next;
2050 }
2051 diff -urN asterisk-1.2.4.orig/build_tools/make_defaults_h asterisk-1.2.4/build_tools/make_defaults_h
2052 --- asterisk-1.2.4.orig/build_tools/make_defaults_h 2005-06-20 19:26:08.000000000 +0200
2053 +++ asterisk-1.2.4/build_tools/make_defaults_h 2006-01-31 09:41:43.000000000 +0100
2054 @@ -16,6 +16,7 @@
2055 #define AST_KEY_DIR "${INSTALL_PATH}${ASTVARLIBDIR}/keys"
2056 #define AST_DB "${INSTALL_PATH}${ASTVARLIBDIR}/astdb"
2057 #define AST_TMP_DIR "${INSTALL_PATH}${ASTSPOOLDIR}/tmp"
2058 +#define AST_SYMBOLIC_NAME "asterisk"
2059
2060 #define AST_CONFIG_FILE "${INSTALL_PATH}${ASTCONFPATH}"
2061
2062 diff -urN asterisk-1.2.4.orig/channel.c asterisk-1.2.4/channel.c
2063 --- asterisk-1.2.4.orig/channel.c 2006-01-25 10:46:43.000000000 +0100
2064 +++ asterisk-1.2.4/channel.c 2006-01-31 09:41:43.000000000 +0100
2065 @@ -94,8 +94,8 @@
2066 */
2067 static int shutting_down = 0;
2068
2069 -AST_MUTEX_DEFINE_STATIC(uniquelock);
2070 static int uniqueint = 0;
2071 +AST_MUTEX_DEFINE_EXPORTED(uniquelock);
2072
2073 unsigned long global_fin = 0, global_fout = 0;
2074
2075 @@ -512,6 +512,17 @@
2076 .description = "Null channel (should not see this)",
2077 };
2078
2079 +char *ast_alloc_uniqueid(void) {
2080 + char *uniqueid;
2081 + uniqueid = malloc(64);
2082 + if (!uniqueid) return NULL;
2083 + ast_mutex_lock(&uniquelock);
2084 + snprintf(uniqueid, 63, "%s-%d-%li.%d", ast_config_AST_SYMBOLIC_NAME, ast_mainpid, (long)time(NULL), uniqueint++);
2085 + ast_mutex_unlock(&uniquelock);
2086 + return uniqueid;
2087 +}
2088 +
2089 +
2090 /*--- ast_channel_alloc: Create a new channel structure */
2091 struct ast_channel *ast_channel_alloc(int needqueue)
2092 {
2093 @@ -519,6 +530,7 @@
2094 int x;
2095 int flags;
2096 struct varshead *headp;
2097 + char *tmpuniqueid;
2098
2099
2100 /* If shutting down, don't allocate any new channels */
2101 @@ -584,9 +596,12 @@
2102 tmp->data = NULL;
2103 tmp->fin = global_fin;
2104 tmp->fout = global_fout;
2105 - ast_mutex_lock(&uniquelock);
2106 - snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), "%li.%d", (long) time(NULL), uniqueint++);
2107 - ast_mutex_unlock(&uniquelock);
2108 + tmpuniqueid = ast_alloc_uniqueid();
2109 + snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), tmpuniqueid);
2110 + if (tmpuniqueid) {
2111 + free(tmpuniqueid);
2112 + tmpuniqueid = NULL;
2113 + }
2114 headp = &tmp->varshead;
2115 ast_mutex_init(&tmp->lock);
2116 AST_LIST_HEAD_INIT_NOLOCK(headp);
2117 @@ -729,7 +744,7 @@
2118 */
2119 static struct ast_channel *channel_find_locked(const struct ast_channel *prev,
2120 const char *name, const int namelen,
2121 - const char *context, const char *exten)
2122 + const char *context, const char *exten, const char *uniqueid)
2123 {
2124 const char *msg = prev ? "deadlock" : "initial deadlock";
2125 int retries, done;
2126 @@ -740,9 +755,14 @@
2127 for (c = channels; c; c = c->next) {
2128 if (!prev) {
2129 /* want head of list */
2130 - if (!name && !exten)
2131 + if (!name && !exten && !uniqueid)
2132 break;
2133 - if (name) {
2134 + if (uniqueid) {
2135 + if (!strcasecmp(c->uniqueid, uniqueid))
2136 + break;
2137 + else
2138 + continue;
2139 + } else if (name) {
2140 /* want match by full name */
2141 if (!namelen) {
2142 if (!strcasecmp(c->name, name))
2143 @@ -793,33 +813,39 @@
2144 /*--- ast_channel_walk_locked: Browse channels in use */
2145 struct ast_channel *ast_channel_walk_locked(const struct ast_channel *prev)
2146 {
2147 - return channel_find_locked(prev, NULL, 0, NULL, NULL);
2148 + return channel_find_locked(prev, NULL, 0, NULL, NULL, NULL);
2149 }
2150
2151 /*--- ast_get_channel_by_name_locked: Get channel by name and lock it */
2152 struct ast_channel *ast_get_channel_by_name_locked(const char *name)
2153 {
2154 - return channel_find_locked(NULL, name, 0, NULL, NULL);
2155 + return channel_find_locked(NULL, name, 0, NULL, NULL, NULL);
2156 }
2157
2158 /*--- ast_get_channel_by_name_prefix_locked: Get channel by name prefix and lock it */
2159 struct ast_channel *ast_get_channel_by_name_prefix_locked(const char *name, const int namelen)
2160 {
2161 - return channel_find_locked(NULL, name, namelen, NULL, NULL);
2162 + return channel_find_locked(NULL, name, namelen, NULL, NULL, NULL);
2163 }
2164
2165 /*--- ast_walk_channel_by_name_prefix_locked: Get next channel by name prefix and lock it */
2166 struct ast_channel *ast_walk_channel_by_name_prefix_locked(struct ast_channel *chan, const char *name, const int namelen)
2167 {
2168 - return channel_find_locked(chan, name, namelen, NULL, NULL);
2169 + return channel_find_locked(chan, name, namelen, NULL, NULL, NULL);
2170 }
2171
2172 /*--- ast_get_channel_by_exten_locked: Get channel by exten (and optionally context) and lock it */
2173 struct ast_channel *ast_get_channel_by_exten_locked(const char *exten, const char *context)
2174 {
2175 - return channel_find_locked(NULL, NULL, 0, context, exten);
2176 + return channel_find_locked(NULL, NULL, 0, context, exten, NULL);
2177 }
2178
2179 +struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid)
2180 +{
2181 + return channel_find_locked(NULL, NULL, 0, NULL, NULL, uniqueid);
2182 +}
2183 +
2184 +
2185 /*--- ast_safe_sleep_conditional: Wait, look for hangups and condition arg */
2186 int ast_safe_sleep_conditional( struct ast_channel *chan, int ms,
2187 int (*cond)(void*), void *data )
2188 @@ -912,8 +938,10 @@
2189 free(chan->tech_pvt);
2190 }
2191
2192 - if (chan->sched)
2193 - sched_context_destroy(chan->sched);
2194 + if (chan->sched) {
2195 + sched_context_destroy(chan->sched);
2196 + chan->sched = NULL;
2197 + }
2198
2199 ast_copy_string(name, chan->name, sizeof(name));
2200
2201 @@ -956,10 +984,11 @@
2202 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries)))
2203 ast_var_delete(vardata);
2204
2205 +
2206 free(chan);
2207 ast_mutex_unlock(&chlock);
2208
2209 - ast_device_state_changed_literal(name);
2210 + ast_device_state_changed_literal(name, NULL, NULL);
2211 }
2212
2213 int ast_channel_spy_add(struct ast_channel *chan, struct ast_channel_spy *spy)
2214 @@ -2364,7 +2393,7 @@
2215 &chan->writetrans, 1);
2216 }
2217
2218 -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)
2219 +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)
2220 {
2221 int state = 0;
2222 int cause = 0;
2223 @@ -2372,7 +2401,7 @@
2224 struct ast_frame *f;
2225 int res = 0;
2226
2227 - chan = ast_request(type, format, data, &cause);
2228 + chan = ast_request(type, format, data, &cause, uniqueid);
2229 if (chan) {
2230 if (oh) {
2231 if (oh->vars)
2232 @@ -2384,6 +2413,7 @@
2233 }
2234 ast_set_callerid(chan, cid_num, cid_name, cid_num);
2235
2236 + chan->cid.cid_pres = callingpres;
2237 if (!ast_call(chan, data, 0)) {
2238 while(timeout && (chan->_state != AST_STATE_UP)) {
2239 res = ast_waitfor(chan, timeout);
2240 @@ -2406,6 +2436,7 @@
2241 if (f->subclass == AST_CONTROL_RINGING)
2242 state = AST_CONTROL_RINGING;
2243 else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
2244 + res = 0;
2245 state = f->subclass;
2246 ast_frfree(f);
2247 break;
2248 @@ -2475,12 +2506,12 @@
2249 return chan;
2250 }
2251
2252 -struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, const char *cidnum, const char *cidname)
2253 +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)
2254 {
2255 - return __ast_request_and_dial(type, format, data, timeout, outstate, cidnum, cidname, NULL);
2256 + return __ast_request_and_dial(type, format, data, timeout, outstate, 0, cidnum, cidname, NULL, uniqueid);
2257 }
2258
2259 -struct ast_channel *ast_request(const char *type, int format, void *data, int *cause)
2260 +struct ast_channel *ast_request(const char *type, int format, void *data, int *cause, char *uniqueid)
2261 {
2262 struct chanlist *chan;
2263 struct ast_channel *c;
2264 @@ -2517,6 +2548,7 @@
2265 if (!(c = chan->tech->requester(type, capabilities, data, cause)))
2266 return NULL;
2267
2268 + if (uniqueid) strncpy(c->uniqueid, uniqueid, sizeof(c->uniqueid));
2269 if (c->_state == AST_STATE_DOWN) {
2270 manager_event(EVENT_FLAG_CALL, "Newchannel",
2271 "Channel: %s\r\n"
2272 @@ -2764,6 +2796,29 @@
2273 return res;
2274 }
2275
2276 +int ast_channel_masquerade_locked(struct ast_channel *original, struct ast_channel *clone)
2277 +{
2278 + struct ast_frame null = { AST_FRAME_NULL, };
2279 + int res = -1;
2280 + ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n",
2281 + clone->name, original->name);
2282 + if (original->masq) {
2283 + ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n",
2284 + original->masq->name, original->name);
2285 + } else if (clone->masqr) {
2286 + ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n",
2287 + clone->name, clone->masqr->name);
2288 + } else {
2289 + original->masq = clone;
2290 + clone->masqr = original;
2291 + ast_queue_frame(original, &null);
2292 + ast_queue_frame(clone, &null);
2293 + ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name);
2294 + res = 0;
2295 + }
2296 + return res;
2297 +}
2298 +
2299 void ast_change_name(struct ast_channel *chan, char *newname)
2300 {
2301 char tmp[256];
2302 @@ -3130,15 +3185,14 @@
2303 );
2304 }
2305
2306 -int ast_setstate(struct ast_channel *chan, int state)
2307 -{
2308 +int ast_setstate_and_cid(struct ast_channel *chan, int state, char *cid_num, char *cid_name) {
2309 int oldstate = chan->_state;
2310
2311 if (oldstate == state)
2312 return 0;
2313
2314 chan->_state = state;
2315 - ast_device_state_changed_literal(chan->name);
2316 + ast_device_state_changed_literal(chan->name, cid_num, cid_name);
2317 manager_event(EVENT_FLAG_CALL,
2318 (oldstate == AST_STATE_DOWN) ? "Newchannel" : "Newstate",
2319 "Channel: %s\r\n"
2320 @@ -3154,6 +3208,10 @@
2321 return 0;
2322 }
2323
2324 +int ast_setstate(struct ast_channel *chan, int state) {
2325 + return ast_setstate_and_cid(chan, state, NULL, NULL);
2326 +}
2327 +
2328 /*--- Find bridged channel */
2329 struct ast_channel *ast_bridged_channel(struct ast_channel *chan)
2330 {
2331 @@ -3331,6 +3389,7 @@
2332 char callee_warning = 0;
2333 int to;
2334
2335 +
2336 if (c0->_bridge) {
2337 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n",
2338 c0->name, c0->_bridge->name);
2339 @@ -3341,6 +3400,10 @@
2340 c1->name, c1->_bridge->name);
2341 return -1;
2342 }
2343 +
2344 + if (IS_DIGITAL(c0->transfercapability) || IS_DIGITAL(c1->transfercapability)) {
2345 + config->flags = 0;
2346 + }
2347
2348 /* Stop if we're a zombie or need a soft hangup */
2349 if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) ||
2350 diff -urN asterisk-1.2.4.orig/channels/Makefile asterisk-1.2.4/channels/Makefile
2351 --- asterisk-1.2.4.orig/channels/Makefile 2005-12-15 11:52:30.000000000 +0100
2352 +++ asterisk-1.2.4/channels/Makefile 2006-01-31 09:41:43.000000000 +0100
2353 @@ -122,6 +122,35 @@
2354 endif
2355 endif # WITHOUT_ZAPTEL
2356
2357 +ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/capi20.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/capi20.h),)
2358 + CHANNEL_LIBS+=chan_capi.so
2359 +# uncomment the following line if you really never ever want early b3 connects,
2360 +# you can also configure it in the dialstring, this is just for performance
2361 +# NOTE: this is probably obsolete by using the "R" dial option
2362 +#CFLAGS+=-DCAPI_NEVER_EVER_EARLY_B3_CONNECTS
2363 +
2364 +# uncommnet next line to force dtmf software detection/generation, can also be configured
2365 +# in capi.conf on a perdevice basis (softdtmf=1)
2366 +#CFLAGS+=-DCAPI_FORCE_SOFTWARE_DTMF
2367 +
2368 +# uncomment the next line if you are in the ulaw world
2369 +#CFLAGS+=-DCAPI_ULAW
2370 +
2371 +# very experimental echo squelching
2372 +CFLAGS+=-DCAPI_ES
2373 +
2374 +#gains
2375 +CFLAGS+=-DCAPI_GAIN
2376 +
2377 +# what do to with call waiting connect indications?
2378 +# uncomment the next line for call deflection in that case
2379 +CFLAGS+=-DCAPI_DEFLECT_ON_CIRCUITBUSY
2380 +
2381 +# audio sync
2382 +CFLAGS+=-DCAPI_SYNC
2383 +
2384 +endif
2385 +
2386 ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/vpbapi.h),)
2387 CHANNEL_LIBS+=chan_vpb.so
2388 CFLAGS+=-DLINUX
2389 @@ -220,6 +249,9 @@
2390 chan_nbs.so: chan_nbs.o
2391 $(CC) $(SOLINK) -o $@ $< -lnbs
2392
2393 +chan_capi.so: chan_capi.o
2394 + $(CC) $(SOLINK) -o $@ $< -lcapi20
2395 +
2396 chan_vpb.o: chan_vpb.c
2397 $(CXX) -c $(CFLAGS) -o $@ chan_vpb.c
2398
2399 diff -urN asterisk-1.2.4.orig/channels/chan_agent.c asterisk-1.2.4/channels/chan_agent.c
2400 --- asterisk-1.2.4.orig/channels/chan_agent.c 2006-01-13 07:07:39.000000000 +0100
2401 +++ asterisk-1.2.4/channels/chan_agent.c 2006-01-31 09:41:43.000000000 +0100
2402 @@ -1331,7 +1331,7 @@
2403 chan = agent_new(p, AST_STATE_DOWN);
2404 } else if (!p->owner && !ast_strlen_zero(p->loginchan)) {
2405 /* Adjustable agent */
2406 - p->chan = ast_request("Local", format, p->loginchan, cause);
2407 + p->chan = ast_request("Local", format, p->loginchan, cause, NULL);
2408 if (p->chan)
2409 chan = agent_new(p, AST_STATE_DOWN);
2410 }
2411 diff -urN asterisk-1.2.4.orig/channels/chan_capi.c asterisk-1.2.4/channels/chan_capi.c
2412 --- asterisk-1.2.4.orig/channels/chan_capi.c 1970-01-01 01:00:00.000000000 +0100
2413 +++ asterisk-1.2.4/channels/chan_capi.c 2006-01-31 09:41:43.000000000 +0100
2414 @@ -0,0 +1,2888 @@
2415 +/*
2416 + * (CAPI*)
2417 + *
2418 + * An implementation of Common ISDN API 2.0 for Asterisk
2419 + *
2420 + * Copyright (C) 2002, 2003, 2004, 2005 Junghanns.NET GmbH
2421 + *
2422 + * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
2423 + *
2424 + * This program is free software and may be modified and
2425 + * distributed under the terms of the GNU Public License.
2426 + */
2427 +
2428 +#include <sys/time.h>
2429 +#include <sys/signal.h>
2430 +#include <stdlib.h>
2431 +#include <stdio.h>
2432 +#include <string.h>
2433 +#include <errno.h>
2434 +#include <unistd.h>
2435 +#include <fcntl.h>
2436 +#include <sys/types.h>
2437 +#include <asterisk/lock.h>
2438 +#include <asterisk/frame.h>
2439 +#include <asterisk/channel.h>
2440 +#include <asterisk/logger.h>
2441 +#include <asterisk/module.h>
2442 +#include <asterisk/pbx.h>
2443 +#include <asterisk/config.h>
2444 +#include <asterisk/options.h>
2445 +#include <asterisk/features.h>
2446 +#include <asterisk/utils.h>
2447 +#include <asterisk/cli.h>
2448 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
2449 +#include <capi_bsd.h>
2450 +#else
2451 +#include <linux/capi.h>
2452 +#endif
2453 +#include <capi20.h>
2454 +#include <asterisk/dsp.h>
2455 +#include <asterisk/xlaw.h>
2456 +#include <asterisk/chan_capi.h>
2457 +
2458 +unsigned ast_capi_ApplID;
2459 +_cword ast_capi_MessageNumber=1;
2460 +static char desc[] = "Common ISDN API for Asterisk";
2461 +#ifdef CAPI_ULAW
2462 +static char tdesc[] = "Common ISDN API Driver (0.4.0) muLaw";
2463 +#else
2464 +static char tdesc[] = "Common ISDN API Driver (0.4.0) aLaw ";
2465 +#endif
2466 +static char type[] = "CAPI";
2467 +
2468 +
2469 +static int usecnt;
2470 +AST_MUTEX_DEFINE_STATIC(usecnt_lock);
2471 +AST_MUTEX_DEFINE_STATIC(iflock);
2472 +AST_MUTEX_DEFINE_STATIC(pipelock);
2473 +AST_MUTEX_DEFINE_STATIC(monlock);
2474 +AST_MUTEX_DEFINE_STATIC(contrlock);
2475 +AST_MUTEX_DEFINE_STATIC(capi_send_buffer_lock);
2476 +AST_MUTEX_DEFINE_STATIC(capi_put_lock);
2477 +
2478 +#ifdef CAPI_ULAW
2479 +static int capi_capability = AST_FORMAT_ULAW;
2480 +#else
2481 +static int capi_capability = AST_FORMAT_ALAW;
2482 +#endif
2483 +
2484 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
2485 +static CAPIProfileBuffer_t profile;
2486 +#else
2487 +static struct ast_capi_profile profile;
2488 +#endif
2489 +static pthread_t monitor_thread = -1;
2490 +
2491 +static struct ast_capi_pvt *iflist = NULL;
2492 +static struct capi_pipe *pipelist = NULL;
2493 +static int capi_last_plci = 0;
2494 +static struct ast_capi_controller *capi_controllers[AST_CAPI_MAX_CONTROLLERS];
2495 +static int capi_num_controllers = 0;
2496 +static int capi_counter = 0;
2497 +static unsigned long capi_used_controllers=0;
2498 +
2499 +static char capi_send_buffer[AST_CAPI_MAX_B3_BLOCKS * AST_CAPI_MAX_B3_BLOCK_SIZE];
2500 +static int capi_send_buffer_handle = 0;
2501 +
2502 +char capi_national_prefix[AST_MAX_EXTENSION];
2503 +char capi_international_prefix[AST_MAX_EXTENSION];
2504 +
2505 +int capidebug = 0;
2506 +
2507 +static const struct ast_channel_tech capi_tech;
2508 +
2509 +MESSAGE_EXCHANGE_ERROR _capi_put_cmsg(_cmsg *CMSG) {
2510 + MESSAGE_EXCHANGE_ERROR error;
2511 + if (ast_mutex_lock(&capi_put_lock)) {
2512 + ast_log(LOG_WARNING,"Unable to lock capi put!\n");
2513 + return -1;
2514 + }
2515 + error = capi20_put_cmsg(CMSG);
2516 + if (ast_mutex_unlock(&capi_put_lock)) {
2517 + ast_log(LOG_WARNING,"Unable to unlock capi put!\n");
2518 + return -1;
2519 + }
2520 + return error;
2521 +}
2522 +
2523 +
2524 +MESSAGE_EXCHANGE_ERROR check_wait_get_cmsg(_cmsg *CMSG) {
2525 + MESSAGE_EXCHANGE_ERROR Info;
2526 + struct timeval tv;
2527 + tv.tv_sec = 0;
2528 + tv.tv_usec = 10000;
2529 + Info = capi20_waitformessage(ast_capi_ApplID,&tv);
2530 + if ((Info != 0x0000) && (Info != 0x1104)) {
2531 + if (capidebug) {
2532 + ast_log(LOG_DEBUG, "Error waiting for cmsg... INFO = %#x\n", Info);
2533 + }
2534 + return Info;
2535 + }
2536 +
2537 + if (Info == 0x0000) {
2538 + Info = capi_get_cmsg(CMSG,ast_capi_ApplID);
2539 + }
2540 + return Info;
2541 +}
2542 +
2543 +
2544 +unsigned ListenOnController(unsigned long CIPmask,unsigned controller) {
2545 + MESSAGE_EXCHANGE_ERROR error;
2546 + _cmsg CMSG,CMSG2;
2547 +
2548 + LISTEN_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, controller);
2549 +#ifdef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
2550 + LISTEN_REQ_INFOMASK(&CMSG) = 0x00ff; // lots of info ;)
2551 +#else
2552 + LISTEN_REQ_INFOMASK(&CMSG) = 0x03ff; // lots of info ;) + early B3 connect
2553 +#endif
2554 + LISTEN_REQ_CIPMASK(&CMSG) = CIPmask;
2555 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2556 + return error;
2557 + }
2558 + while (!IS_LISTEN_CONF(&CMSG2)) {
2559 + error = check_wait_get_cmsg(&CMSG2);
2560 + }
2561 + return 0;
2562 +}
2563 +
2564 +// Echo cancellation is for cards w/ integrated echo cancellation only
2565 +// (i.e. Eicon active cards support it)
2566 +
2567 +#define EC_FUNCTION_ENABLE 1
2568 +#define EC_FUNCTION_DISABLE 2
2569 +#define EC_FUNCTION_FREEZE 3
2570 +#define EC_FUNCTION_RESUME 4
2571 +#define EC_FUNCTION_RESET 5
2572 +#define EC_OPTION_DISABLE_NEVER 0
2573 +#define EC_OPTION_DISABLE_G165 (1<<1)
2574 +#define EC_OPTION_DISABLE_G164_OR_G165 (1<<1 | 1<<2)
2575 +#define EC_DEFAULT_TAIL 64
2576 +
2577 +static int capi_echo_canceller(struct ast_channel *c, int function) {
2578 + struct ast_capi_pvt *i = c->tech_pvt;
2579 + MESSAGE_EXCHANGE_ERROR error;
2580 + _cmsg CMSG;
2581 + unsigned char buf[7];
2582 +
2583 + /* If echo cancellation is not requested or supported, don't attempt to enable it */
2584 + ast_mutex_lock(&contrlock);
2585 + if (!capi_controllers[i->controller]->echocancel || !i->doEC) {
2586 + ast_mutex_unlock(&contrlock);
2587 + return 0;
2588 + }
2589 + ast_mutex_unlock(&contrlock);
2590 +
2591 + if (option_verbose > 2)
2592 + 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);
2593 +
2594 + FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
2595 + FACILITY_REQ_NCCI(&CMSG) = i->NCCI;
2596 + FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 6; /* Echo canceller */
2597 +
2598 + buf[0]=6; /* msg size */
2599 + buf[1]=function;
2600 + if (function == EC_FUNCTION_ENABLE) {
2601 + buf[3]=i->ecOption; /* bit field - ignore echo canceller disable tone */
2602 + buf[5]=i->ecTail; /* Tail length, ms */
2603 + }
2604 + else {
2605 + buf[3]=0;
2606 + buf[5]=0;
2607 + }
2608 +
2609 + // Always null:
2610 + buf[2]=0;
2611 + buf[4]=0;
2612 + buf[6]=0;
2613 +
2614 + FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = buf;
2615 +
2616 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2617 + ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
2618 + return error;
2619 + }
2620 +
2621 + if (option_verbose > 5)
2622 + ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_REQ (PLCI=%#x)\n",i->PLCI);
2623 +
2624 + return 0;
2625 +}
2626 +
2627 +int capi_detect_dtmf(struct ast_channel *c, int flag) {
2628 + struct ast_capi_pvt *i = c->tech_pvt;
2629 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
2630 + MESSAGE_EXCHANGE_ERROR error;
2631 + _cmsg CMSG;
2632 + unsigned char buf[9];
2633 + // does the controller support dtmf? and do we want to use it?
2634 + ast_mutex_lock(&contrlock);
2635 + if ((capi_controllers[i->controller]->dtmf == 1) && (i->doDTMF == 0)) {
2636 + ast_mutex_unlock(&contrlock);
2637 + FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
2638 + FACILITY_REQ_PLCI(&CMSG) = i->PLCI;
2639 + FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 1;
2640 + buf[0] = 8;
2641 + if (flag == 1) {
2642 + buf[1] = 1;
2643 + } else {
2644 + buf[1] = 2;
2645 + }
2646 + buf[2] = 0;
2647 + buf[3] = AST_CAPI_DTMF_DURATION;
2648 + buf[4] = 0;
2649 + buf[5] = AST_CAPI_DTMF_DURATION;
2650 + buf[6] = 0;
2651 + buf[7] = 0;
2652 + buf[8] = 0;
2653 + FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = buf;
2654 +
2655 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2656 + ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
2657 + return error;
2658 + } else {
2659 + if (option_verbose > 5) {
2660 + ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_REQ (PLCI=%#x)\n",i->PLCI);
2661 + }
2662 + }
2663 + } else {
2664 + ast_mutex_unlock(&contrlock);
2665 +
2666 +#endif
2667 + // do software dtmf detection
2668 + i->doDTMF = 1; // just being paranoid again...
2669 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
2670 + }
2671 +#endif
2672 + return 0;
2673 +}
2674 +static int capi_send_digit(struct ast_channel *c,char digit) {
2675 + struct ast_capi_pvt *i = c->tech_pvt;
2676 + MESSAGE_EXCHANGE_ERROR error;
2677 + _cmsg CMSG;
2678 + unsigned char buf[10];
2679 +
2680 + if (i->state != CAPI_STATE_BCONNECTED) {
2681 + return 0;
2682 + }
2683 +
2684 +
2685 +#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
2686 + if(i->earlyB3 == 1)
2687 + /* we should really test for the network saying the number is incomplete
2688 + since i'm only doing a test and this is true at the right time
2689 + i'm going with this */
2690 + {
2691 +
2692 + INFO_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
2693 + INFO_REQ_PLCI(&CMSG) = i->PLCI;
2694 + buf[0] = 2;
2695 + buf[1] = 0x80;
2696 + buf[2] = digit;
2697 + INFO_REQ_CALLEDPARTYNUMBER(&CMSG) = buf;
2698 +
2699 +
2700 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2701 + ast_log(LOG_ERROR,"error sending CALLEDPARTYNUMBER INFO (error=%#x)\n",error);
2702 + return error;
2703 + } else {
2704 + if (option_verbose > 5) {
2705 + ast_verbose(VERBOSE_PREFIX_4 "sent CALLEDPARTYNUMBER INFO digit = %c (PLCI=%#x)\n", digit, i->PLCI);
2706 + }
2707 + }
2708 +
2709 + } else {
2710 +#endif
2711 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
2712 + ast_mutex_lock(&contrlock);
2713 + if ((capi_controllers[i->controller]->dtmf == 0) || (i->doDTMF == 1)) {
2714 +#endif
2715 + // let * fake it
2716 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
2717 + ast_mutex_unlock(&contrlock);
2718 +#endif
2719 + return -1;
2720 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
2721 + }
2722 + ast_mutex_unlock(&contrlock);
2723 +
2724 + FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
2725 + FACILITY_REQ_PLCI(&CMSG) = i->NCCI;
2726 + FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 1;
2727 + buf[0] = 8;
2728 +
2729 + buf[1] = 3;
2730 + buf[2] = 0;
2731 +
2732 + buf[3] = AST_CAPI_DTMF_DURATION;
2733 + buf[4] = 0;
2734 +
2735 + buf[5] = AST_CAPI_DTMF_DURATION;
2736 + buf[6] = 0;
2737 +
2738 + buf[7] = 1;
2739 + buf[8] = digit;
2740 + buf[9] = 0;
2741 + FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = buf;
2742 +
2743 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2744 + ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
2745 + return error;
2746 + } else {
2747 + if (option_verbose > 4) {
2748 + ast_verbose(VERBOSE_PREFIX_3 "sent dtmf '%c'\n",digit);
2749 + }
2750 + }
2751 +#endif
2752 +#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
2753 + }
2754 +#endif
2755 + return 0;
2756 +}
2757 +
2758 +static int capi_alert(struct ast_channel *c) {
2759 + struct ast_capi_pvt *i = c->tech_pvt;
2760 + MESSAGE_EXCHANGE_ERROR error;
2761 + _cmsg CMSG;
2762 +
2763 + ALERT_REQ_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
2764 + ALERT_REQ_PLCI(&CMSG) = i->PLCI;
2765 +
2766 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2767 + ast_log(LOG_ERROR,"error sending ALERT_REQ PLCI = %#x\n",i->PLCI);
2768 + return -1;
2769 + } else {
2770 + if (option_verbose > 5) {
2771 + ast_verbose(VERBOSE_PREFIX_4 "sent ALERT_REQ PLCI = %#x\n",i->PLCI);
2772 + }
2773 + }
2774 +
2775 + i->state = CAPI_STATE_ALERTING;
2776 + return 0;
2777 +}
2778 +
2779 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
2780 +static int capi_deflect(struct ast_channel *chan, void *data)
2781 +{
2782 + struct ast_capi_pvt *i = chan->tech_pvt;
2783 + MESSAGE_EXCHANGE_ERROR Info;
2784 + _cmsg CMSG;
2785 + char bchaninfo[1];
2786 + char fac[60];
2787 + int res=0;
2788 + int ms=3000;
2789 +
2790 + if (!data) {
2791 + ast_log(LOG_WARNING, "cd requires an argument (destination phone number)\n");
2792 + return -1;
2793 + }
2794 +
2795 + if ((i->state == CAPI_STATE_CONNECTED) || (i->state == CAPI_STATE_BCONNECTED)) {
2796 + ast_log(LOG_ERROR, "call deflection does not work with calls that are already connected!\n");
2797 + return -1;
2798 + }
2799 + // wait until the channel is alerting, so we dont drop the call and interfer with msgs
2800 + while ((ms > 0) && (i->state != CAPI_STATE_ALERTING)) {
2801 + sleep(100);
2802 + ms -= 100;
2803 + }
2804 +
2805 + // make sure we hang up correctly
2806 + i->state = CAPI_STATE_CONNECTPENDING;
2807 +
2808 + fac[0]=0; // len
2809 + fac[1]=0; //len
2810 + fac[2]=0x01; // Use D-Chan
2811 + fac[3]=0; // Keypad len
2812 + fac[4]=31; // user user data? len = 31 = 29 + 2
2813 + fac[5]=0x1c; // magic?
2814 + fac[6]=0x1d; // strlen destination + 18 = 29
2815 + fac[7]=0x91; // ..
2816 + fac[8]=0xA1;
2817 + fac[9]=0x1A; // strlen destination + 15 = 26
2818 + fac[10]=0x02;
2819 + fac[11]=0x01;
2820 + fac[12]=0x70;
2821 + fac[13]=0x02;
2822 + fac[14]=0x01;
2823 + fac[15]=0x0d;
2824 + fac[16]=0x30;
2825 + fac[17]=0x12; // strlen destination + 7 = 18
2826 + fac[18]=0x30; // ...hm 0x30
2827 + fac[19]=0x0d; // strlen destination + 2
2828 + fac[20]=0x80; // CLIP
2829 + fac[21]=0x0b; // strlen destination
2830 + fac[22]=0x01; // destination start
2831 + fac[23]=0x01; //
2832 + fac[24]=0x01; //
2833 + fac[25]=0x01; //
2834 + fac[26]=0x01; //
2835 + fac[27]=0x01; //
2836 + fac[28]=0x01; //
2837 + fac[29]=0x01; //
2838 + fac[30]=0x01; //
2839 + fac[31]=0x01; //
2840 + fac[32]=0x01; //
2841 + fac[33]=0x01; // 0x1 = sending complete
2842 + fac[34]=0x01;
2843 + fac[35]=0x01;
2844 +
2845 + memcpy((unsigned char *)fac+22,data,strlen(data));
2846 + fac[22+strlen(data)]=0x01; // fill with 0x01 if number is only 6 numbers (local call)
2847 + fac[23+strlen(data)]=0x01;
2848 + fac[24+strlen(data)]=0x01;
2849 + fac[25+strlen(data)]=0x01;
2850 + fac[26+strlen(data)]=0x01;
2851 +
2852 + fac[6]=18+strlen(data);
2853 + fac[9]=15+strlen(data);
2854 + fac[17]=7+strlen(data);
2855 + fac[19]=2+strlen(data);
2856 + fac[21]=strlen(data);
2857 +
2858 + bchaninfo[0] = 0x1;
2859 + INFO_REQ_HEADER(&CMSG,ast_capi_ApplID,ast_capi_MessageNumber++,0);
2860 + INFO_REQ_CONTROLLER(&CMSG) = i->controller;
2861 + INFO_REQ_PLCI(&CMSG) = i->PLCI;
2862 + INFO_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char*)bchaninfo; // use D-Channel
2863 + INFO_REQ_KEYPADFACILITY(&CMSG) = 0;
2864 + INFO_REQ_USERUSERDATA(&CMSG) = 0;
2865 + INFO_REQ_FACILITYDATAARRAY(&CMSG) = (unsigned char*) fac + 4;
2866 +
2867 + if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
2868 + ast_log(LOG_ERROR,"Error sending INFO_REQ\n");
2869 + return Info;
2870 + } else {
2871 + if (capidebug) {
2872 + // ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(&CMSG));
2873 + ast_log(LOG_NOTICE,"sent INFO_REQ PLCI = %#x\n",i->PLCI);
2874 + }
2875 + }
2876 +
2877 + return res;
2878 +}
2879 +#endif
2880 +
2881 +void remove_pipe(int PLCI) {
2882 + struct capi_pipe *p,*ptmp;
2883 +
2884 + ast_mutex_lock(&pipelock);
2885 + p = pipelist;
2886 + ptmp = NULL;
2887 + while (p) {
2888 + if (p->PLCI == PLCI) {
2889 + if (ptmp == NULL) {
2890 + // mypipe == head of pipelist
2891 + pipelist = p->next;
2892 + if(p->fd > -1) close(p->fd);
2893 + if(p->i != NULL && p->i->fd > -1) close(p->i->fd);
2894 + free(p);
2895 + if (option_verbose > 4) {
2896 + ast_verbose(VERBOSE_PREFIX_3 "removed pipe for PLCI = %#x\n",PLCI);
2897 + }
2898 + break;
2899 + } else {
2900 + // somehwere inbetween or at the end
2901 + ptmp->next = p->next;
2902 + if (p->next == NULL) {
2903 + capi_last_plci = p->PLCI;
2904 + }
2905 + if(p->fd > -1) close(p->fd);
2906 + if(p->i != NULL && p->i->fd > -1) close(p->i->fd);
2907 + free(p);
2908 + if (option_verbose > 4) {
2909 + ast_verbose(VERBOSE_PREFIX_3 "removed pipe for PLCI = %#x\n",PLCI);
2910 + }
2911 + break;
2912 + }
2913 + }
2914 + ptmp = p;
2915 + p = p->next;
2916 + }
2917 + ast_mutex_unlock(&pipelock);
2918 +}
2919 +
2920 +static int capi_activehangup(struct ast_channel *c) {
2921 + struct ast_capi_pvt *i = c->tech_pvt;
2922 + MESSAGE_EXCHANGE_ERROR error;
2923 + _cmsg CMSG;
2924 +
2925 + if (option_verbose > 2) {
2926 + if (capidebug)
2927 + ast_verbose(VERBOSE_PREFIX_4 "activehangingup\n");
2928 + }
2929 +
2930 + if (i == NULL) {
2931 + return 0;
2932 + }
2933 +
2934 + if (c->_state == AST_STATE_RING) {
2935 + CONNECT_RESP_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
2936 + CONNECT_RESP_PLCI(&CMSG) = i->PLCI;
2937 + CONNECT_RESP_REJECT(&CMSG) = 2;
2938 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2939 + ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",i->PLCI);
2940 + } else {
2941 + if (option_verbose > 5) {
2942 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",i->PLCI);
2943 + }
2944 + }
2945 + return 0;
2946 + }
2947 +
2948 + // active disconnect
2949 + if (i->state == CAPI_STATE_BCONNECTED) {
2950 + DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
2951 + DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
2952 +
2953 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2954 + ast_log(LOG_ERROR, "error sending DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
2955 + } else {
2956 + if (option_verbose > 5) {
2957 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
2958 + }
2959 + }
2960 + // wait for the B3 layer to go down
2961 + while (i->state != CAPI_STATE_CONNECTED) {
2962 + usleep(10000);
2963 + }
2964 + }
2965 + if ((i->state == CAPI_STATE_CONNECTED) || (i->state == CAPI_STATE_CONNECTPENDING)){
2966 + DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
2967 + DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
2968 +
2969 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
2970 + ast_log(LOG_ERROR, "error sending DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
2971 + } else {
2972 + if (option_verbose > 5) {
2973 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
2974 + }
2975 + }
2976 + // wait for the B1 layer to go down
2977 + while (i->state != CAPI_STATE_DISCONNECTED) {
2978 + usleep(10000);
2979 + }
2980 + }
2981 + return 0;
2982 +}
2983 +
2984 +static int capi_hangup(struct ast_channel *c) {
2985 + struct ast_capi_pvt *i = c->tech_pvt;
2986 +
2987 + // hmm....ok...this is called to free the capi interface (passive disconnect)
2988 + // or to bring down the channel (active disconnect)
2989 +
2990 + if (option_verbose > 3)
2991 + ast_verbose(VERBOSE_PREFIX_3 "CAPI Hangingup\n");
2992 +
2993 + if (i == NULL) {
2994 + ast_log(LOG_ERROR,"channel has no interface!\n");
2995 + return -1;
2996 + }
2997 +
2998 + // are we down, yet?
2999 + if (i->state != CAPI_STATE_DISCONNECTED) {
3000 + // no
3001 + capi_activehangup(c);
3002 + }
3003 +
3004 + remove_pipe(i->PLCI);
3005 + i->PLCI = 0;
3006 + i->NCCI = 0;
3007 + if ((i->doDTMF == 1) && (i->vad != NULL)) {
3008 + ast_dsp_free(i->vad);
3009 + }
3010 + ast_smoother_free(i->smoother); // discard any frames left hanging
3011 + i->smoother=ast_smoother_new(AST_CAPI_MAX_B3_BLOCK_SIZE * 2);
3012 + memset(i->cid,0,sizeof(i->cid));
3013 + i->owner=NULL;
3014 + ast_mutex_lock(&usecnt_lock);
3015 + usecnt--;
3016 + ast_mutex_unlock(&usecnt_lock);
3017 + ast_update_use_count();
3018 + i->mypipe = NULL;
3019 + i = NULL;
3020 + c->tech_pvt = NULL;
3021 + ast_setstate(c,AST_STATE_DOWN);
3022 + return 0;
3023 +}
3024 +
3025 +static char *capi_number(char *data,int strip) {
3026 + unsigned len = *data;
3027 + // XXX fix me
3028 + // convert a capi struct to a \0 terminated string
3029 + if (!len || len < (unsigned int) strip) return NULL;
3030 + len = len - strip;
3031 + data = (char *)(data + 1 + strip);
3032 + return strndup((char *)data,len);
3033 +}
3034 +
3035 +int capi_call(struct ast_channel *c, char *idest, int timeout)
3036 +{
3037 + struct ast_capi_pvt *i;
3038 + struct capi_pipe *p = NULL;
3039 + int fds[2];
3040 + char *dest,*interface;
3041 + char buffer[AST_MAX_EXTENSION];
3042 + char called[AST_MAX_EXTENSION],calling[AST_MAX_EXTENSION];
3043 + char bchaninfo[3];
3044 + long flags;
3045 +
3046 + _cmsg CMSG;
3047 + MESSAGE_EXCHANGE_ERROR error;
3048 +
3049 + strncpy(buffer,idest,sizeof(buffer)-1);
3050 + interface = strtok(buffer, "/");
3051 + dest = strtok(NULL, "/");
3052 +
3053 +
3054 + if (!dest) {
3055 + ast_log(LOG_WARNING, "Destination %s requires a real destination\n", idest);
3056 + return -1;
3057 + }
3058 + i = c->tech_pvt;
3059 + i->doB3 = AST_CAPI_B3_DONT; // <homer>DOH</homer>
3060 +
3061 + // always B3
3062 + if (((char *)dest)[0] == 'b') {
3063 + i->doB3 = AST_CAPI_B3_ALWAYS;
3064 + }
3065 + // only do B3 on successfull calls
3066 + if (((char *)dest)[0] == 'B') {
3067 + i->doB3 = AST_CAPI_B3_ON_SUCCESS;
3068 + }
3069 +
3070 + if (i->doB3 != AST_CAPI_B3_DONT) {
3071 + dest++;
3072 + }
3073 +
3074 + if (option_verbose > 1) {
3075 + if (capidebug)
3076 + ast_verbose(VERBOSE_PREFIX_2 "CAPI Call %s %s", c->name, i->doB3?"with B3":"");
3077 + }
3078 + switch (c->cid.cid_pres) {
3079 + case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
3080 + case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
3081 + case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
3082 + case PRES_ALLOWED_NETWORK_NUMBER:
3083 + case PRES_NUMBER_NOT_AVAILABLE:
3084 + i->CLIR = 0;
3085 + break;
3086 + case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
3087 + case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
3088 + case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
3089 + case PRES_PROHIB_NETWORK_NUMBER:
3090 + i->CLIR = 1;
3091 + break;
3092 + default:
3093 + i->CLIR = 0;
3094 + }
3095 +
3096 + if (pipe(fds) == 0) {
3097 + ast_mutex_lock(&pipelock);
3098 + i->fd = fds[0];
3099 + flags = fcntl(i->fd,F_GETFL);
3100 + fcntl(i->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
3101 + p = malloc(sizeof(struct capi_pipe));
3102 + memset(p, 0, sizeof(struct capi_pipe));
3103 + p->fd = fds[1];
3104 + flags = fcntl(i->fd,F_GETFL);
3105 + fcntl(p->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
3106 + c->fds[0] = i->fd;
3107 + p->PLCI = -1;
3108 + p->i = i;
3109 + p->c = c;
3110 + i->mypipe = p;
3111 + p->next = pipelist;
3112 + pipelist = p;
3113 + if (option_verbose > 4) {
3114 + ast_verbose(VERBOSE_PREFIX_3 "creating pipe for PLCI=-1\n");
3115 + }
3116 + ast_mutex_unlock(&pipelock);
3117 + }
3118 + i->outgoing = 1;
3119 +
3120 + i->MessageNumber = ast_capi_MessageNumber++;
3121 + CONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, i->controller);
3122 + CONNECT_REQ_CONTROLLER(&CMSG) = i->controller;
3123 + CONNECT_REQ_CIPVALUE(&CMSG) = 0x10; // Telephony, could also use 0x04 (3.1Khz audio)
3124 + called[0] = strlen(dest)+1;
3125 + called[1] = 0x80;
3126 + strncpy(&called[2],dest,sizeof(called)-2);
3127 + CONNECT_REQ_CALLEDPARTYNUMBER(&CMSG) = (unsigned char *)called;
3128 + CONNECT_REQ_CALLEDPARTYSUBADDRESS(&CMSG) = NULL;
3129 +
3130 + if (c->cid.cid_num) {
3131 + calling[0] = strlen(c->cid.cid_num)+2;
3132 + calling[1] = 0x0;
3133 + } else {
3134 + calling[0] = 0x0;
3135 + calling[1] = 0x0;
3136 + }
3137 +
3138 + if (i->CLIR == 1) {
3139 + calling[2] = 0xA0; // CLIR
3140 + } else {
3141 + calling[2] = 0x80; // CLIP
3142 + }
3143 +
3144 + if (c->cid.cid_num) {
3145 + strncpy(&calling[3],c->cid.cid_num,sizeof(calling)-3);
3146 + }
3147 + CONNECT_REQ_CALLINGPARTYNUMBER(&CMSG) = (unsigned char *)calling;
3148 + CONNECT_REQ_CALLINGPARTYSUBADDRESS(&CMSG) = NULL;
3149 +
3150 + CONNECT_REQ_B1PROTOCOL(&CMSG) = 1;
3151 + CONNECT_REQ_B2PROTOCOL(&CMSG) = 1; // 1
3152 + CONNECT_REQ_B3PROTOCOL(&CMSG) = 0;
3153 +
3154 + bchaninfo[0] = 2;
3155 + bchaninfo[1] = 0x0;
3156 + bchaninfo[2] = 0x0;
3157 + CONNECT_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char *)bchaninfo; // 0
3158 +
3159 + if ((error = _capi_put_cmsg(&CMSG))) {
3160 + ast_log(LOG_ERROR,"error sending CONNECT_REQ (error=%#x)\n",error);
3161 + return error;
3162 + } else {
3163 + if (option_verbose > 5) {
3164 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_REQ MN =%#x\n",CMSG.Messagenumber);
3165 + }
3166 + }
3167 +
3168 + i->state = CAPI_STATE_CONNECTPENDING;
3169 +
3170 + ast_setstate(c, AST_STATE_DIALING);
3171 +
3172 + // XXX fixme, not nice:
3173 +/* if (i->controller > 0) {
3174 + capi_controllers[i->controller]->nfreebchannels--;
3175 + } */
3176 +
3177 + // now we shall return .... the rest has to be done by handle_msg
3178 + return 0;
3179 +}
3180 +
3181 +
3182 +static int capi_answer(struct ast_channel *c) {
3183 + struct ast_capi_pvt *i = c->tech_pvt;
3184 + MESSAGE_EXCHANGE_ERROR error;
3185 + _cmsg CMSG;
3186 + char buf[AST_MAX_EXTENSION];
3187 + char *dnid;
3188 +
3189 + if (i->isdnmode && (strlen(i->incomingmsn)<strlen(i->dnid)))
3190 + dnid = i->dnid + strlen(i->incomingmsn);
3191 + else
3192 + dnid = i->dnid;
3193 +
3194 + CONNECT_RESP_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
3195 + CONNECT_RESP_PLCI(&CMSG) = i->PLCI;
3196 + CONNECT_RESP_REJECT(&CMSG) = 0;
3197 + buf[0] = strlen(dnid)+2;
3198 + buf[1] = 0x0;
3199 + buf[2] = 0x80;
3200 + strncpy(&buf[3],dnid,sizeof(buf)-4);
3201 + CONNECT_RESP_CONNECTEDNUMBER(&CMSG) = (unsigned char *)buf;
3202 + CONNECT_RESP_CONNECTEDSUBADDRESS(&CMSG) = NULL;
3203 + CONNECT_RESP_LLC(&CMSG) = NULL;
3204 + CONNECT_RESP_B1PROTOCOL(&CMSG) = 1;
3205 + CONNECT_RESP_B2PROTOCOL(&CMSG) = 1;
3206 + CONNECT_RESP_B3PROTOCOL(&CMSG) = 0;
3207 +
3208 + if (option_verbose > 3)
3209 + ast_verbose(VERBOSE_PREFIX_3 "CAPI Answering for MSN %s\n", dnid);
3210 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3211 + return -1;
3212 + } else {
3213 + if (option_verbose > 5) {
3214 + if (capidebug)
3215 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP PLCI = %#x DNID = %s\n",i->PLCI,i->dnid);
3216 + }
3217 + }
3218 +
3219 + i->state = CAPI_STATE_ANSWERING;
3220 + i->doB3 = AST_CAPI_B3_DONT;
3221 + i->outgoing = 0;
3222 + i->earlyB3 = -1;
3223 +
3224 + return 0;
3225 +}
3226 +
3227 +struct ast_frame *capi_read(struct ast_channel *c) {
3228 + struct ast_capi_pvt *i = c->tech_pvt;
3229 + int readsize = 0;
3230 +
3231 + if ((i->state == CAPI_STATE_REMOTE_HANGUP)) {
3232 + ast_log(LOG_ERROR,"this channel is not connected\n");
3233 + return NULL;
3234 + }
3235 + if (i->state == CAPI_STATE_ONHOLD) {
3236 + i->fr.frametype = AST_FRAME_NULL;
3237 + return &i->fr;
3238 + }
3239 +
3240 + if (i == NULL) {
3241 + ast_log(LOG_ERROR,"channel has no interface\n");
3242 + return NULL;
3243 + }
3244 + i->fr.frametype = AST_FRAME_NULL;
3245 + i->fr.subclass = 0;
3246 + i->fr.delivery.tv_sec = 0;
3247 + i->fr.delivery.tv_usec = 0;
3248 + readsize = read(i->fd,&i->fr,sizeof(struct ast_frame));
3249 + if (readsize != sizeof(struct ast_frame)) {
3250 + ast_log(LOG_ERROR,"did not read a whole frame\n");
3251 + }
3252 + if (i->fr.frametype == AST_FRAME_VOICE) {
3253 + readsize = read(i->fd,i->fr.data,i->fr.datalen);
3254 + if (readsize != i->fr.datalen) {
3255 + ast_log(LOG_ERROR,"did not read whole frame data\n");
3256 + }
3257 + }
3258 + i->fr.mallocd = 0;
3259 + if (i->fr.frametype == AST_FRAME_NULL) {
3260 + return NULL;
3261 + }
3262 + if ((i->fr.frametype == AST_FRAME_DTMF) && (i->fr.subclass == 'f')) {
3263 + if (strcmp(c->exten, "fax")) {
3264 + if (ast_exists_extension(c, ast_strlen_zero(c->macrocontext) ? c->context : c->macrocontext, "fax", 1, c->cid.cid_num)) {
3265 + if (option_verbose > 2)
3266 + ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", c->name);
3267 + /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
3268 + pbx_builtin_setvar_helper(c,"FAXEXTEN",c->exten);
3269 + if (ast_async_goto(c, c->context, "fax", 1))
3270 + ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", c->name, c->context);
3271 + } else {
3272 + ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
3273 + }
3274 + } else {
3275 + ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
3276 + }
3277 + }
3278 + return &i->fr;
3279 +}
3280 +
3281 +int capi_write(struct ast_channel *c, struct ast_frame *f) {
3282 + struct ast_capi_pvt *i = c->tech_pvt;
3283 + _cmsg CMSG;
3284 + MESSAGE_EXCHANGE_ERROR error;
3285 + int j=0;
3286 + char buf[1000];
3287 + struct ast_frame *fsmooth;
3288 +#ifdef CAPI_ES
3289 + int txavg=0;
3290 +#endif
3291 +
3292 +#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
3293 + // dont send audio to the local exchange!
3294 + if (i->earlyB3 == 1 || !i->NCCI) {
3295 + return 0;
3296 + }
3297 +#endif
3298 +
3299 + if (!i) {
3300 + ast_log(LOG_ERROR,"channel has no interface\n");
3301 + return -1;
3302 + }
3303 +
3304 + if (f->frametype == AST_FRAME_NULL) {
3305 + return 0;
3306 + }
3307 + if (f->frametype == AST_FRAME_DTMF) {
3308 + ast_log(LOG_ERROR,"dtmf frame should be written\n");
3309 + return 0;
3310 + }
3311 + if (f->frametype != AST_FRAME_VOICE) {
3312 + ast_log(LOG_ERROR,"not a voice frame\n");
3313 + return -1;
3314 + }
3315 + if (f->subclass != capi_capability) {
3316 + ast_log(LOG_ERROR,"dont know how to write subclass %d\n",f->subclass);
3317 + return -1;
3318 + }
3319 +// ast_log(LOG_NOTICE,"writing frame %d %d\n",f->frametype,f->subclass);
3320 +
3321 + if (ast_smoother_feed(i->smoother, f)!=0) {
3322 + ast_log(LOG_ERROR,"failed to fill smoother\n");
3323 + return -1;
3324 + }
3325 +
3326 + fsmooth=ast_smoother_read(i->smoother);
3327 + while(fsmooth != NULL) {
3328 + DATA_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
3329 + DATA_B3_REQ_NCCI(&CMSG) = i->NCCI;
3330 + DATA_B3_REQ_DATALENGTH(&CMSG) = fsmooth->datalen;
3331 + DATA_B3_REQ_FLAGS(&CMSG) = 0;
3332 +
3333 + if (ast_mutex_lock(&capi_send_buffer_lock)) {
3334 + ast_log(LOG_WARNING,"Unable to lock B3 send buffer!\n");
3335 + return -1;
3336 + }
3337 +#ifndef CAPI_ES
3338 +#ifdef CAPI_GAIN
3339 + for (j=0;j<fsmooth->datalen;j++) {
3340 + buf[j] = i->g.txgains[reversebits[((unsigned char *)fsmooth->data)[j]]];
3341 + }
3342 +#else
3343 + for (j=0;j<fsmooth->datalen;j++) {
3344 + buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ];
3345 + }
3346 +#endif
3347 +#else
3348 + if ((i->doES == 1)) {
3349 + for (j=0;j<fsmooth->datalen;j++) {
3350 + buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ];
3351 + txavg += abs( capiXLAW2INT(reversebits[ ((unsigned char*)fsmooth->data)[j]]) );
3352 + }
3353 + txavg = txavg/j;
3354 + for(j=0;j<ECHO_TX_COUNT-1;j++) {
3355 + i->txavg[j] = i->txavg[j+1];
3356 + }
3357 + i->txavg[ECHO_TX_COUNT-1] = txavg;
3358 +
3359 +// ast_log(LOG_NOTICE,"txavg = %d\n",txavg);
3360 + } else {
3361 +#ifdef CAPI_GAIN
3362 + for (j=0;j<fsmooth->datalen;j++) {
3363 + buf[j] = i->g.txgains[reversebits[((unsigned char *)fsmooth->data)[j]]];
3364 + }
3365 +#else
3366 + for (j=0;j<fsmooth->datalen;j++) {
3367 + buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ];
3368 + }
3369 +#endif
3370 + }
3371 +#endif
3372 +
3373 + DATA_B3_REQ_DATAHANDLE(&CMSG) = capi_send_buffer_handle;
3374 + memcpy((char *)&capi_send_buffer[(capi_send_buffer_handle % AST_CAPI_MAX_B3_BLOCKS) * AST_CAPI_MAX_B3_BLOCK_SIZE],&buf,fsmooth->datalen);
3375 + 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];
3376 + capi_send_buffer_handle++;
3377 +
3378 + if (ast_mutex_unlock(&capi_send_buffer_lock)) {
3379 + ast_log(LOG_WARNING,"Unable to unlock B3 send buffer!\n");
3380 + return -1;
3381 + }
3382 +
3383 +
3384 +#ifdef CAPI_SYNC
3385 + ast_mutex_lock(&i->lockB3in);
3386 + if ((i->B3in >= 1) && (i->B3in <= AST_CAPI_MAX_B3_BLOCKS)) {
3387 + i->B3in--;
3388 + ast_mutex_unlock(&i->lockB3in);
3389 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3390 + ast_log(LOG_ERROR,"error sending DATA_B3_REQ (error=%#x, datalen=%d) B3in=%d\n",error,fsmooth->datalen,i->B3in);
3391 +// ast_log(LOG_NOTICE,"f: timelen %d b = %d MN = %d \n",fsmooth->timelen,b,CMSG.Messagenumber);
3392 + } else {
3393 + if (option_verbose > 5) {
3394 + if (capidebug)
3395 + ast_verbose(VERBOSE_PREFIX_4 "sent DATA_B3_REQ (NCCI=%#x) (%d bytes)\n",i->NCCI,fsmooth->datalen);
3396 + }
3397 + }
3398 + } else {
3399 + if (i->B3in > 0) i->B3in--;
3400 + ast_mutex_unlock(&i->lockB3in);
3401 + }
3402 +#else
3403 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3404 + ast_log(LOG_ERROR,"error sending DATA_B3_REQ (error=%#x, datalen=%d)\n",error,fsmooth->datalen);
3405 +// ast_log(LOG_NOTICE,"f: timelen %d b = %d MN = %d \n",fsmooth->timelen,b,CMSG.Messagenumber);
3406 + } else {
3407 + if (option_verbose > 5) {
3408 + if (capidebug)
3409 + ast_verbose(VERBOSE_PREFIX_4 "sent DATA_B3_REQ (NCCI=%#x) (%d bytes)\n",i->NCCI,fsmooth->datalen);
3410 + }
3411 + }
3412 +#endif
3413 +
3414 +// ast_frfree(fsmooth);
3415 +
3416 + fsmooth=ast_smoother_read(i->smoother);
3417 + }
3418 + return 0;
3419 +}
3420 +
3421 +static int capi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan) {
3422 + struct ast_capi_pvt *p = newchan->tech_pvt;
3423 + p->owner = newchan;
3424 + return 0;
3425 +}
3426 +
3427 +int capi_indicate(struct ast_channel *c,int condition) {
3428 + return -1;
3429 +}
3430 +
3431 +int capi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc) {
3432 + return -1;
3433 +}
3434 +
3435 +
3436 +struct ast_channel *capi_new(struct ast_capi_pvt *i,int state) {
3437 + struct ast_channel *tmp;
3438 + int fmt;
3439 +
3440 + tmp = ast_channel_alloc(1);
3441 + if (tmp != NULL) {
3442 + snprintf(tmp->name,sizeof(tmp->name),"CAPI/contr%d/%s-%d",i->controller,i->dnid,capi_counter++);
3443 + tmp->type = type;
3444 + tmp->tech = &capi_tech;
3445 + tmp->nativeformats = capi_capability;
3446 + ast_setstate(tmp,state);
3447 + tmp->fds[0] = i->fd;
3448 + i->smoother = ast_smoother_new(AST_CAPI_MAX_B3_BLOCK_SIZE);
3449 + if (i->smoother == NULL) {
3450 + ast_log(LOG_ERROR, "smoother NULL!\n");
3451 + }
3452 + i->fr.frametype = 0;
3453 + i->fr.subclass = 0;
3454 + i->fr.delivery.tv_sec = 0;
3455 + i->fr.delivery.tv_usec = 0;
3456 + i->state = CAPI_STATE_DISCONNECTED;
3457 + i->CLIR = 0;
3458 + i->calledPartyIsISDN = 0; // let's be pessimistic
3459 + i->earlyB3 = -1;
3460 + i->doB3 = AST_CAPI_B3_DONT;
3461 + i->outgoing = 0;
3462 + i->onholdPLCI = 0;
3463 +#ifdef CAPI_SYNC
3464 + i->B3in = 0;
3465 + ast_mutex_init(&i->lockB3in);
3466 +#endif
3467 +#ifdef CAPI_ES
3468 + memset(i->txavg,0,ECHO_TX_COUNT);
3469 +#endif
3470 +
3471 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
3472 + if (i->doDTMF == 1) {
3473 +#endif
3474 + i->vad = ast_dsp_new();
3475 + ast_dsp_set_features(i->vad, DSP_FEATURE_DTMF_DETECT);
3476 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
3477 + }
3478 +#endif
3479 +
3480 + tmp->tech_pvt = i;
3481 + tmp->callgroup = i->callgroup;
3482 + tmp->nativeformats = capi_capability;
3483 + fmt = ast_best_codec(tmp->nativeformats);
3484 +// fmt = capi_capability;
3485 + tmp->readformat = fmt;
3486 + tmp->writeformat = fmt;
3487 + tmp->rawreadformat = fmt;
3488 + tmp->rawwriteformat = fmt;
3489 + strncpy(tmp->context,i->context,sizeof(tmp->context)-1);
3490 + tmp->cid.cid_num = strdup(i->cid);
3491 + tmp->cid.cid_dnid = strdup(i->dnid);
3492 + strncpy(tmp->exten,i->dnid,sizeof(tmp->exten)-1);
3493 + strncpy(tmp->accountcode,i->accountcode,sizeof(tmp->accountcode)-1);
3494 + i->owner = tmp;
3495 + ast_mutex_lock(&usecnt_lock);
3496 + usecnt++;
3497 + ast_mutex_unlock(&usecnt_lock);
3498 + ast_update_use_count();
3499 + if (state != AST_STATE_DOWN) {
3500 + // we are alerting (phones ringing)
3501 + if (state == AST_STATE_RING)
3502 + capi_alert(tmp);
3503 + if (ast_pbx_start(tmp)) {
3504 + ast_log(LOG_ERROR,"Unable to start pbx on channel!\n");
3505 + ast_hangup(tmp);
3506 + tmp = NULL;
3507 + } else {
3508 + if (option_verbose > 2) {
3509 + ast_verbose(VERBOSE_PREFIX_3 "started pbx on channel (callgroup=%d)!\n",tmp->callgroup);
3510 + }
3511 + }
3512 + }
3513 + } else {
3514 + ast_log(LOG_ERROR,"Unable to allocate channel!\n");
3515 + }
3516 + return tmp;
3517 +}
3518 +
3519 +
3520 +struct ast_channel *capi_request(const char *type, int format, void *data, int *cause)
3521 +{
3522 + struct ast_capi_pvt *i;
3523 + struct ast_channel *tmp = NULL;
3524 + char *dest,*interface;
3525 + char buffer[AST_MAX_EXTENSION];
3526 + unsigned int capigroup=0, controller=0;
3527 + int notfound = 1;
3528 +
3529 + if (option_verbose > 1) {
3530 + if (capidebug)
3531 + ast_verbose(VERBOSE_PREFIX_3 "data = %s\n",(char *)data);
3532 + }
3533 + strncpy(buffer,(char *)data,sizeof(buffer)-1);
3534 +
3535 + interface = strtok(buffer, "/");
3536 + dest = strtok(NULL, "/");
3537 +
3538 +
3539 + if (((char *)interface)[0] == 'g') {
3540 + interface++;
3541 + capigroup = atoi(interface);
3542 + if (option_verbose > 1) {
3543 + if (capidebug)
3544 + ast_verbose(VERBOSE_PREFIX_3 "capi request group = %d\n",capigroup);
3545 + }
3546 + } else if (!strncmp(interface,"contr",5)) {
3547 + interface += 5;
3548 + controller = atoi(interface);
3549 + if (option_verbose > 1) {
3550 + if (capidebug)
3551 + ast_verbose(VERBOSE_PREFIX_3 "capi request controller = %d\n",controller);
3552 + }
3553 + } else {
3554 + ast_log(LOG_ERROR,"Syntax error in dialstring. read the docs!\n");
3555 + }
3556 +
3557 + ast_mutex_lock(&iflock);
3558 + i = iflist;
3559 + while (i && notfound) {
3560 + // unused channel
3561 + if (!i->owner) {
3562 + if (controller && (i->controllers & (1 << controller))) {
3563 + // DIAL(CAPI/contrX/...)
3564 + ast_mutex_lock(&contrlock);
3565 + if (capi_controllers[controller]->nfreebchannels > 0) {
3566 + strncpy(i->dnid,dest,sizeof(i->dnid)-1);
3567 + i->controller = controller;
3568 + tmp = capi_new(i, AST_STATE_DOWN);
3569 + i->PLCI = -1;
3570 + i->datahandle = 0;
3571 + i->outgoing = 1; // this is an outgoing line
3572 + i->earlyB3 = -1;
3573 + // capi_detect_dtmf(tmp,1);
3574 + ast_mutex_unlock(&contrlock);
3575 + ast_mutex_unlock(&iflock);
3576 + return tmp;
3577 + } else {
3578 + // keep on running!
3579 + ast_mutex_unlock(&contrlock);
3580 + }
3581 + } else if (capigroup && (i->group & (1 << capigroup))) {
3582 + int c;
3583 + // DIAL(CAPI/gX/...)
3584 + ast_mutex_lock(&contrlock);
3585 + for (c=1;c<=capi_num_controllers;c++) {
3586 + if (i->controllers & (1 << c)) {
3587 + if (capi_controllers[c]->nfreebchannels > 0) {
3588 + strncpy(i->dnid,dest,sizeof(i->dnid)-1);
3589 + i->controller = c;
3590 + tmp = capi_new(i, AST_STATE_DOWN);
3591 + i->PLCI = -1;
3592 + i->datahandle = 0;
3593 + i->outgoing = 1; // this is an outgoing line
3594 + i->earlyB3 = -1;
3595 + // capi_detect_dtmf(tmp,1);
3596 + ast_mutex_unlock(&contrlock);
3597 + ast_mutex_unlock(&iflock);
3598 + return tmp;
3599 + } else {
3600 + // keep on running!
3601 + }
3602 + }
3603 + }
3604 + ast_mutex_unlock(&contrlock);
3605 + }
3606 + }
3607 +// ast_log(LOG_NOTICE,"not contr %d group %d\n",i->controllers, i->group);
3608 + i = i->next;
3609 + }
3610 + ast_mutex_unlock(&iflock);
3611 + ast_log(LOG_NOTICE,"didn't find capi device with controller = %d or group = %d.\n",controller, capigroup);
3612 + return NULL;
3613 +}
3614 +
3615 +
3616 +struct capi_pipe *find_pipe(int PLCI,int MN) {
3617 + struct capi_pipe *p;
3618 + // find a pipe by PLCI or by MessageNumber (in case this is a CONNECT_CONF)
3619 + ast_mutex_lock(&pipelock);
3620 + p = pipelist;
3621 + if ((p == NULL) && (capi_last_plci != PLCI)){
3622 + if (capidebug) {
3623 + ast_log(LOG_NOTICE,"PLCI doesnt match last pipe (PLCI = %#x)\n",PLCI);
3624 + }
3625 + ast_mutex_unlock(&pipelock);
3626 + return NULL;
3627 + }
3628 + while(p != NULL) {
3629 + if ((p->PLCI == PLCI) || ( (p->PLCI == -1) && (p->i->MessageNumber == MN) ) ){
3630 + ast_mutex_unlock(&pipelock);
3631 + return p;
3632 + }
3633 + p = p->next;
3634 + }
3635 + if (capidebug) {
3636 + ast_log(LOG_ERROR,"unable to find a pipe for PLCI = %#x MN = %#x\n",PLCI,MN);
3637 + }
3638 + ast_mutex_unlock(&pipelock);
3639 + return NULL;
3640 +}
3641 +
3642 +int pipe_frame(struct capi_pipe *p,struct ast_frame *f) {
3643 + fd_set wfds;
3644 + int written=0;
3645 + struct timeval tv;
3646 + FD_ZERO(&wfds);
3647 + FD_SET(p->fd,&wfds);
3648 + tv.tv_sec = 0;
3649 + tv.tv_usec = 10;
3650 + if ((f->frametype == AST_FRAME_VOICE) && (p->i->doDTMF == 1) && (p->i->vad != NULL)) {
3651 + f = ast_dsp_process(p->c,p->i->vad,f);
3652 + if (f->frametype == AST_FRAME_NULL) {
3653 + return 0;
3654 + }
3655 + }
3656 + // we dont want the monitor thread to block
3657 + if (select(p->fd + 1,NULL,&wfds,NULL,&tv) == 1) {
3658 + written = write(p->fd,f,sizeof(struct ast_frame));
3659 + if (written < (signed int) sizeof(struct ast_frame)) {
3660 + ast_log(LOG_ERROR,"wrote %d bytes instead of %d\n", written, (int)sizeof(struct ast_frame));
3661 + return -1;
3662 + }
3663 + if (f->frametype == AST_FRAME_VOICE) {
3664 + written = write(p->fd,f->data,f->datalen);
3665 + if (written < f->datalen) {
3666 + ast_log(LOG_ERROR,"wrote %d bytes instead of %d\n",written,f->datalen);
3667 + return -1;
3668 + }
3669 + }
3670 + } else {
3671 + return 0;
3672 + }
3673 + return -1;
3674 +}
3675 +
3676 +static int search_did(struct ast_channel *c)
3677 +{
3678 + // Returns
3679 + // -1 = Failure
3680 + // 0 = Match
3681 + // 1 = possible match
3682 + struct ast_capi_pvt *i = c->tech_pvt;
3683 + char *exten;
3684 +
3685 + if (strlen(i->dnid)<strlen(i->incomingmsn))
3686 + return -1;
3687 +
3688 +// exten = i->dnid + strlen(i->incomingmsn);
3689 + exten = i->dnid;
3690 +
3691 + if (ast_exists_extension(NULL, c->context, exten, 1, NULL)) {
3692 + c->priority = 1;
3693 + strncpy(c->exten, exten, sizeof(c->exten) - 1);
3694 + return 0;
3695 + }
3696 +
3697 + if (ast_canmatch_extension(NULL, c->context, exten, 1, NULL)) {
3698 + return 1;
3699 + }
3700 +
3701 +
3702 + return -1;
3703 +}
3704 +
3705 +int pipe_msg(int PLCI,_cmsg *CMSG) {
3706 + struct capi_pipe *p;
3707 + _cmsg CMSG2;
3708 + MESSAGE_EXCHANGE_ERROR error;
3709 + struct ast_frame fr;
3710 + char b3buf[1024];
3711 + int j;
3712 + int b3len=0;
3713 + char dtmf;
3714 + unsigned dtmflen;
3715 +#ifdef CAPI_ES
3716 + int rxavg = 0;
3717 + int txavg = 0;
3718 +#endif
3719 +
3720 + p = find_pipe(PLCI,CMSG->Messagenumber);
3721 + if (p == NULL) {
3722 + if (IS_DISCONNECT_IND(CMSG)) {
3723 + DISCONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber , 0);
3724 + DISCONNECT_RESP_PLCI(&CMSG2) = PLCI;
3725 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
3726 + ast_log(LOG_NOTICE, "error sending DISCONNECT_RESP PLCI=%#x\n",PLCI);
3727 + } else {
3728 + if (option_verbose > 5) {
3729 + if (capidebug)
3730 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_RESP PLCI=%#x\n",PLCI);
3731 + }
3732 + }
3733 + return 0;
3734 + }
3735 + if (capidebug) {
3736 + ast_log(LOG_NOTICE,"%s",capi_cmsg2str(CMSG));
3737 + }
3738 + return -1;
3739 + }
3740 +
3741 + if (CMSG != NULL) {
3742 + switch (CMSG->Subcommand) {
3743 + case CAPI_IND:
3744 + switch (CMSG->Command) {
3745 + case CAPI_DISCONNECT_B3:
3746 +// ast_log(LOG_NOTICE,"DISCONNECT_B3_IND\n");
3747 +
3748 + DISCONNECT_B3_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
3749 + DISCONNECT_B3_RESP_NCCI(&CMSG2) = DISCONNECT_B3_IND_NCCI(CMSG);
3750 +
3751 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
3752 + ast_log(LOG_NOTICE, "error sending DISCONNECT_B3_RESP NCCI=%#x\n",(int)DISCONNECT_B3_IND_NCCI(CMSG));
3753 + } else {
3754 + if (option_verbose > 5) {
3755 + if (capidebug)
3756 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_B3_RESP NCCI=%#x\n",(int)DISCONNECT_B3_IND_NCCI(CMSG));
3757 + }
3758 + }
3759 + if (p->i->state == CAPI_STATE_BCONNECTED) {
3760 + // passive disconnect
3761 + p->i->state = CAPI_STATE_CONNECTED;
3762 + } else
3763 + if (p->i->state == CAPI_STATE_DISCONNECTING) {
3764 + // active disconnect
3765 + memset(&CMSG2,0,sizeof(_cmsg));
3766 + DISCONNECT_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
3767 + DISCONNECT_REQ_PLCI(&CMSG2) = PLCI;
3768 +
3769 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
3770 + ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",PLCI);
3771 + } else {
3772 + if (option_verbose > 5) {
3773 + if (capidebug)
3774 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_REQ PLCI=%#x\n",PLCI);
3775 + }
3776 + }
3777 + } else
3778 + if (p->i->state == CAPI_STATE_ONHOLD) {
3779 + // no hangup
3780 + }
3781 + ast_mutex_lock(&contrlock);
3782 + if (p->i->controller > 0) {
3783 + capi_controllers[p->i->controller]->nfreebchannels++;
3784 + }
3785 + ast_mutex_unlock(&contrlock);
3786 + break;
3787 + case CAPI_DISCONNECT:
3788 +// ast_log(LOG_NOTICE,"DISCONNECT_IND\n");
3789 + DISCONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber , 0);
3790 + DISCONNECT_RESP_PLCI(&CMSG2) = PLCI;
3791 +/* if (p->i->controller > 0) {
3792 + capi_controllers[p->i->controller]->nfreebchannels++;
3793 + } */
3794 +
3795 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
3796 + ast_log(LOG_NOTICE, "error sending DISCONNECT_RESP PLCI=%#x\n",PLCI);
3797 + } else {
3798 + if (option_verbose > 5) {
3799 + if (capidebug)
3800 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_RESP PLCI=%#x\n",PLCI);
3801 + }
3802 + }
3803 + if (p->c) {
3804 + p->c->hangupcause = DISCONNECT_IND_REASON(CMSG) - 0x3480;
3805 + }
3806 +
3807 + if (PLCI == p->i->onholdPLCI) {
3808 + // the caller onhold hung up (or ECTed away)
3809 + p->i->onholdPLCI = 0;
3810 + remove_pipe(PLCI);
3811 + return 0;
3812 + }
3813 +
3814 + if (p->i->state == CAPI_STATE_DID) {
3815 + if ((p->c) != NULL) {
3816 + ast_hangup(p->c);
3817 + } else {
3818 + ast_log(LOG_WARNING, "unable to hangup channel on DID. Channel is NULL.\n");
3819 + }
3820 + return 0;
3821 + }
3822 +
3823 + p->i->state = CAPI_STATE_DISCONNECTED;
3824 +
3825 + fr.frametype = AST_FRAME_CONTROL;
3826 + if (DISCONNECT_IND_REASON(CMSG) == 0x34a2) {
3827 + fr.subclass = AST_CONTROL_BUSY;
3828 + } else {
3829 + fr.frametype = AST_FRAME_NULL;
3830 + }
3831 + fr.datalen = 0;
3832 + if (pipe_frame(p,(struct ast_frame *)&fr) == -1) {
3833 + // printf("STATE = %#x\n",p->i->state);
3834 + // in this case * did not read our hangup control frame
3835 + // so we must hangup the channel!
3836 + if ( (p->i->state != CAPI_STATE_DISCONNECTED) && (ast_check_hangup(p->c) == 0)) {
3837 + if (option_verbose > 1) {
3838 + ast_verbose(VERBOSE_PREFIX_3 "soft hangup by capi\n");
3839 + }
3840 + ast_softhangup(p->c,AST_SOFTHANGUP_DEV);
3841 + } else {
3842 + // dont ever hangup while hanging up!
3843 +// ast_log(LOG_NOTICE,"no soft hangup by capi\n");
3844 + }
3845 + return -1;
3846 + } else {
3847 + return 0;
3848 + }
3849 +
3850 +/* fr.frametype = AST_FRAME_NULL;
3851 + fr.datalen = 0;
3852 + pipe_frame(p,(struct ast_frame *)&fr); */
3853 + break;
3854 + case CAPI_DATA_B3:
3855 +
3856 + memcpy(&b3buf[AST_FRIENDLY_OFFSET],(char *)DATA_B3_IND_DATA(CMSG),DATA_B3_IND_DATALENGTH(CMSG));
3857 + b3len = DATA_B3_IND_DATALENGTH(CMSG);
3858 +
3859 + // send a DATA_B3_RESP very quickly to free the buffer in capi
3860 + DATA_B3_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber,0);
3861 + DATA_B3_RESP_NCCI(&CMSG2) = DATA_B3_IND_NCCI(CMSG);
3862 + DATA_B3_RESP_DATAHANDLE(&CMSG2) = DATA_B3_IND_DATAHANDLE(CMSG);
3863 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
3864 + ast_log(LOG_ERROR,"error sending DATA_B3_RESP (error=%#x)\n",error);
3865 + } else {
3866 + if (option_verbose > 6) {
3867 + if (capidebug)
3868 + ast_verbose(VERBOSE_PREFIX_4 "sent DATA_B3_RESP (NCCI=%#x)\n",(int)DATA_B3_IND_NCCI(CMSG));
3869 + }
3870 + }
3871 +#ifdef CAPI_SYNC
3872 + ast_mutex_lock(&p->i->lockB3in);
3873 + p->i->B3in++;
3874 + if (p->i->B3in > AST_CAPI_MAX_B3_BLOCKS) p->i->B3in = AST_CAPI_MAX_B3_BLOCKS;
3875 + ast_mutex_unlock(&p->i->lockB3in);
3876 +#endif
3877 +#ifdef CAPI_ES
3878 + if ((p->i->doES == 1)) {
3879 + for (j=0;j<b3len;j++) {
3880 + b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]];
3881 + rxavg += abs(capiXLAW2INT( reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]));
3882 + }
3883 + rxavg = rxavg/j;
3884 + for(j=0;j<ECHO_EFFECTIVE_TX_COUNT;j++) {
3885 + txavg += p->i->txavg[j];
3886 + }
3887 + txavg = txavg/j;
3888 +
3889 + if( (txavg/ECHO_TXRX_RATIO) > rxavg) {
3890 +#ifdef CAPI_ULAW
3891 + memset(&b3buf[AST_FRIENDLY_OFFSET],255,b3len);
3892 +#else
3893 + memset(&b3buf[AST_FRIENDLY_OFFSET],84,b3len);
3894 +#endif
3895 + if (capidebug) {
3896 + ast_log(LOG_NOTICE,"SUPPRESSING ECHOrx=%d, tx=%d\n",rxavg,txavg);
3897 + }
3898 + }
3899 + } else {
3900 +#ifdef CAPI_GAIN
3901 + for (j=0;j<b3len;j++) {
3902 + b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[p->i->g.rxgains[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]];
3903 + }
3904 +#else
3905 + for (j=0;j<b3len;j++) {
3906 + b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]];
3907 + }
3908 +#endif
3909 + }
3910 +#else
3911 +
3912 +#ifdef CAPI_GAIN
3913 + for (j=0;j<b3len;j++) {
3914 + b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[p->i->g.rxgains[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]];
3915 + }
3916 +#else
3917 + for (j=0;j<b3len;j++) {
3918 + b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]];
3919 + }
3920 +#endif
3921 +
3922 +#endif
3923 + // just being paranoid ...
3924 + /* if (p->c->_state != AST_STATE_UP) {
3925 + ast_setstate(p->c,AST_STATE_UP);
3926 + } */
3927 +
3928 + fr.frametype = AST_FRAME_VOICE;
3929 + fr.subclass = capi_capability;
3930 + fr.data = (char *)&b3buf[AST_FRIENDLY_OFFSET];
3931 + fr.datalen = b3len;
3932 + fr.samples = b3len;
3933 + fr.offset = AST_FRIENDLY_OFFSET;
3934 + fr.mallocd = 0;
3935 + fr.delivery.tv_sec = 0;
3936 + fr.delivery.tv_usec = 0;
3937 + fr.src = NULL;
3938 + // 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);
3939 + return pipe_frame(p,(struct ast_frame *)&fr);
3940 + break;
3941 + case CAPI_FACILITY:
3942 + if (FACILITY_IND_FACILITYSELECTOR(CMSG) == 0x0001) {
3943 + // DTMF received
3944 + if (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[0] != (0xff)) {
3945 + dtmflen = FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[0];
3946 + FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG) += 1;
3947 + } else {
3948 + dtmflen = ((__u16 *) (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG) + 1))[0];
3949 + FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG) += 3;
3950 + }
3951 + if (dtmflen == 1) {
3952 + dtmf = (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG))[0];
3953 + fr.frametype = AST_FRAME_DTMF;
3954 + fr.subclass = dtmf;
3955 + if (option_verbose > 1) {
3956 + if (capidebug)
3957 + ast_verbose(VERBOSE_PREFIX_3 "c_dtmf = %c\n",dtmf);
3958 + }
3959 + pipe_frame(p,(struct ast_frame *)&fr);
3960 + }
3961 + }
3962 + if (FACILITY_IND_FACILITYSELECTOR(CMSG) == 0x0003) {
3963 + // sservices
3964 + /* ast_log(LOG_NOTICE,"FACILITY_IND PLCI = %#x\n",(int)FACILITY_IND_PLCI(CMSG));
3965 + ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[0]);
3966 + ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[1]);
3967 + ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[2]);
3968 + ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[3]);
3969 + ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4]);
3970 + ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5]); */
3971 + // RETRIEVE
3972 + if ( (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[1] == 0x3) && (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[3] == 0x2)) {
3973 + p->i->state = CAPI_STATE_CONNECTED;
3974 + p->i->PLCI = p->i->onholdPLCI;
3975 + p->i->onholdPLCI = 0;
3976 + }
3977 + if ( (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[1] == 0x2) && (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[3] == 0x2)) {
3978 + if ((FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5] != 0) && (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4] != 0)) {
3979 + // reason != 0x0000 == problem
3980 + p->i->onholdPLCI = 0;
3981 + p->i->state = CAPI_STATE_ONHOLD;
3982 + 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]);
3983 + } else {
3984 + // reason = 0x0000 == call on hold
3985 + p->i->state = CAPI_STATE_ONHOLD;
3986 + if (capidebug)
3987 + ast_log(LOG_NOTICE, "PLCI=%#x put onhold\n",(int)FACILITY_IND_PLCI(CMSG));
3988 + }
3989 + }
3990 + }
3991 +
3992 + error = FACILITY_RESP(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber,FACILITY_IND_PLCI(CMSG),FACILITY_IND_FACILITYSELECTOR(CMSG),FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG));
3993 +
3994 + if (error != 0) {
3995 + ast_log(LOG_ERROR,"error sending FACILITY_RESP (error=%#x)\n",error);
3996 + } else {
3997 + if (option_verbose > 5) {
3998 + if (capidebug)
3999 + ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_RESP (PLCI=%#x)\n",(int)FACILITY_IND_PLCI(CMSG));
4000 + }
4001 + }
4002 + break;
4003 + case CAPI_INFO:
4004 + // ast_log(LOG_ERROR,"INFO_IND PLCI=%#x INFO# = %#x\n",PLCI,INFO_IND_INFONUMBER(CMSG));
4005 +
4006 + memset(&CMSG2,0,sizeof(_cmsg));
4007 + error = INFO_RESP(&CMSG2,ast_capi_ApplID,CMSG->Messagenumber,PLCI);
4008 + if (error != 0) {
4009 + ast_log(LOG_ERROR,"error sending INFO_RESP (error=%#x)\n",error);
4010 + return -1;
4011 + } else {
4012 + if (option_verbose > 5) {
4013 + if (capidebug)
4014 + ast_verbose(VERBOSE_PREFIX_4 "sent INFO_RESP (PLCI=%#x)\n",PLCI);
4015 + }
4016 + }
4017 +/* if ((INFO_IND_INFONUMBER(CMSG) >> 8) == 0x00) {
4018 + ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[0]);
4019 + ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[1]);
4020 + ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[2]);
4021 + ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[3]);
4022 + } */
4023 +#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
4024 + if ((INFO_IND_INFONUMBER(CMSG) == 0x001e) && (p->i->doB3 != AST_CAPI_B3_DONT) && (p->i->earlyB3 == -1) && (p->i->state != CAPI_STATE_BCONNECTED)){
4025 + // ETSI 300 102-1 Progress Indicator
4026 + // we do early B3 Connect
4027 + if(INFO_IND_INFOELEMENT(CMSG)[0] >= 2) {
4028 + if(INFO_IND_INFOELEMENT(CMSG)[2] & 0x2) {
4029 + p->i->calledPartyIsISDN = 0;
4030 + // ast_log(LOG_NOTICE,"A N A L O G \n");
4031 + } else {
4032 + p->i->calledPartyIsISDN = 1;
4033 + // ast_log(LOG_NOTICE,"I S D N\n");
4034 + }
4035 + if(INFO_IND_INFOELEMENT(CMSG)[2] & 0x88) {
4036 + // in-band info available
4037 + p->i->earlyB3 = 1;
4038 + memset(&CMSG2,0,sizeof(_cmsg));
4039 + CONNECT_B3_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++,0);
4040 + CONNECT_B3_REQ_PLCI(&CMSG2) = PLCI;
4041 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4042 + ast_log(LOG_ERROR,"error sending early CONNECT_B3_REQ (error=%#x)\n",error);
4043 + return -1;
4044 + } else {
4045 + if (option_verbose > 1) {
4046 + if (capidebug)
4047 + ast_verbose(VERBOSE_PREFIX_4 "sent early CONNECT_B3_REQ (PLCI=%#x)\n",PLCI);
4048 + }
4049 + }
4050 + }
4051 + }
4052 + }
4053 + // DISCONNECT
4054 + if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (PLCI == p->i->onholdPLCI)) {
4055 + // the caller onhold hung up (or ECTed away)
4056 + // send a disconnect_req , we cannot hangup the channel here!!!
4057 + memset(&CMSG2,0,sizeof(_cmsg));
4058 + DISCONNECT_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
4059 + DISCONNECT_REQ_PLCI(&CMSG2) = p->i->onholdPLCI;
4060 +
4061 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4062 + ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",PLCI);
4063 + } else {
4064 + if (option_verbose > 1) {
4065 + if (capidebug)
4066 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_REQ for onholdPLCI=%#x\n",PLCI);
4067 + }
4068 + }
4069 + return 0;
4070 + }
4071 +
4072 + // case 1: B3 on success or no B3 at all
4073 + if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->doB3 != AST_CAPI_B3_ALWAYS) && (p->i->outgoing == 1)) {
4074 + p->i->earlyB3 = 0; // !!!
4075 + fr.frametype = AST_FRAME_NULL;
4076 + fr.datalen = 0;
4077 + return pipe_frame(p,(struct ast_frame *)&fr);
4078 + }
4079 + // case 2: we are doing B3, and receive the 0x8045 after a successful call
4080 + if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->doB3 != AST_CAPI_B3_DONT) && (p->i->earlyB3 == 0) && (p->i->outgoing == 1)) {
4081 + fr.frametype = AST_FRAME_NULL;
4082 + fr.datalen = 0;
4083 + return pipe_frame(p,(struct ast_frame *)&fr);
4084 + }
4085 + // case 3: this channel is an incoming channel! the user hung up!
4086 + // it is much better to hangup now instead of waiting for a timeout and
4087 + // network caused DISCONNECT_IND!
4088 + if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->outgoing == 0)) {
4089 + // ast_log(LOG_NOTICE,"case 3\n");
4090 + fr.frametype = AST_FRAME_NULL;
4091 + fr.datalen = 0;
4092 + return pipe_frame(p,(struct ast_frame *)&fr);
4093 + }
4094 + // case 4 (a.k.a. the italian case): B3 always. call is unsuccessful
4095 + if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->doB3 == AST_CAPI_B3_ALWAYS) && (p->i->earlyB3 == -1) && (p->i->outgoing == 1)) {
4096 + // wait for the 0x001e (PROGRESS), play audio and wait for a timeout from the network
4097 + return 0;
4098 + }
4099 +#endif
4100 + // Handle DID digits
4101 + if ((INFO_IND_INFONUMBER(CMSG) == 0x0070) && p->i->isdnmode && (p->c != NULL)) {
4102 + int search = -1;
4103 + char name[AST_CHANNEL_NAME] = "";
4104 + char *did;
4105 +
4106 + did = capi_number((char *)INFO_IND_INFOELEMENT(CMSG),1);
4107 + if (strcasecmp(p->i->dnid, did)) {
4108 + strncat(p->i->dnid, did, sizeof(p->i->dnid)-1);
4109 + }
4110 +
4111 + snprintf(name,sizeof(name),"CAPI/contr%d/%s/-%d",p->i->controller,p->i->dnid,capi_counter++);
4112 + ast_change_name(p->c, name);
4113 +
4114 + search = search_did(p->c);
4115 + if (search != -1) {
4116 + if (!search) {
4117 + ast_setstate(p->c, AST_STATE_RING);
4118 + // we are alerting (phones ringing)
4119 + capi_alert(p->c); // Do this here after pbx_start the Channel can be destroyed
4120 + if (ast_pbx_start(p->c)) {
4121 + ast_log(LOG_ERROR,"Unable to start pbx on channel!\n");
4122 + ast_hangup(p->c);
4123 + } else {
4124 + if (option_verbose > 2) {
4125 + if (capidebug)
4126 + ast_verbose(VERBOSE_PREFIX_3 "started pbx on channel!\n");
4127 + }
4128 + }
4129 + }
4130 + } else {
4131 + ast_log(LOG_ERROR,"did not find device for msn = %s\n",p->i->dnid);
4132 + CONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4133 + CONNECT_RESP_PLCI(&CMSG2) = PLCI;
4134 + CONNECT_RESP_REJECT(&CMSG2) = 1; // ignore
4135 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4136 + ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4137 + } else {
4138 + if (option_verbose > 5) {
4139 + if (capidebug)
4140 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4141 + }
4142 + }
4143 +
4144 + return 0;
4145 + }
4146 + }
4147 + if (INFO_IND_INFONUMBER(CMSG) == 0x8001) {
4148 + fr.frametype = AST_FRAME_CONTROL;
4149 + fr.subclass = AST_CONTROL_RINGING;
4150 + return pipe_frame(p,(struct ast_frame *)&fr);
4151 + }
4152 + if (INFO_IND_INFONUMBER(CMSG) == 0x800d) {
4153 + fr.frametype = AST_FRAME_CONTROL;
4154 + fr.subclass = AST_CONTROL_PROGRESS;
4155 + return pipe_frame(p,(struct ast_frame *)&fr);
4156 + }
4157 + if (INFO_IND_INFONUMBER(CMSG) == 0x74) {
4158 + strncpy(p->i->owner->exten,capi_number((char *)INFO_IND_INFOELEMENT(CMSG),3),sizeof(p->i->owner->exten)-1);
4159 + ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(CMSG));
4160 + }
4161 + if (INFO_IND_INFONUMBER(CMSG) == 0x28) {
4162 + // ast_sendtext(p->i->owner,capi_number(INFO_IND_INFOELEMENT(CMSG),0));
4163 + // struct ast_frame ft = { AST_FRAME_TEXT, capi_number(INFO_IND_INFOELEMENT(CMSG),0), };
4164 + // ast_queue_frame(p->i->owner, &ft);
4165 + // ast_log(LOG_NOTICE,"%s\n",capi_number(INFO_IND_INFOELEMENT(CMSG),0));
4166 + }
4167 + break;
4168 + case CAPI_CONNECT_ACTIVE:
4169 +// ast_log(LOG_NOTICE,"CONNECT_ACTIVE_IND PLCI=%#x\n",(int)CONNECT_ACTIVE_IND_PLCI(CMSG));
4170 + CONNECT_ACTIVE_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber,0);
4171 + CONNECT_ACTIVE_RESP_PLCI(&CMSG2) = PLCI;
4172 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4173 + ast_log(LOG_ERROR,"error sending CONNECT_ACTIVE_RESP (error=%#x)\n",error);
4174 + return -1;
4175 + } else {
4176 + if (option_verbose > 5) {
4177 + if (capidebug)
4178 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_ACTIVE_RESP (PLCI=%#x)\n",PLCI);
4179 + }
4180 + }
4181 + // normal processing
4182 + if (p->i->earlyB3 != 1) {
4183 + p->i->state = CAPI_STATE_CONNECTED;
4184 +
4185 + // send a CONNECT_B3_REQ
4186 + if (p->i->outgoing == 1) {
4187 + // outgoing call
4188 + memset(&CMSG2,0,sizeof(_cmsg));
4189 + CONNECT_B3_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++,0);
4190 + CONNECT_B3_REQ_PLCI(&CMSG2) = PLCI;
4191 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4192 + ast_log(LOG_ERROR,"error sending CONNECT_B3_REQ (error=%#x)\n",error);
4193 + return -1;
4194 + } else {
4195 + if (option_verbose > 1) {
4196 + if (capidebug)
4197 + ast_verbose(VERBOSE_PREFIX_3 "sent CONNECT_B3_REQ (PLCI=%#x)\n",PLCI);
4198 + }
4199 + }
4200 + } else {
4201 + // incoming call
4202 + // RESP already sent ... wait for CONNECT_B3_IND
4203 +// ast_log(LOG_NOTICE,"waiting for CONNECT_B3_IND\n");
4204 + }
4205 + } else {
4206 + // special treatment for early B3 connects
4207 + p->i->state = CAPI_STATE_BCONNECTED;
4208 + if (p->c->_state != AST_STATE_UP) {
4209 + ast_setstate(p->c,AST_STATE_UP);
4210 + }
4211 + p->i->earlyB3 = 0; // not early anymore
4212 + fr.frametype = AST_FRAME_CONTROL;
4213 + fr.subclass = AST_CONTROL_ANSWER;
4214 + fr.datalen = 0;
4215 + return pipe_frame(p,(struct ast_frame *)&fr);
4216 +
4217 + }
4218 + break;
4219 + case CAPI_CONNECT_B3:
4220 + // then send a CONNECT_B3_RESP
4221 + memset(&CMSG2,0,sizeof(_cmsg));
4222 + CONNECT_B3_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4223 + CONNECT_B3_RESP_NCCI(&CMSG2) = CONNECT_B3_IND_NCCI(CMSG);
4224 + p->NCCI = CONNECT_B3_IND_NCCI(CMSG);
4225 + p->i->NCCI = p->NCCI;
4226 + CONNECT_B3_RESP_REJECT(&CMSG2) = 0;
4227 +
4228 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4229 + ast_log(LOG_ERROR,"error sending CONNECT_B3_RESP (error=%#x)\n",error);
4230 + return -1;
4231 + } else {
4232 + if (option_verbose > 5) {
4233 + if (capidebug)
4234 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_B3_RESP (NCCI=%#x)\n",p->i->NCCI);
4235 + }
4236 + }
4237 + /* if (p->i->controller > 0) {
4238 + capi_controllers[p->i->controller]->nfreebchannels--;
4239 + } */
4240 + break;
4241 + case CAPI_CONNECT_B3_ACTIVE:
4242 +// ast_log(LOG_NOTICE,"CONNECT_B3_ACTIVE_IND NCCI=%#x\n",p->i->NCCI);
4243 + // then send a CONNECT_B3__ACTIVERESP
4244 +
4245 + CONNECT_B3_ACTIVE_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4246 + CONNECT_B3_ACTIVE_RESP_NCCI(&CMSG2) = p->i->NCCI;
4247 +
4248 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4249 + ast_log(LOG_ERROR,"error sending CONNECT_B3_ACTIVE_RESP (error=%#x)\n",error);
4250 + return -1;
4251 + } else {
4252 + if (option_verbose > 5) {
4253 + if (capidebug)
4254 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_B3_ACTIVE_RESP (NCCI=%#x)\n",p->i->NCCI);
4255 + }
4256 + }
4257 +
4258 + ast_mutex_lock(&contrlock);
4259 + if (p->i->controller > 0) {
4260 + capi_controllers[p->i->controller]->nfreebchannels--;
4261 + }
4262 + ast_mutex_unlock(&contrlock);
4263 +
4264 + p->i->state = CAPI_STATE_BCONNECTED;
4265 + capi_echo_canceller(p->c,EC_FUNCTION_ENABLE);
4266 + capi_detect_dtmf(p->c,1);
4267 +
4268 + if (p->i->earlyB3 != 1) {
4269 + ast_setstate(p->c,AST_STATE_UP);
4270 + fr.frametype = AST_FRAME_CONTROL;
4271 + fr.subclass = AST_CONTROL_ANSWER;
4272 + fr.datalen = 0;
4273 + return pipe_frame(p,(struct ast_frame *)&fr);
4274 + }
4275 + return 0;
4276 + break;
4277 + }
4278 + break;
4279 +
4280 + case CAPI_CONF:
4281 + switch (CMSG->Command) {
4282 + case CAPI_FACILITY:
4283 + if (FACILITY_CONF_FACILITYSELECTOR(CMSG) == 0x3) {
4284 + if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[1] == 0x2) && (FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[2] == 0x0)) {
4285 + if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[4] == 0x0) && (FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[5] == 0x0)) {
4286 + } else {
4287 + p->i->state = CAPI_STATE_BCONNECTED;
4288 + if (capidebug)
4289 + ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(CMSG));
4290 + }
4291 + }
4292 + }
4293 + break;
4294 + case CAPI_DATA_B3:
4295 +// ast_log(LOG_NOTICE,"DATA_B3_CONF (NCCI %#x) for DATAHANDLE %#x\n",DATA_B3_CONF_NCCI(CMSG),DATA_B3_CONF_DATAHANDLE(CMSG));
4296 + break;
4297 + case CAPI_ALERT:
4298 +// ast_log(LOG_NOTICE,"ALERT_CONF (PLCI=%#x)\n",(int)ALERT_CONF_PLCI(CMSG));
4299 + p->i->state = CAPI_STATE_ALERTING;
4300 + if (p->c->_state == AST_STATE_RING) {
4301 + p->c->rings = 1;
4302 + }
4303 + break;
4304 + case CAPI_CONNECT:
4305 + if (option_verbose > 1) {
4306 + if (capidebug)
4307 + ast_verbose(VERBOSE_PREFIX_2 "received CONNECT_CONF PLCI = %#x INFO = %#x\n",(int)CONNECT_CONF_PLCI(CMSG),CONNECT_CONF_INFO(CMSG));
4308 + }
4309 + if (CONNECT_CONF_INFO(CMSG) == 0) {
4310 + p->i->PLCI = CONNECT_CONF_PLCI(CMSG);
4311 + p->PLCI = p->i->PLCI;
4312 + ast_setstate(p->c,AST_STATE_DIALING);
4313 + } else {
4314 + // here, something has to be done -->
4315 + fr.frametype = AST_FRAME_CONTROL;
4316 + fr.subclass = AST_CONTROL_BUSY;
4317 + fr.datalen = 0;
4318 + return pipe_frame(p,(struct ast_frame *)&fr);
4319 + }
4320 + break;
4321 + case CAPI_CONNECT_B3:
4322 +// ast_log(LOG_NOTICE,"received CONNECT_B3_CONF NCCI = %#x INFO = %#x\n",(int)CONNECT_B3_CONF_NCCI(CMSG),CONNECT_B3_CONF_INFO(CMSG));
4323 + if (CONNECT_B3_CONF_INFO(CMSG) == 0) {
4324 + p->i->NCCI = CONNECT_B3_CONF_NCCI(CMSG);
4325 + } else {
4326 + p->i->earlyB3 = -1;
4327 + p->i->doB3 = AST_CAPI_B3_DONT;
4328 + }
4329 + break;
4330 + }
4331 + break;
4332 + }
4333 + }
4334 +// ast_log(LOG_NOTICE,"returning\n");
4335 + return 0;
4336 +}
4337 +
4338 +static void capi_handle_msg(_cmsg *CMSG) {
4339 + struct ast_capi_pvt *i;
4340 + char *DNID;
4341 + char *CID;
4342 + char *msn;
4343 + _cmsg CMSG2;
4344 + MESSAGE_EXCHANGE_ERROR error;
4345 + int PLCI=0,NCCI;
4346 + int NPLAN=0;
4347 + int fds[2];
4348 + int controller=0;
4349 + char buffer[AST_MAX_EXTENSION];
4350 + struct capi_pipe *p;
4351 + char *magicmsn = "*\0";
4352 + char *emptyid = "\0";
4353 + char *emptydnid = "s\0";
4354 + long flags;
4355 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
4356 + int deflect=0;
4357 +#endif
4358 +
4359 + switch (CMSG->Subcommand) {
4360 + // indication msgs
4361 + case CAPI_IND:
4362 +
4363 + switch (CMSG->Command) {
4364 + case CAPI_CONNECT: // only connect_ind are global (not channel specific)
4365 + if (capidebug)
4366 + ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(CMSG));
4367 + DNID = capi_number((char *)CONNECT_IND_CALLEDPARTYNUMBER(CMSG),1);
4368 + if ((DNID && *DNID == 0) || !DNID) {
4369 + DNID = emptydnid;
4370 + }
4371 + NPLAN = (CONNECT_IND_CALLINGPARTYNUMBER(CMSG)[1] & 0x70);
4372 + CID = capi_number((char *)CONNECT_IND_CALLINGPARTYNUMBER(CMSG),2);
4373 + PLCI = CONNECT_IND_PLCI(CMSG);
4374 + controller = PLCI & 0xff;
4375 + if (option_verbose > 1) {
4376 + if (capidebug)
4377 + 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);
4378 + }
4379 + if(CONNECT_IND_BCHANNELINFORMATION(CMSG))
4380 + if ((CONNECT_IND_BCHANNELINFORMATION(CMSG)[1] == 0x02) && (!capi_controllers[controller]->isdnmode)) {
4381 + // this is a call waiting CONNECT_IND with BChannelinformation[1] == 0x02
4382 + // meaning "no B or D channel for this call", since we can't do anything with call waiting now
4383 + // just reject it with "user busy"
4384 + // however...if we are a p2p BRI then the telco switch will allow us to choose the b channel
4385 + // so it will look like a callwaiting connect_ind to us
4386 +
4387 + ast_log(LOG_ERROR,"received a call waiting CONNECT_IND\n");
4388 +#ifndef CAPI_DEFLECT_ON_CIRCUITBUSY
4389 + CONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4390 + CONNECT_RESP_PLCI(&CMSG2) = CONNECT_IND_PLCI(CMSG);
4391 + CONNECT_RESP_REJECT(&CMSG2) = 3; // user is busy
4392 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4393 + ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4394 + } else {
4395 + if (option_verbose > 5) {
4396 + if (capidebug)
4397 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4398 + }
4399 + }
4400 + // no need to pipe this
4401 + PLCI = 0;
4402 + break;
4403 +#else
4404 + deflect = 1;
4405 +#endif
4406 + }
4407 + // well...somebody is calling us. let's set up a channel
4408 + ast_mutex_lock(&iflock);
4409 + i = iflist;
4410 + while(i) {
4411 + //XXX test this!
4412 + // has no owner
4413 + if ((!i->owner) && (i->incomingmsn != NULL)){
4414 + strncpy(buffer,i->incomingmsn,sizeof(buffer)-1);
4415 + msn = strtok(buffer,",");
4416 + while (msn != NULL) {
4417 +// ast_log(LOG_NOTICE,"msn=%s\n",msn);
4418 + if (DNID && ((!strcasecmp(msn,DNID)) ||
4419 + (i->isdnmode && (strlen(msn)<strlen(DNID)) && !strncasecmp(msn, DNID, strlen(msn))) || (!strncasecmp(msn,magicmsn,strlen(msn)))) &&
4420 + (i->controllers & (1 << controller))) {
4421 + if (CID != NULL) {
4422 + if(NPLAN == CAPI_ETSI_NPLAN_NATIONAL)
4423 + snprintf(i->cid, (sizeof(i->cid)-1), "%s%s%s", i->prefix, capi_national_prefix, CID);
4424 + else if(NPLAN == CAPI_ETSI_NPLAN_INTERNAT)
4425 + snprintf(i->cid, (sizeof(i->cid)-1), "%s%s%s", i->prefix, capi_international_prefix, CID);
4426 + else
4427 + snprintf(i->cid, (sizeof(i->cid)-1), "%s%s", i->prefix, CID);
4428 + } else
4429 + strncpy(i->cid,emptyid,sizeof(i->cid)-1);
4430 +
4431 + if (DNID != NULL)
4432 + strncpy(i->dnid,DNID,sizeof(i->dnid)-1);
4433 + else
4434 + strncpy(i->dnid,emptydnid,sizeof(i->dnid)-1);
4435 +
4436 + i->controller=controller;
4437 + i->PLCI = PLCI;
4438 + i->MessageNumber = CMSG->Messagenumber;
4439 + if (pipe(fds) == 0) {
4440 + if (option_verbose > 4) {
4441 + ast_verbose(VERBOSE_PREFIX_3 "creating pipe for PLCI=%#x msn = %s\n",PLCI,msn);
4442 + }
4443 + i->fd = fds[0];
4444 + flags = fcntl(i->fd,F_GETFL);
4445 + fcntl(i->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
4446 +// ast_log(LOG_NOTICE,"i->fd = %d\n",i->fd);
4447 + p = malloc(sizeof(struct capi_pipe));
4448 + memset(p, 0, sizeof(struct capi_pipe));
4449 + p->fd = fds[1];
4450 + flags = fcntl(i->fd,F_GETFL);
4451 + fcntl(p->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
4452 +// ast_log(LOG_NOTICE,"p->fd = %d\n",p->fd);
4453 + p->PLCI = PLCI;
4454 + p->i = i;
4455 + ast_mutex_init(&(p->lock));
4456 + i->mypipe = p;
4457 + if (i->isdnmode) {
4458 + p->c = capi_new(i,AST_STATE_DOWN);
4459 + i->state = CAPI_STATE_DID;
4460 + } else {
4461 + p->c = capi_new(i,AST_STATE_RING);
4462 + }
4463 + p->next = pipelist;
4464 + pipelist = p;
4465 + // hmmm....
4466 + ast_mutex_unlock(&iflock);
4467 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
4468 + if ((deflect == 1) && (i->deflect2)) {
4469 + capi_deflect(p->c,i->deflect2);
4470 + }
4471 +#endif
4472 + return;
4473 + } else {
4474 + ast_log(LOG_ERROR,"creating pipe for PLCI=%#x failed\n",PLCI);
4475 + }
4476 + break;
4477 + } // if strcasecmp
4478 + msn = strtok(NULL,",");
4479 + } // while strtok
4480 + } // if
4481 + i = i->next;
4482 + } // while interface list
4483 + ast_mutex_unlock(&iflock); // obviously we are not called...so tell capi to ignore this call
4484 + if (capidebug) {
4485 + ast_log(LOG_ERROR,"did not find device for msn = %s\n",DNID);
4486 + }
4487 + CONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4488 + CONNECT_RESP_PLCI(&CMSG2) = CONNECT_IND_PLCI(CMSG);
4489 + CONNECT_RESP_REJECT(&CMSG2) = 1; // ignore
4490 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4491 + ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4492 + } else {
4493 + if (option_verbose > 5) {
4494 + if (capidebug)
4495 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4496 + }
4497 + }
4498 + ast_mutex_lock(&pipelock);
4499 + if (pipelist == NULL) {
4500 + capi_last_plci = PLCI;
4501 + }
4502 + ast_mutex_unlock(&pipelock);
4503 + // no need to pipe this
4504 + PLCI = 0;
4505 +// ast_mutex_unlock(&iflock);
4506 +// return;
4507 + break;
4508 + case CAPI_FACILITY:
4509 + PLCI = FACILITY_IND_PLCI(CMSG) & 0xffff; // this is for you eicon
4510 + if (option_verbose > 3) {
4511 + if (capidebug)
4512 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4513 + }
4514 +// ast_log(LOG_ERROR,"FACILITY_IND PLCI=%#x\n",PLCI);
4515 + break;
4516 + case CAPI_INFO:
4517 + PLCI = INFO_IND_PLCI(CMSG);
4518 + if (option_verbose > 3) {
4519 + if (capidebug)
4520 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4521 + }
4522 +// ast_log(LOG_ERROR,"INFO_IND PLCI=%#x INFO# = %#x\n",PLCI,INFO_IND_INFONUMBER(CMSG));
4523 + break;
4524 + case CAPI_CONNECT_ACTIVE:
4525 + PLCI = CONNECT_ACTIVE_IND_PLCI(CMSG);
4526 + if (option_verbose > 3) {
4527 + if (capidebug)
4528 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4529 + }
4530 +// ast_log(LOG_ERROR,"CONNECT_ACTIVE_IND PLCI=%#x\n",PLCI);
4531 + break;
4532 + case CAPI_CONNECT_B3:
4533 + NCCI = CONNECT_B3_IND_NCCI(CMSG);
4534 + PLCI = (NCCI << 16) >> 16;
4535 + if (option_verbose > 3) {
4536 + if (capidebug)
4537 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4538 + }
4539 +// ast_log(LOG_ERROR,"CONNECT_B3_IND NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
4540 + break;
4541 + case CAPI_CONNECT_B3_ACTIVE:
4542 + NCCI = CONNECT_B3_IND_NCCI(CMSG);
4543 + PLCI = (NCCI << 16) >> 16;
4544 + if (option_verbose > 3) {
4545 + if (capidebug)
4546 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4547 + }
4548 +// ast_log(LOG_ERROR,"CONNECT_B3_ACTIVE_IND NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
4549 + break;
4550 + case CAPI_DATA_B3:
4551 + NCCI = DATA_B3_IND_NCCI(CMSG);
4552 + PLCI = (NCCI << 16) >> 16;
4553 +// ast_log(LOG_ERROR,"DATA_B3_IND NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
4554 + break;
4555 + case CAPI_DISCONNECT_B3:
4556 + NCCI = DISCONNECT_B3_IND_NCCI(CMSG);
4557 + PLCI = (NCCI << 16) >> 16;
4558 + if (option_verbose > 1) {
4559 + if (capidebug)
4560 + ast_verbose(VERBOSE_PREFIX_2 "DISCONNECT_B3_IND NCCI=%#x\n",NCCI);
4561 + }
4562 + break;
4563 + case CAPI_DISCONNECT:
4564 + PLCI = DISCONNECT_IND_PLCI(CMSG);
4565 + if (option_verbose > 1) {
4566 + if (capidebug)
4567 + ast_verbose(VERBOSE_PREFIX_2 "DISCONNECT_IND PLCI=%#x REASON=%#x\n",PLCI,DISCONNECT_IND_REASON(CMSG));
4568 + }
4569 + break;
4570 + default:
4571 + ast_log(LOG_ERROR,"Command.Subcommand = %#x.%#x\n",CMSG->Command,CMSG->Subcommand);
4572 + }
4573 + break;
4574 + // confirmation msgs
4575 + case CAPI_CONF:
4576 + switch (CMSG->Command) {
4577 + case CAPI_FACILITY:
4578 + NCCI = FACILITY_CONF_NCCI(CMSG);
4579 + PLCI = (NCCI << 16) >> 16;
4580 + if (option_verbose > 2) {
4581 + if (FACILITY_CONF_FACILITYSELECTOR(CMSG) == 6) {
4582 + if (FACILITY_CONF_INFO(CMSG))
4583 + ast_verbose (VERBOSE_PREFIX_3 "Error setting up echo canceller (PLCI=%#x, Info=%#04x)\n", PLCI, FACILITY_CONF_INFO(CMSG));
4584 + else
4585 + ast_verbose (VERBOSE_PREFIX_3 "Echo canceller successfully set up (PLCI=%#x)\n",PLCI);
4586 + }
4587 + }
4588 + if (option_verbose > 3) {
4589 + if (capidebug)
4590 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4591 + }
4592 +// ast_log(LOG_ERROR,"FACILITY_CONF NCCI=%#x INFO=%#x\n",(int)FACILITY_CONF_NCCI(CMSG),FACILITY_CONF_INFO(CMSG));
4593 + break;
4594 + case CAPI_INFO:
4595 + PLCI = INFO_CONF_PLCI(CMSG);
4596 +// ast_log(LOG_ERROR,"INFO_CONF PLCI=%#x INFO=%#x\n",PLCI,INFO_CONF_INFO(CMSG));
4597 + break;
4598 + case CAPI_CONNECT:
4599 + PLCI = CONNECT_CONF_PLCI(CMSG);
4600 + if (option_verbose > 3) {
4601 + if (capidebug)
4602 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4603 + }
4604 +// ast_log(LOG_ERROR,"CONNECT_CONF PLCI=%#x INFO=%#x MN=%#x\n",PLCI,CONNECT_CONF_INFO(CMSG),CMSG->Messagenumber);
4605 + break;
4606 + case CAPI_DISCONNECT:
4607 + PLCI = DISCONNECT_CONF_PLCI(CMSG);
4608 + if (option_verbose > 3) {
4609 + if (capidebug)
4610 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4611 + }
4612 +// ast_log(LOG_ERROR,"DISCONNECT_CONF PLCI=%#x INFO=%#x MN=%#x\n",PLCI,DISCONNECT_CONF_INFO(CMSG),CMSG->Messagenumber);
4613 + break;
4614 + case CAPI_DISCONNECT_B3:
4615 + NCCI = DISCONNECT_B3_CONF_NCCI(CMSG);
4616 + PLCI = (NCCI << 16) >> 16;
4617 + if (option_verbose > 3) {
4618 + if (capidebug)
4619 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4620 + }
4621 +// ast_log(LOG_ERROR,"DISCONNECT_B3_CONF NCCI=%#x INFO=%#x MN=%#x\n",NCCI,DISCONNECT_B3_CONF_INFO(CMSG),CMSG->Messagenumber);
4622 + break;
4623 + case CAPI_CONNECT_B3:
4624 + NCCI = CONNECT_B3_CONF_NCCI(CMSG);
4625 + PLCI = (NCCI << 16) >> 16;
4626 + if (option_verbose > 3) {
4627 + if (capidebug)
4628 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4629 + }
4630 +// ast_log(LOG_ERROR,"CONNECT_B3_CONF PLCI=%#x INFO=%#x MN=%#x\n",PLCI,CONNECT_B3_CONF_INFO(CMSG),CMSG->Messagenumber);
4631 + break;
4632 + case CAPI_ALERT:
4633 + PLCI = ALERT_CONF_PLCI(CMSG);
4634 + if (option_verbose > 3) {
4635 + if (capidebug)
4636 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4637 + }
4638 +// ast_log(LOG_ERROR,"ALERT_CONF PLCI=%#x\n",PLCI);
4639 + break;
4640 + case CAPI_DATA_B3:
4641 + NCCI = DATA_B3_CONF_NCCI(CMSG);
4642 + PLCI = (NCCI << 16) >> 16;
4643 + if (option_verbose > 5) {
4644 + if (capidebug)
4645 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
4646 + }
4647 +// ast_log(LOG_ERROR,"DATA_B3_CONF NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
4648 + break;
4649 + default:
4650 + ast_log(LOG_ERROR,"Command.Subcommand = %#x.%#x\n",CMSG->Command,CMSG->Subcommand);
4651 + }
4652 + break;
4653 + }
4654 + if (PLCI > 0) {
4655 + pipe_msg(PLCI,CMSG);
4656 + }
4657 +
4658 +}
4659 +
4660 +// module stuff, monitor...
4661 +
4662 +static void *do_monitor(void *data) {
4663 + unsigned int Info;
4664 + _cmsg *monCMSG;
4665 + for (;;) {
4666 +/*
4667 + if (ast_mutex_lock(&monlock)) {
4668 + ast_log(LOG_ERROR,"Unable to get monitor lock!\n");
4669 + return NULL;
4670 + }
4671 + // do some nifty stuff
4672 + ast_mutex_unlock(&monlock);
4673 +*/
4674 + monCMSG = malloc(sizeof(_cmsg));
4675 + memset(monCMSG,0,sizeof(_cmsg));
4676 + switch(Info = check_wait_get_cmsg(monCMSG)) {
4677 + case 0x0000:
4678 + if (option_verbose > 8) {
4679 + if (capidebug)
4680 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(monCMSG));
4681 + }
4682 + capi_handle_msg(monCMSG);
4683 + break;
4684 + case 0x1104:
4685 + // CAPI queue is empty
4686 + break;
4687 + default:
4688 + // something is wrong!
4689 + break;
4690 + } //switch
4691 + free(monCMSG);
4692 + } // for
4693 + // never reached
4694 + return NULL;
4695 +}
4696 +
4697 +#ifdef CAPI_GAIN
4698 +static void capi_gains(struct ast_capi_gains *g,float rxgain,float txgain) {
4699 + int i=0;
4700 + int x=0;
4701 + if (rxgain != 1.0) {
4702 + for (i=0;i<256;i++) {
4703 + x = (int)(((float)capiXLAW2INT(i)) * rxgain);
4704 + if (x > 32767) x = 32767;
4705 + if (x < -32767) x = -32767;
4706 + g->rxgains[i] = capiINT2XLAW(x);
4707 + }
4708 + } else {
4709 + for (i=0;i<256;i++) {
4710 + g->rxgains[i] = i;
4711 + }
4712 + }
4713 + if (txgain != 1.0) {
4714 + for (i=0;i<256;i++) {
4715 + x = (int)(((float)capiXLAW2INT(i)) * txgain);
4716 + if (x > 32767) x = 32767;
4717 + if (x < -32767) x = -32767;
4718 + g->txgains[i] = capiINT2XLAW(x);
4719 + }
4720 + } else {
4721 + for (i=0;i<256;i++) {
4722 + g->txgains[i] = i;
4723 + }
4724 + }
4725 +
4726 +}
4727 +#endif
4728 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
4729 +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) {
4730 +#else
4731 +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) {
4732 +#endif
4733 + struct ast_capi_pvt *tmp;
4734 + int i=0;
4735 + char buffer[100];
4736 + char *contr;
4737 + unsigned long contrmap=0;
4738 +
4739 + for (i=0;i<devices;i++) {
4740 + tmp = malloc(sizeof(struct ast_capi_pvt));
4741 + memset(tmp, 0, sizeof(struct ast_capi_pvt));
4742 + if (tmp) {
4743 + ast_mutex_init(&(tmp->lock));
4744 + strncpy(tmp->context, context, sizeof(tmp->context)-1);
4745 + strncpy(tmp->incomingmsn, incomingmsn, sizeof(tmp->incomingmsn)-1);
4746 + strncpy(tmp->prefix, prefix, sizeof(tmp->prefix)-1);
4747 + strncpy(tmp->accountcode, accountcode, sizeof(tmp->accountcode)-1);
4748 +
4749 + strncpy(buffer,controllerstr,sizeof(buffer)-1);
4750 + contr = strtok(buffer,",");
4751 + while (contr != NULL) {
4752 + contrmap |= (1 << atoi(contr));
4753 + if (capi_controllers[atoi(contr)]) {
4754 + capi_controllers[atoi(contr)]->isdnmode = isdnmode;
4755 + // ast_log(LOG_NOTICE, "contr %d isdnmode %d\n",atoi(contr),isdnmode);
4756 + }
4757 + contr = strtok(NULL,",");
4758 + }
4759 + tmp->controllers = contrmap;
4760 + capi_used_controllers |= contrmap;
4761 + tmp->controller = 0;
4762 + tmp->CLIR = 0;
4763 + tmp->earlyB3 = -1;
4764 + tmp->onholdPLCI = 0;
4765 + tmp->doEC = echocancel;
4766 + tmp->ecOption = ecoption;
4767 + tmp->ecTail = ectail;
4768 + tmp->isdnmode = isdnmode;
4769 + tmp->doES = es;
4770 + tmp->callgroup = callgroup;
4771 + tmp->group = group;
4772 +#ifdef CAPI_ES
4773 +#endif
4774 +#ifdef CAPI_GAIN
4775 + tmp->rxgain = rxgain;
4776 + tmp->txgain = txgain;
4777 + capi_gains(&tmp->g,rxgain,txgain);
4778 +#endif
4779 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
4780 + strncpy(tmp->deflect2, deflect2, sizeof(tmp->deflect2)-1);
4781 +#endif
4782 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
4783 + if (softdtmf == 1) {
4784 +#endif
4785 + tmp->doDTMF = 1;
4786 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
4787 + } else {
4788 + tmp->doDTMF = 0;
4789 + }
4790 +#endif
4791 + tmp->next = iflist; // prepend
4792 + iflist = tmp;
4793 + // 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);
4794 + if (option_verbose > 2) {
4795 + 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);
4796 + }
4797 +
4798 + } else {
4799 + return -1;
4800 + }
4801 + }
4802 + return 0;
4803 +}
4804 +
4805 +void supported_sservices(struct ast_capi_controller *cp) {
4806 + MESSAGE_EXCHANGE_ERROR error;
4807 + _cmsg CMSG,CMSG2;
4808 + struct timeval tv;
4809 + char fac[20];
4810 +
4811 + FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
4812 + FACILITY_REQ_CONTROLLER(&CMSG) = cp->controller;
4813 + FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 0x0003; // sservices
4814 + fac[0] = 3;
4815 + fac[1] = 0;
4816 + fac[2] = 0;
4817 + fac[3] = 0;
4818 + FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = (unsigned char *)&fac;
4819 + if ((error= _capi_put_cmsg(&CMSG)) != 0) {
4820 + ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
4821 + } else {
4822 + if (option_verbose > 5) {
4823 + ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_REQ (CONTROLLER=%#x)\n",cp->controller);
4824 + }
4825 + }
4826 +
4827 + tv.tv_sec = 1;
4828 + tv.tv_usec = 0;
4829 + for (;;){
4830 + error = capi20_waitformessage(ast_capi_ApplID,&tv);
4831 + error = capi_get_cmsg(&CMSG2,ast_capi_ApplID);
4832 +// error = check_wait_get_cmsg(&CMSG2);
4833 + if (error == 0) {
4834 + if (IS_FACILITY_CONF(&CMSG2)) {
4835 + if (option_verbose > 5) {
4836 + ast_verbose(VERBOSE_PREFIX_4 "FACILITY_CONF INFO = %#x\n",FACILITY_CONF_INFO(&CMSG2));
4837 + }
4838 + break;
4839 + }
4840 + }
4841 + }
4842 + // parse supported sservices
4843 + if (FACILITY_CONF_FACILITYSELECTOR(&CMSG2) == 0x0003) {
4844 + // success
4845 + if (FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[4] == 0) {
4846 + if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 1) == 1) {
4847 + cp->holdretrieve = 1;
4848 + if (option_verbose > 3)
4849 + ast_verbose(VERBOSE_PREFIX_4 "HOLD/RETRIEVE\n");
4850 + } else {
4851 + cp->holdretrieve = 0;
4852 + }
4853 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 2) >> 1) == 1) {
4854 + cp->terminalportability = 1;
4855 + if (option_verbose > 3)
4856 + ast_verbose(VERBOSE_PREFIX_4 "TERMINAL PORTABILITY\n");
4857 + } else {
4858 + cp->terminalportability = 0;
4859 + }
4860 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 4) >> 2) == 1) {
4861 + cp->ECT = 1;
4862 + if (option_verbose > 3)
4863 + ast_verbose(VERBOSE_PREFIX_4 "ECT\n");
4864 + } else {
4865 + cp->ECT = 0;
4866 + }
4867 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 8) >> 3) == 1) {
4868 + cp->threePTY = 1;
4869 + if (option_verbose > 3)
4870 + ast_verbose(VERBOSE_PREFIX_4 "3PTY\n");
4871 + } else {
4872 + cp->threePTY = 0;
4873 + }
4874 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 16) >> 4) == 1) {
4875 + cp->CF = 1;
4876 + if (option_verbose > 3)
4877 + ast_verbose(VERBOSE_PREFIX_4 "CF\n");
4878 + } else {
4879 + cp->CF = 0;
4880 + }
4881 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 32) >> 5) == 1) {
4882 + cp->CD = 1;
4883 + if (option_verbose > 3)
4884 + ast_verbose(VERBOSE_PREFIX_4 "CD\n");
4885 + } else {
4886 + cp->CD = 0;
4887 + }
4888 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 64) >> 6) == 1) {
4889 + cp->MCID = 1;
4890 + if (option_verbose > 3)
4891 + ast_verbose(VERBOSE_PREFIX_4 "MCID\n");
4892 + } else {
4893 + cp->MCID = 0;
4894 + }
4895 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 128) >> 7) == 1) {
4896 + cp->CCBS = 1;
4897 + if (option_verbose > 3)
4898 + ast_verbose(VERBOSE_PREFIX_4 "CCBS\n");
4899 + } else {
4900 + cp->CCBS = 0;
4901 + }
4902 + if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[7] & 1) == 1) {
4903 + cp->MWI = 1;
4904 + if (option_verbose > 3)
4905 + ast_verbose(VERBOSE_PREFIX_4 "MWI\n");
4906 + } else {
4907 + cp->MWI = 0;
4908 + }
4909 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[7] & 2) >> 1) == 1) {
4910 + cp->CCNR = 1;
4911 + if (option_verbose > 3)
4912 + ast_verbose(VERBOSE_PREFIX_4 "CCNR\n");
4913 + } else {
4914 + cp->CCNR = 0;
4915 + }
4916 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[7] & 4) >> 2) == 1) {
4917 + cp->CONF = 1;
4918 + if (option_verbose > 3)
4919 + ast_verbose(VERBOSE_PREFIX_4 "CONF\n");
4920 + } else {
4921 + cp->CONF = 0;
4922 + }
4923 + } else {
4924 + ast_log(LOG_NOTICE,"supplementary services info = %#x\n",(short)FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[1]);
4925 + }
4926 + } else {
4927 + ast_log(LOG_NOTICE,"unexpected FACILITY_SELECTOR = %#x\n",FACILITY_CONF_FACILITYSELECTOR(&CMSG2));
4928 + }
4929 +}
4930 +
4931 +static int capi_info(int fd, int argc, char *argv[])
4932 +{
4933 + int i=0;
4934 + if (argc != 2)
4935 + return RESULT_SHOWUSAGE;
4936 + for (i=1;i<=capi_num_controllers;i++) {
4937 + ast_mutex_lock(&contrlock);
4938 + if (capi_controllers[i] != NULL) {
4939 + ast_cli(fd,"Contr%d: %d B channels total, %d B channels free.\n",i,capi_controllers[i]->nbchannels,capi_controllers[i]->nfreebchannels);
4940 + }
4941 + ast_mutex_unlock(&contrlock);
4942 + }
4943 + return RESULT_SUCCESS;
4944 +}
4945 +
4946 +static int capi_do_debug(int fd, int argc, char *argv[])
4947 +{
4948 + if (argc != 2)
4949 + return RESULT_SHOWUSAGE;
4950 + capidebug = 1;
4951 + ast_cli(fd, "CAPI Debugging Enabled\n");
4952 + return RESULT_SUCCESS;
4953 +}
4954 +
4955 +static int capi_no_debug(int fd, int argc, char *argv[])
4956 +{
4957 + if (argc != 3)
4958 + return RESULT_SHOWUSAGE;
4959 + capidebug = 0;
4960 + ast_cli(fd, "CAPI Debugging Disabled\n");
4961 + return RESULT_SUCCESS;
4962 +}
4963 +
4964 +static char info_usage[] =
4965 +"Usage: capi info\n"
4966 +" Show info about B channels.\n";
4967 +
4968 +static char debug_usage[] =
4969 +"Usage: capi debug\n"
4970 +" Enables dumping of CAPI packets for debugging purposes\n";
4971 +
4972 +static char no_debug_usage[] =
4973 +"Usage: capi no debug\n"
4974 +" Disables dumping of CAPI packets for debugging purposes\n";
4975 +
4976 +static struct ast_cli_entry cli_info =
4977 + { { "capi", "info", NULL }, capi_info, "Show CAPI info", info_usage };
4978 +static struct ast_cli_entry cli_debug =
4979 + { { "capi", "debug", NULL }, capi_do_debug, "Enable CAPI debugging", debug_usage };
4980 +static struct ast_cli_entry cli_no_debug =
4981 + { { "capi", "no", "debug", NULL }, capi_no_debug, "Disable CAPI debugging", no_debug_usage };
4982 +
4983 +static const struct ast_channel_tech capi_tech = {
4984 + .type = type,
4985 + .description = tdesc,
4986 +#ifdef CAPI_ULAW
4987 + .capabilities = AST_FORMAT_ULAW,
4988 +#else
4989 + .capabilities = AST_FORMAT_ALAW,
4990 +#endif
4991 + .requester = capi_request,
4992 + .send_digit = capi_send_digit,
4993 + .send_text = NULL,
4994 + .call = capi_call,
4995 + .hangup = capi_hangup,
4996 + .answer = capi_answer,
4997 + .read = capi_read,
4998 + .write = capi_write,
4999 + .bridge = NULL,
5000 + .exception = NULL,
5001 + .indicate = capi_indicate,
5002 + .fixup = capi_fixup,
5003 + .setoption = NULL,
5004 +};
5005 +
5006 +int load_module(void)
5007 +{
5008 + struct ast_config *cfg;
5009 + struct ast_variable *v;
5010 + char *config = "capi.conf";
5011 + char incomingmsn[AST_MAX_EXTENSION]="";
5012 + char context[AST_MAX_EXTENSION]="";
5013 + char prefix[AST_MAX_EXTENSION]="";
5014 + char accountcode[20]="";
5015 + char *empty = "\0";
5016 + char deflect2[AST_MAX_EXTENSION]="";
5017 + char controllerstr[AST_MAX_EXTENSION]="";
5018 + int res = 0;
5019 + int controller=0;
5020 + int softdtmf=0;
5021 + int echocancel=1;
5022 + int ecoption=EC_OPTION_DISABLE_G165;
5023 + int ectail=EC_DEFAULT_TAIL;
5024 + int es=0;
5025 + float rxgain = 1.0;
5026 + float txgain = 1.0;
5027 + int isdnmode = 0;
5028 + unsigned int callgroup=0;
5029 + unsigned int group=0;
5030 + struct ast_capi_controller *cp;
5031 +
5032 + cfg = ast_config_load(config);
5033 +
5034 + /* We *must* have a config file otherwise stop immediately, well no... */
5035 + if (!cfg) {
5036 + ast_log(LOG_ERROR, "Unable to load config %s, CAPI disabled\n", config);
5037 + return 0;
5038 + }
5039 + if (ast_mutex_lock(&iflock)) {
5040 + ast_log(LOG_ERROR, "Unable to lock interface list???\n");
5041 + return -1;
5042 + }
5043 +
5044 + strncpy(capi_national_prefix, AST_CAPI_NATIONAL_PREF, sizeof(capi_national_prefix)-1);
5045 + strncpy(capi_international_prefix, AST_CAPI_NATIONAL_PREF, sizeof(capi_national_prefix)-1);
5046 + v = ast_variable_browse(cfg, "general");
5047 + while(v) {
5048 + if (!strcasecmp(v->name, "nationalprefix")) {
5049 + strncpy(capi_national_prefix, v->value, sizeof(capi_national_prefix)-1);
5050 + } else if (!strcasecmp(v->name, "internationalprefix")) {
5051 + strncpy(capi_international_prefix, v->value, sizeof(capi_international_prefix)-1);
5052 + } else if (!strcasecmp(v->name, "rxgain")) {
5053 + if (sscanf(v->value,"%f",&rxgain) != 1) {
5054 + ast_log(LOG_ERROR,"invalid rxgain\n");
5055 + }
5056 + } else if (!strcasecmp(v->name, "txgain")) {
5057 + if (sscanf(v->value,"%f",&txgain) != 1) {
5058 + ast_log(LOG_ERROR,"invalid txgain\n");
5059 + }
5060 + }
5061 + v = v->next;
5062 + }
5063 +
5064 +
5065 +
5066 +
5067 + if (capi20_isinstalled() != 0) {
5068 + ast_log(LOG_WARNING,"CAPI not installed, CAPI disabled!\n");
5069 + return 0;
5070 + }
5071 +
5072 + if (capi20_register(AST_CAPI_BCHANS,AST_CAPI_MAX_B3_BLOCKS,AST_CAPI_MAX_B3_BLOCK_SIZE,&ast_capi_ApplID) != 0) {
5073 + ast_log(LOG_NOTICE,"unable to register application at CAPI!\n");
5074 + return -1;
5075 + }
5076 +
5077 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5078 + if (capi20_get_profile(0,&profile) != 0) {
5079 +#else
5080 + if (capi20_get_profile(0,(unsigned char *)&profile) != 0) {
5081 +#endif
5082 + ast_log(LOG_NOTICE,"unable to get CAPI profile!\n");
5083 + return -1;
5084 + } else {
5085 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5086 + capi_num_controllers = profile.wCtlr;
5087 +#else
5088 + capi_num_controllers = profile.ncontrollers;
5089 +#endif
5090 + if (option_verbose > 3)
5091 + ast_verbose(VERBOSE_PREFIX_3 "This box has %d capi controller(s).\n",capi_num_controllers);
5092 + for (controller=1;controller<=capi_num_controllers;controller++) {
5093 +
5094 + memset(&profile,0,sizeof(profile));
5095 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5096 + capi20_get_profile(controller,&profile);
5097 +#else
5098 + capi20_get_profile(controller,(unsigned char *)&profile);
5099 +#endif
5100 + cp = malloc(sizeof(struct ast_capi_controller));
5101 + cp->controller = controller;
5102 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5103 + cp->nbchannels = profile.wNumBChannels;
5104 + cp->nfreebchannels = profile.wNumBChannels;
5105 + if (profile.dwGlobalOptions & CAPI_PROFILE_DTMF_SUPPORT) {
5106 +#else
5107 + cp->nbchannels = profile.nbchannels;
5108 + cp->nfreebchannels = profile.nbchannels;
5109 + if ((profile.globaloptions & 8) >> 3 == 1) {
5110 +#endif
5111 + if (option_verbose > 3)
5112 + ast_verbose(VERBOSE_PREFIX_3 "CAPI/contr%d supports DTMF\n",controller);
5113 + cp->dtmf = 1;
5114 + } else {
5115 + cp->dtmf = 0;
5116 + }
5117 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5118 + if (profile.dwGlobalOptions & CAPI_PROFILE_ECHO_CANCELLATION) {
5119 +#else
5120 + if (profile.globaloptions2 & 1) {
5121 +#endif
5122 + if (option_verbose > 3)
5123 + ast_verbose(VERBOSE_PREFIX_3 "CAPI/contr%d supports echo cancellation\n",controller);
5124 + cp->echocancel = 1;
5125 + } else {
5126 + cp->echocancel = 0;
5127 + }
5128 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5129 + if (profile.dwGlobalOptions & CAPI_PROFILE_SUPPLEMENTARY_SERVICES) {
5130 +#else
5131 + if ((profile.globaloptions & 16) >> 4 == 1) {
5132 +#endif
5133 + cp->sservices = 1;
5134 + } else {
5135 + cp->sservices = 0;
5136 + }
5137 + capi_controllers[controller] = cp;
5138 + if (cp->sservices == 1) {
5139 + if (option_verbose > 3)
5140 + ast_verbose(VERBOSE_PREFIX_3 "CAPI/contr%d supports supplementary services\n",controller);
5141 + supported_sservices(cp);
5142 + }
5143 + }
5144 + }
5145 +
5146 + v = ast_variable_browse(cfg, "interfaces");
5147 + while(v) {
5148 + /* Create the interface list */
5149 + if (!strcasecmp(v->name, "devices")) {
5150 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
5151 + if (mkif(incomingmsn,context,controllerstr,atoi(v->value),softdtmf,echocancel,ecoption,ectail, prefix, isdnmode, es,rxgain,txgain,deflect2,accountcode,callgroup, group)) {
5152 +#else
5153 + if (mkif(incomingmsn,context,controllerstr,atoi(v->value),softdtmf,echocancel,ecoption,ectail, prefix, isdnmode, es,rxgain,txgain,accountcode,callgroup, group)) {
5154 +#endif
5155 + ast_log(LOG_ERROR,"Error creating interface list\n");
5156 + return -1;
5157 + }
5158 + es=0;
5159 + strncpy(deflect2, empty, sizeof(deflect2)-1);
5160 + } else if (!strcasecmp(v->name, "context")) {
5161 + strncpy(context, v->value, sizeof(context)-1);
5162 + } else if (!strcasecmp(v->name, "incomingmsn")) {
5163 + strncpy(incomingmsn, v->value, sizeof(incomingmsn)-1);
5164 + } else if (!strcasecmp(v->name, "controller")) {
5165 + strncpy(controllerstr, v->value, sizeof(controllerstr)-1);
5166 + } else if (!strcasecmp(v->name, "softdtmf")) {
5167 + softdtmf = atoi(v->value);
5168 + } else if (!strcasecmp(v->name, "echosquelch")) {
5169 + es = atoi(v->value);
5170 + } else if (!strcasecmp(v->name, "callgroup")) {
5171 + callgroup = ast_get_group(v->value);
5172 + } else if (!strcasecmp(v->name, "group")) {
5173 + group = ast_get_group(v->value);
5174 + } else if (!strcasecmp(v->name, "deflect")) {
5175 + strncpy(deflect2, v->value, sizeof(deflect2)-1);
5176 + } else if (!strcasecmp(v->name, "rxgain")) {
5177 + if (sscanf(v->value,"%f",&rxgain) != 1) {
5178 + ast_log(LOG_ERROR,"invalid rxgain\n");
5179 + }
5180 + } else if (!strcasecmp(v->name, "txgain")) {
5181 + if (sscanf(v->value,"%f",&txgain) != 1) {
5182 + ast_log(LOG_ERROR,"invalid txgain\n");
5183 + }
5184 + } else if (!strcasecmp(v->name, "echocancel")) {
5185 + if (!strcasecmp(v->value, "yes") || !strcasecmp(v->value, "1") || !strcasecmp(v->value, "on")) {
5186 + echocancel=1;
5187 + ecoption=EC_OPTION_DISABLE_G165;
5188 + }
5189 + else if (!strcasecmp(v->value, "no") || !strcasecmp(v->value, "0") || !strcasecmp(v->value, "off")) {
5190 + echocancel=0;
5191 + ecoption=0;
5192 + }
5193 + else if (!strcasecmp(v->value, "g165") || !strcasecmp(v->value, "g.165")) {
5194 + echocancel=1;
5195 + ecoption=EC_OPTION_DISABLE_G165;
5196 + }
5197 + else if (!strcasecmp(v->value, "g164") || !strcasecmp(v->value, "g.164")) {
5198 + echocancel=1;
5199 + ecoption=EC_OPTION_DISABLE_G164_OR_G165;
5200 + }
5201 + else if (!strcasecmp(v->value, "force")) {
5202 + echocancel=1;
5203 + ecoption=EC_OPTION_DISABLE_NEVER;
5204 + }
5205 + else {
5206 + ast_log(LOG_ERROR,"Unknown echocancel parameter \"%s\" -- ignoring\n",v->value);
5207 + }
5208 + } else if (!strcasecmp(v->name, "echotail")) {
5209 + ectail = atoi(v->value);
5210 + if (ectail > 255)
5211 + ectail = 255;
5212 + } else if (!strcasecmp(v->name, "prefix")) {
5213 + strncpy(prefix, v->value, sizeof(prefix)-1);
5214 + } else if (!strcasecmp(v->name, "accountcode")) {
5215 + strncpy(accountcode, v->value, sizeof(accountcode)-1);
5216 + } else if (!strcasecmp(v->name, "isdnmode")) {
5217 + if (!strcasecmp(v->value, "ptp") || !strcasecmp(v->value, "1"))
5218 + isdnmode = 1;
5219 + else if (!strcasecmp(v->value, "ptm") || !strcasecmp(v->value, "0") || !strcasecmp(v->value, "ptmp"))
5220 + isdnmode = 0;
5221 + else
5222 + ast_log(LOG_ERROR,"Unknown isdnmode parameter \"%s\" -- ignoring\n",v->value);
5223 +
5224 + }
5225 +
5226 + v = v->next;
5227 + }
5228 + ast_config_destroy(cfg);
5229 +
5230 + for (controller=1;controller<=capi_num_controllers;controller++) {
5231 + if (capi_used_controllers & (1 << controller)) {
5232 + if (ListenOnController(ALL_SERVICES,controller) != 0) {
5233 + ast_log(LOG_ERROR,"Unable to listen on contr%d\n",controller);
5234 + } else {
5235 + if (option_verbose > 2)
5236 + ast_verbose(VERBOSE_PREFIX_3 "listening on contr%d CIPmask = %#x\n",controller,ALL_SERVICES);
5237 + }
5238 + } else {
5239 + ast_log(LOG_WARNING,"Unused contr%d\n",controller);
5240 + }
5241 + }
5242 +
5243 +
5244 + ast_mutex_unlock(&iflock);
5245 +
5246 + if (ast_channel_register(&capi_tech)) {
5247 + ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
5248 + unload_module();
5249 + return -1;
5250 + }
5251 +
5252 + ast_cli_register(&cli_info);
5253 + ast_cli_register(&cli_debug);
5254 + ast_cli_register(&cli_no_debug);
5255 +
5256 + if (ast_mutex_lock(&monlock)) {
5257 + ast_log(LOG_WARNING,"Unable to get monitor lock!\n");
5258 + return -1;
5259 + }
5260 + if (monitor_thread == pthread_self()) {
5261 + ast_mutex_unlock(&monlock);
5262 + ast_log(LOG_WARNING,"Unable to kill myself!\n");
5263 + return -1;
5264 + }
5265 +
5266 + if (ast_pthread_create(&monitor_thread,NULL,do_monitor,NULL) < 0) {
5267 + ast_mutex_unlock(&monlock);
5268 + ast_log(LOG_ERROR,"Unable to start monitor thread!\n");
5269 + return -1;
5270 + }
5271 +
5272 + return res;
5273 +}
5274 +
5275 +
5276 +int unload_module()
5277 +{
5278 + if (capi20_release(ast_capi_ApplID) != 0)
5279 + ast_log(LOG_WARNING,"Unable to unregister from CAPI!\n");
5280 + ast_channel_unregister(&capi_tech);
5281 + return 0;
5282 +}
5283 +
5284 +int usecount()
5285 +{
5286 + int res;
5287 + ast_mutex_lock(&usecnt_lock);
5288 + res = usecnt;
5289 + ast_mutex_unlock(&usecnt_lock);
5290 + return res;
5291 +}
5292 +
5293 +char *description()
5294 +{
5295 + return desc;
5296 +}
5297 +
5298 +
5299 +char *key()
5300 +{
5301 + return ASTERISK_GPL_KEY;
5302 +}
5303 diff -urN asterisk-1.2.4.orig/channels/chan_features.c asterisk-1.2.4/channels/chan_features.c
5304 --- asterisk-1.2.4.orig/channels/chan_features.c 2006-01-25 19:39:44.000000000 +0100
5305 +++ asterisk-1.2.4/channels/chan_features.c 2006-01-31 09:41:43.000000000 +0100
5306 @@ -438,7 +438,7 @@
5307 }
5308 ast_mutex_unlock(&featurelock);
5309 if (!tmp) {
5310 - chan = ast_request(tech, format, dest, &status);
5311 + chan = ast_request(tech, format, dest, &status, NULL);
5312 if (!chan) {
5313 ast_log(LOG_NOTICE, "Unable to allocate subchannel '%s/%s'\n", tech, dest);
5314 return NULL;
5315 diff -urN asterisk-1.2.4.orig/channels/chan_iax2.c asterisk-1.2.4/channels/chan_iax2.c
5316 --- asterisk-1.2.4.orig/channels/chan_iax2.c 2006-01-20 02:00:46.000000000 +0100
5317 +++ asterisk-1.2.4/channels/chan_iax2.c 2006-01-31 09:41:43.000000000 +0100
5318 @@ -11,6 +11,9 @@
5319 * the project provides a web site, mailing lists and IRC
5320 * channels for your use.
5321 *
5322 + * Hangup cause signalling implementation by
5323 + * Levent Guendogdu <levon@feature-it.com>
5324 + *
5325 * This program is free software, distributed under the terms of
5326 * the GNU General Public License Version 2. See the LICENSE file
5327 * at the top of the source tree.
5328 @@ -3050,7 +3053,7 @@
5329 memset(&ied, 0, sizeof(ied));
5330 ast_mutex_lock(&iaxsl[callno]);
5331 if (callno && iaxs[callno]) {
5332 - ast_log(LOG_DEBUG, "We're hanging up %s now...\n", c->name);
5333 + ast_log(LOG_DEBUG, "We're hanging up %s with cause %i now...\n", c->name, c->hangupcause);
5334 alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
5335 /* Send the hangup unless we have had a transmission error or are already gone */
5336 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
5337 @@ -3102,7 +3105,8 @@
5338 static struct ast_frame *iax2_read(struct ast_channel *c)
5339 {
5340 static struct ast_frame f = { AST_FRAME_NULL, };
5341 - ast_log(LOG_NOTICE, "I should never be called!\n");
5342 + if (option_verbose > 3)
5343 + ast_log(LOG_NOTICE, "I should never be called!\n");
5344 return &f;
5345 }
5346
5347 @@ -6688,7 +6692,7 @@
5348 }
5349 if (f.frametype == AST_FRAME_IAX) {
5350 if (iaxs[fr.callno]->initid > -1) {
5351 - /* Don't auto congest anymore since we've gotten something usefulb ack */
5352 + /* Don't auto congest anymore since we've gotten something useful back */
5353 ast_sched_del(sched, iaxs[fr.callno]->initid);
5354 iaxs[fr.callno]->initid = -1;
5355 }
5356 diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_sip.c
5357 --- asterisk-1.2.4.orig/channels/chan_sip.c 2006-01-28 14:52:15.000000000 +0100
5358 +++ asterisk-1.2.4/channels/chan_sip.c 2006-01-31 09:41:43.000000000 +0100
5359 @@ -596,6 +596,7 @@
5360 unsigned int flags; /*!< SIP_ flags */
5361 int timer_t1; /*!< SIP timer T1, ms rtt */
5362 unsigned int sipoptions; /*!< Supported SIP sipoptions on the other end */
5363 + int dialog_established; /*!< SIP dialog established */
5364 int capability; /*!< Special capability (codec) */
5365 int jointcapability; /*!< Supported capability at both ends (codecs ) */
5366 int peercapability; /*!< Supported peer capability */
5367 @@ -619,6 +620,7 @@
5368 char refer_to[AST_MAX_EXTENSION]; /*!< Place to store REFER-TO extension */
5369 char referred_by[AST_MAX_EXTENSION]; /*!< Place to store REFERRED-BY extension */
5370 char refer_contact[AST_MAX_EXTENSION]; /*!< Place to store Contact info from a REFER extension */
5371 + char refer_replaces[AST_MAX_EXTENSION]; /*!< Place to store Replaces header of REFER-TO header */
5372 struct sip_pvt *refer_call; /*!< Call we are referring */
5373 struct sip_route *route; /*!< Head of linked list of routing steps (fm Record-Route) */
5374 int route_persistant; /*!< Is this the "real" route? */
5375 @@ -638,6 +640,7 @@
5376 char peername[256]; /*!< [peer] name, not set if [user] */
5377 char authname[256]; /*!< Who we use for authentication */
5378 char uri[256]; /*!< Original requested URI */
5379 + char origuri[256]; /*!< REAL! Original requested URI */
5380 char okcontacturi[256]; /*!< URI from the 200 OK on INVITE */
5381 char peersecret[256]; /*!< Password */
5382 char peermd5secret[256];
5383 @@ -921,7 +924,7 @@
5384 static int determine_firstline_parts(struct sip_request *req);
5385 static void sip_dump_history(struct sip_pvt *dialog); /* Dump history to LOG_DEBUG at end of dialog, before destroying data */
5386 static const struct cfsubscription_types *find_subscription_type(enum subscriptiontype subtype);
5387 -static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate);
5388 +static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate, char *cid_num, char *cid_name);
5389 static char *gettag(struct sip_request *req, char *header, char *tagbuf, int tagbufsize);
5390
5391 /*! \brief Definition of this channel for PBX channel registration */
5392 @@ -1304,7 +1307,7 @@
5393 /* If this is a subscription, tell the phone that we got a timeout */
5394 if (p->subscribed) {
5395 p->subscribed = TIMEOUT;
5396 - transmit_state_notify(p, AST_EXTENSION_DEACTIVATED, 1, 1); /* Send first notification */
5397 + transmit_state_notify(p, AST_EXTENSION_DEACTIVATED, 1, 1, NULL, NULL); /* Send first notification */
5398 p->subscribed = NONE;
5399 append_history(p, "Subscribestatus", "timeout");
5400 return 10000; /* Reschedule this destruction so that we know that it's gone */
5401 @@ -3109,16 +3112,30 @@
5402
5403 /*! \brief find_call: Connect incoming SIP message to current dialog or create new dialog structure */
5404 /* Called by handle_request, sipsock_read */
5405 -static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *sin, const int intended_method)
5406 +static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *sin, const int intended_method, const int replaces_callid)
5407 {
5408 struct sip_pvt *p;
5409 char *callid;
5410 char *tag = "";
5411 + char *replaces;
5412 char totag[128];
5413 char fromtag[128];
5414 + char *c;
5415
5416 callid = get_header(req, "Call-ID");
5417
5418 + if (replaces_callid) {
5419 + replaces = get_header(req, "Replaces");
5420 + c = strchr(replaces, ';');
5421 + if (c)
5422 + *c = '\0';
5423 + if (!ast_strlen_zero(replaces)) {
5424 + callid = replaces;
5425 + } else {
5426 + return NULL;
5427 + }
5428 + }
5429 +
5430 if (pedanticsipchecking) {
5431 /* In principle Call-ID's uniquely identify a call, but with a forking SIP proxy
5432 we need more to identify a branch - so we have to check branch, from
5433 @@ -4043,6 +4060,7 @@
5434 if (sipmethod == SIP_CANCEL) {
5435 c = p->initreq.rlPart2; /* Use original URI */
5436 } else if (sipmethod == SIP_ACK) {
5437 +// XXX+ } else if (!strcasecmp(msg, "ACK") && !p->dialog_established) {
5438 /* Use URI from Contact: in 200 OK (if INVITE)
5439 (we only have the contacturi on INVITEs) */
5440 if (!ast_strlen_zero(p->okcontacturi))
5441 @@ -4808,10 +4826,12 @@
5442 ast_build_string(&invite, &invite_max, ";%s", p->options->uri_options);
5443
5444 ast_copy_string(p->uri, invite_buf, sizeof(p->uri));
5445 + ast_copy_string(p->origuri, invite, sizeof(p->origuri));
5446
5447 /* If there is a VXML URL append it to the SIP URL */
5448 if (p->options && p->options->vxml_url) {
5449 - snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url);
5450 +// snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url);
5451 + snprintf(to, sizeof(to), "<%s;%s>", p->uri, p->options->vxml_url);
5452 } else {
5453 snprintf(to, sizeof(to), "<%s>", p->uri);
5454 }
5455 @@ -4867,6 +4887,11 @@
5456 if (!ast_strlen_zero(p->referred_by))
5457 add_header(&req, "Referred-By", p->referred_by);
5458 }
5459 + if (sipmethod == SIP_INVITE) {
5460 + if (!ast_strlen_zero(p->refer_replaces)) {
5461 + add_header(&req, "Replaces", p->refer_replaces);
5462 + }
5463 + }
5464 #ifdef OSP_SUPPORT
5465 if ((req.method != SIP_OPTIONS) && p->options && !ast_strlen_zero(p->options->osptoken)) {
5466 ast_log(LOG_DEBUG,"Adding OSP Token: %s\n", p->options->osptoken);
5467 @@ -4941,8 +4966,7 @@
5468 }
5469
5470 /*! \brief transmit_state_notify: Used in the SUBSCRIBE notification subsystem ----*/
5471 -static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate)
5472 -{
5473 +static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate, char *cid_num, char *cid_name) {
5474 char tmp[4000], from[256], to[256];
5475 char *t = tmp, *c, *a, *mfrom, *mto;
5476 size_t maxbytes = sizeof(tmp);
5477 @@ -5086,10 +5110,19 @@
5478 case DIALOG_INFO_XML: /* SNOM subscribes in this format */
5479 ast_build_string(&t, &maxbytes, "<?xml version=\"1.0\"?>\n");
5480 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);
5481 - if ((state & AST_EXTENSION_RINGING) && global_notifyringing)
5482 - ast_build_string(&t, &maxbytes, "<dialog id=\"%s\" direction=\"recipient\">\n", p->exten);
5483 - else
5484 + if ((state & AST_EXTENSION_RINGING) && global_notifyringing) {
5485 + ast_build_string(&t, &maxbytes, "<dialog id=\"%s\" direction=\"recipient\">\n", p->exten);
5486 + if (cid_num) {
5487 + ast_build_string(&t, &maxbytes, "<local><identity display=\"%s\">%s</identity><target uri=\"%s\"/></local>\n", p->exten, p->exten, mfrom);
5488 + if (cid_name && !ast_strlen_zero(cid_name)) {
5489 + 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);
5490 + } else {
5491 + 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);
5492 + }
5493 + }
5494 + } else {
5495 ast_build_string(&t, &maxbytes, "<dialog id=\"%s\">\n", p->exten);
5496 + }
5497 ast_build_string(&t, &maxbytes, "<state>%s</state>\n", statestring);
5498 ast_build_string(&t, &maxbytes, "</dialog>\n</dialog-info>\n");
5499 break;
5500 @@ -6299,7 +6332,7 @@
5501 /*! \brief cb_extensionstate: Callback for the devicestate notification (SUBSCRIBE) support subsystem ---*/
5502 /* If you add an "hint" priority to the extension in the dial plan,
5503 you will get notifications on device state changes */
5504 -static int cb_extensionstate(char *context, char* exten, int state, void *data)
5505 +static int cb_extensionstate(char *context, char* exten, int state, void *data, char *cid_num, char *cid_name)
5506 {
5507 struct sip_pvt *p = data;
5508
5509 @@ -6318,7 +6351,7 @@
5510 p->laststate = state;
5511 break;
5512 }
5513 - transmit_state_notify(p, state, 1, 1);
5514 + transmit_state_notify(p, state, 1, 1, cid_num, cid_name);
5515
5516 if (option_debug > 1)
5517 ast_verbose(VERBOSE_PREFIX_1 "Extension Changed %s new state %s for Notify User %s\n", exten, ast_extension_state2str(state), p->username);
5518 @@ -8584,6 +8617,7 @@
5519 char buf[1024];
5520 unsigned int event;
5521 char *c;
5522 + struct ast_call_feature *feature;
5523
5524 /* Need to check the media/type */
5525 if (!strcasecmp(get_header(req, "Content-Type"), "application/dtmf-relay") ||
5526 @@ -8647,6 +8681,19 @@
5527 ast_queue_control(p->owner, AST_CONTROL_VIDUPDATE);
5528 transmit_response(p, "200 OK", req);
5529 return;
5530 + } else if ((c = get_header(req, "Record"))) {
5531 + feature = ast_find_builtin_feature("automon");
5532 + if (feature && (!ast_strlen_zero(feature->exten))) {
5533 + int i = 0;
5534 +// ast_log(LOG_NOTICE, "feature exten %s\n", feature->exten);
5535 + for (i=0; i<strlen(feature->exten); i++) {
5536 + struct ast_frame f = { AST_FRAME_DTMF, feature->exten[i] };
5537 + ast_queue_frame(p->owner, &f);
5538 + }
5539 + } else {
5540 + ast_log(LOG_NOTICE, "Feature \"One Touch Monitor\" not configured in features.conf.\n");
5541 + }
5542 + return;
5543 } else if ((c = get_header(req, "X-ClientCode"))) {
5544 /* Client code (from SNOM phone) */
5545 if (ast_test_flag(p, SIP_USECLIENTCODE)) {
5546 @@ -8746,12 +8793,63 @@
5547 return RESULT_SUCCESS;
5548 }
5549
5550 +
5551 +/*! \brief sip_notify: Send SIP notify to peer */
5552 +static int sip_send_notify(int fd, char *notify_type, char *peer)
5553 +{
5554 + struct ast_variable *varlist;
5555 + struct sip_pvt *p;
5556 + struct sip_request req;
5557 + struct ast_variable *var;
5558 +
5559 + varlist = ast_variable_browse(notify_types, notify_type);
5560 +
5561 + if (!varlist) {
5562 + if (fd > 0)
5563 + ast_cli(fd, "Unable to find notify type '%s'\n", notify_type);
5564 + return RESULT_FAILURE;
5565 + }
5566 +
5567 + p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY);
5568 + if (!p) {
5569 + ast_log(LOG_WARNING, "Unable to build sip pvt data for notify\n");
5570 + return RESULT_FAILURE;
5571 + }
5572 +
5573 + if (create_addr(p, peer)) {
5574 + /* Maybe they're not registered, etc. */
5575 + sip_destroy(p);
5576 + if (fd > 0)
5577 + ast_cli(fd, "Could not create address for '%s'\n", peer);
5578 + return RESULT_FAILURE;
5579 + }
5580 +
5581 + initreqprep(&req, p, SIP_NOTIFY);
5582 +
5583 + for (var = varlist; var; var = var->next)
5584 + add_header(&req, var->name, var->value);
5585 +
5586 + add_blank_header(&req);
5587 + /* Recalculate our side, and recalculate Call ID */
5588 + if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
5589 + memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
5590 + build_via(p, p->via, sizeof(p->via));
5591 + build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
5592 + if (fd > 0)
5593 + ast_cli(fd, "Sending NOTIFY of type '%s' to '%s'\n", notify_type, peer);
5594 + transmit_sip_request(p, &req);
5595 + sip_scheddestroy(p, 15000);
5596 +
5597 + return RESULT_SUCCESS;
5598 +}
5599 +
5600 /*! \brief sip_notify: Send SIP notify to peer */
5601 static int sip_notify(int fd, int argc, char *argv[])
5602 {
5603 struct ast_variable *varlist;
5604 int i;
5605 -
5606 + int res = RESULT_SUCCESS;
5607 +
5608 if (argc < 4)
5609 return RESULT_SHOWUSAGE;
5610
5611 @@ -8768,41 +8866,13 @@
5612 }
5613
5614 for (i = 3; i < argc; i++) {
5615 - struct sip_pvt *p;
5616 - struct sip_request req;
5617 - struct ast_variable *var;
5618 -
5619 - p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY);
5620 - if (!p) {
5621 - ast_log(LOG_WARNING, "Unable to build sip pvt data for notify\n");
5622 - return RESULT_FAILURE;
5623 - }
5624 -
5625 - if (create_addr(p, argv[i])) {
5626 - /* Maybe they're not registered, etc. */
5627 - sip_destroy(p);
5628 - ast_cli(fd, "Could not create address for '%s'\n", argv[i]);
5629 - continue;
5630 - }
5631 -
5632 - initreqprep(&req, p, SIP_NOTIFY);
5633 -
5634 - for (var = varlist; var; var = var->next)
5635 - add_header(&req, var->name, var->value);
5636 + if (sip_send_notify(fd, argv[2], argv[i]) == RESULT_FAILURE)
5637 + res = RESULT_FAILURE;
5638 + }
5639 + return res;
5640 +}
5641
5642 - add_blank_header(&req);
5643 - /* Recalculate our side, and recalculate Call ID */
5644 - if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
5645 - memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
5646 - build_via(p, p->via, sizeof(p->via));
5647 - build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
5648 - ast_cli(fd, "Sending NOTIFY of type '%s' to '%s'\n", argv[2], argv[i]);
5649 - transmit_sip_request(p, &req);
5650 - sip_scheddestroy(p, 15000);
5651 - }
5652
5653 - return RESULT_SUCCESS;
5654 -}
5655 /*! \brief sip_do_history: Enable SIP History logging (CLI) ---*/
5656 static int sip_do_history(int fd, int argc, char *argv[])
5657 {
5658 @@ -9447,7 +9517,7 @@
5659 if (!ignore && p->owner) {
5660 ast_queue_control(p->owner, AST_CONTROL_RINGING);
5661 if (p->owner->_state != AST_STATE_UP)
5662 - ast_setstate(p->owner, AST_STATE_RINGING);
5663 + ast_setstate_and_cid(p->owner, AST_STATE_RINGING, p->owner->cid.cid_num, p->owner->cid.cid_name);
5664 }
5665 if (!strcasecmp(get_header(req, "Content-Type"), "application/sdp")) {
5666 process_sdp(p, req);
5667 @@ -10801,7 +10871,7 @@
5668 struct sip_pvt *p_old;
5669
5670 transmit_response(p, "200 OK", req);
5671 - transmit_state_notify(p, firststate, 1, 1); /* Send first notification */
5672 + transmit_state_notify(p, firststate, 1, 1, NULL, NULL); /* Send first notification */
5673 append_history(p, "Subscribestatus", ast_extension_state2str(firststate));
5674
5675 /* remove any old subscription from this peer for the same exten/context,
5676 @@ -11113,7 +11183,7 @@
5677 /* Process request, with netlock held */
5678 retrylock:
5679 ast_mutex_lock(&netlock);
5680 - p = find_call(&req, &sin, req.method);
5681 + p = find_call(&req, &sin, req.method, 0);
5682 if (p) {
5683 /* Go ahead and lock the owner if it has one -- we may need it */
5684 if (p->owner && ast_mutex_trylock(&p->owner->lock)) {
5685 @@ -11435,6 +11505,52 @@
5686 return 0;
5687 }
5688
5689 +static char mandescr_sip_notify[] =
5690 +"Description: Send a NOTIFY message to one or more SIP peers.\n"
5691 +"Variables: \n"
5692 +" Peer: <name> The peer name you want to send a NOTIFY to.\n"
5693 +" Type: <name> The notify type (see sip_notify.conf).\n"
5694 +" ActionID: <id> Optional action ID for this AMI transaction.\n";
5695 +
5696 +/*! \brief manager_sip_notify: Send a notify (see sip_notify.conf) to a peer ---*/
5697 +static int manager_sip_notify(struct mansession *s, struct message *m)
5698 +{
5699 + char *id = astman_get_header(m,"ActionID");
5700 + char *peer;
5701 + char *notify_type;
5702 + int res = 0;
5703 +
5704 + peer = astman_get_header(m,"Peer");
5705 + if (ast_strlen_zero(peer)) {
5706 + astman_send_error(s, m, "Peer: <name> missing.\n");
5707 + return 0;
5708 + }
5709 + notify_type = astman_get_header(m,"Type");
5710 + if (ast_strlen_zero(notify_type)) {
5711 + astman_send_error(s, m, "Type: <name> missing.\n");
5712 + return 0;
5713 + }
5714 +
5715 + res = sip_send_notify(-1, notify_type, peer);
5716 + if (res != RESULT_SUCCESS) {
5717 + ast_cli(s->fd, "Response: SIPNotify Failure\r\n"
5718 + "Peer: %s\r\n"
5719 + "Type: %s\r\n"
5720 + "ActionID: %s\r\n"
5721 + "\r\n",
5722 + peer, notify_type, id);
5723 + } else {
5724 + ast_cli(s->fd, "Response: SIPNotify Success\r\n"
5725 + "Peer: %s\r\n"
5726 + "Type: %s\r\n"
5727 + "ActionID: %s\r\n"
5728 + "\r\n",
5729 + peer, notify_type, id);
5730 + }
5731 + return res;
5732 +}
5733 +
5734 +
5735 /*! \brief sip_devicestate: Part of PBX channel interface ---*/
5736
5737 /* Return values:---
5738 @@ -13128,6 +13244,8 @@
5739 "List SIP peers (text format)", mandescr_show_peers);
5740 ast_manager_register2("SIPshowpeer", EVENT_FLAG_SYSTEM, manager_sip_show_peer,
5741 "Show SIP peer (text format)", mandescr_show_peer);
5742 + ast_manager_register2("SIPNotify", EVENT_FLAG_SYSTEM, manager_sip_notify,
5743 + "Send NOTIFY to peer", mandescr_sip_notify);
5744
5745 sip_poke_all_peers();
5746 sip_send_all_registers();
5747 @@ -13158,6 +13276,7 @@
5748
5749 ast_rtp_proto_unregister(&sip_rtp);
5750
5751 + ast_manager_unregister("SIPNotify");
5752 ast_manager_unregister("SIPpeers");
5753 ast_manager_unregister("SIPshowpeer");
5754
5755 diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_zap.c
5756 --- asterisk-1.2.4.orig/channels/chan_zap.c 2006-01-30 18:08:28.000000000 +0100
5757 +++ asterisk-1.2.4/channels/chan_zap.c 2006-01-31 09:46:14.000000000 +0100
5758 @@ -11,6 +11,10 @@
5759 * the project provides a web site, mailing lists and IRC
5760 * channels for your use.
5761 *
5762 + * Copyright (C) 2003, 2004, 2005 Junghanns.NET GmbH
5763 + * Klaus-Peter Junghanns <kpj@junghanns.net>
5764 + *
5765 + *
5766 * This program is free software, distributed under the terms of
5767 * the GNU General Public License Version 2. See the LICENSE file
5768 * at the top of the source tree.
5769 @@ -96,6 +100,7 @@
5770 #include "asterisk/term.h"
5771 #include "asterisk/utils.h"
5772 #include "asterisk/transcap.h"
5773 +#include "asterisk/devicestate.h"
5774
5775 #ifndef ZT_SIG_EM_E1
5776 #error "Your zaptel is too old. please cvs update"
5777 @@ -183,7 +188,7 @@
5778 #define SIG_GR303FXOKS (0x0100000 | ZT_SIG_FXOKS)
5779 #define SIG_GR303FXSKS (0x0100000 | ZT_SIG_FXSKS)
5780
5781 -#define NUM_SPANS 32
5782 +#define NUM_SPANS 128 /*!<"32 spans", muahahaha, us alaws like to have some more... */
5783 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
5784 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
5785
5786 @@ -201,6 +206,9 @@
5787 static char defaultcic[64] = "";
5788 static char defaultozz[64] = "";
5789
5790 +static char nocid[256] = "No CID available";
5791 +static char withheldcid[256] = "CID withheld";
5792 +
5793 static char language[MAX_LANGUAGE] = "";
5794 static char musicclass[MAX_MUSICCLASS] = "";
5795 static char progzone[10]= "";
5796 @@ -287,6 +295,7 @@
5797 static int cur_priexclusive = 0;
5798
5799 static int priindication_oob = 0;
5800 +static int pritransfer = 0;
5801
5802 #ifdef ZAPATA_PRI
5803 static int minunused = 2;
5804 @@ -294,6 +303,7 @@
5805 static char idleext[AST_MAX_EXTENSION];
5806 static char idledial[AST_MAX_EXTENSION];
5807 static int overlapdial = 0;
5808 +static int usercid = 0;
5809 static int facilityenable = 0;
5810 static char internationalprefix[10] = "";
5811 static char nationalprefix[10] = "";
5812 @@ -305,8 +315,6 @@
5813 #ifdef PRI_GETSET_TIMERS
5814 static int pritimers[PRI_MAX_TIMERS];
5815 #endif
5816 -static int pridebugfd = -1;
5817 -static char pridebugfilename[1024]="";
5818 #endif
5819
5820 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
5821 @@ -327,10 +335,6 @@
5822
5823 static int ifcount = 0;
5824
5825 -#ifdef ZAPATA_PRI
5826 -AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
5827 -#endif
5828 -
5829 /*! \brief Whether we answer on a Polarity Switch event */
5830 static int answeronpolarityswitch = 0;
5831
5832 @@ -403,6 +407,27 @@
5833 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
5834 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
5835
5836 +struct zt_suspended_call {
5837 + ast_mutex_t lock; /* Mutex */
5838 + char msn[AST_MAX_EXTENSION]; /* the MSN to which this parked call belongs */
5839 + char callid[10]; /* the callID provided by the user */
5840 + int parked_at; /* extension in the call parking context */
5841 + struct zt_suspended_call *next;
5842 +};
5843 +
5844 +struct zt_holded_call {
5845 + ast_mutex_t lock; /* Mutex */
5846 + char msn[AST_MAX_EXTENSION]; /* the MSN to which this parked call belongs */
5847 + char uniqueid[AST_MAX_EXTENSION]; /* unique id of the onhold channel */
5848 + int tei;
5849 + int cref;
5850 + int alreadyhungup;
5851 + struct ast_channel *channel;
5852 + struct ast_channel *bridge;
5853 + q931_call *call; /* this also covers tei mumbojumbo */
5854 + struct zt_holded_call *next;
5855 +};
5856 +
5857 struct zt_pri {
5858 pthread_t master; /*!< Thread of master */
5859 ast_mutex_t lock; /*!< Mutex */
5860 @@ -416,6 +441,8 @@
5861 int nsf; /*!< Network-Specific Facilities */
5862 int dialplan; /*!< Dialing plan */
5863 int localdialplan; /*!< Local dialing plan */
5864 + char nocid[256];
5865 + char withheldcid[256];
5866 char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
5867 char nationalprefix[10]; /*!< area access code ('0' for european dialplans) */
5868 char localprefix[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
5869 @@ -435,6 +462,7 @@
5870 int fds[NUM_DCHANS]; /*!< FD's for d-channels */
5871 int offset;
5872 int span;
5873 + int usercid; /* trust user provided callerid (callerani) ?? */
5874 int resetting;
5875 int resetpos;
5876 time_t lastreset; /*!< time when unused channels were last reset */
5877 @@ -442,6 +470,9 @@
5878 struct zt_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
5879 struct zt_pvt *crvs; /*!< Member CRV structs */
5880 struct zt_pvt *crvend; /*!< Pointer to end of CRV structs */
5881 + struct zt_suspended_call *suspended_calls; /* Calls parked with SUSPEND messages */
5882 + struct zt_holded_call *holded_calls; /* Calls on hold */
5883 + int debugfd;
5884 };
5885
5886
5887 @@ -561,6 +592,8 @@
5888 unsigned int echocanbridged:1;
5889 unsigned int echocanon:1;
5890 unsigned int faxhandled:1; /*!< Has a fax tone already been handled? */
5891 + /*!< KPJ: i will abuse this flag to implement a zapata option for dialing out
5892 + on a zap channel with EC to be off no matter what happens. */
5893 unsigned int firstradio:1;
5894 unsigned int hanguponpolarityswitch:1;
5895 unsigned int hardwaredtmf:1;
5896 @@ -573,7 +606,8 @@
5897 unsigned int overlapdial:1;
5898 unsigned int permcallwaiting:1;
5899 unsigned int permhidecallerid:1; /*!< Whether to hide our outgoing caller ID or not */
5900 - unsigned int priindication_oob:1;
5901 + unsigned int priindication_oob:2;
5902 + unsigned int pritransfer:2;
5903 unsigned int priexclusive:1;
5904 unsigned int pulse:1;
5905 unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */
5906 @@ -612,6 +646,7 @@
5907 #endif
5908 char cid_num[AST_MAX_EXTENSION];
5909 int cid_ton; /*!< Type Of Number (TON) */
5910 + int cid_pres; /*!< Calling Presentation */
5911 char cid_name[AST_MAX_EXTENSION];
5912 char lastcid_num[AST_MAX_EXTENSION];
5913 char lastcid_name[AST_MAX_EXTENSION];
5914 @@ -676,6 +711,8 @@
5915 struct zt_pri *pri;
5916 struct zt_pvt *bearer;
5917 struct zt_pvt *realcall;
5918 + int tei; /* channel in use by this tei */
5919 + q931_call *holdedcall;
5920 q931_call *call;
5921 int prioffset;
5922 int logicalspan;
5923 @@ -701,11 +738,14 @@
5924 static int zt_indicate(struct ast_channel *chan, int condition);
5925 static int zt_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
5926 static int zt_setoption(struct ast_channel *chan, int option, void *data, int datalen);
5927 +static int zt_devicestate(void *data);
5928 +static void disable_dtmf_detect(struct zt_pvt *p);
5929 +static void enable_dtmf_detect(struct zt_pvt *p);
5930
5931 static const struct ast_channel_tech zap_tech = {
5932 .type = type,
5933 .description = tdesc,
5934 - .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW,
5935 + .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
5936 .requester = zt_request,
5937 .send_digit = zt_digit,
5938 .send_text = zt_sendtext,
5939 @@ -719,6 +759,7 @@
5940 .indicate = zt_indicate,
5941 .fixup = zt_fixup,
5942 .setoption = zt_setoption,
5943 + .devicestate = zt_devicestate
5944 };
5945
5946 #ifdef ZAPATA_PRI
5947 @@ -730,6 +771,13 @@
5948 struct zt_pvt *round_robin[32];
5949
5950 #ifdef ZAPATA_PRI
5951 +struct app_tmp {
5952 + char app[256];
5953 + char data[256];
5954 + struct ast_channel *chan;
5955 + pthread_t t;
5956 +};
5957 +
5958 static inline int pri_grab(struct zt_pvt *pvt, struct zt_pri *pri)
5959 {
5960 int res;
5961 @@ -779,6 +827,112 @@
5962 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
5963 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
5964
5965 +static int zt_devicestate(void *data)
5966 +{
5967 + int groupmatch = 0;
5968 + int channelmatch = 0;
5969 + struct zt_pvt *p;
5970 + char *dest=NULL;
5971 + int x,d;
5972 + char *s;
5973 + char opt=0;
5974 + int res, y=0;
5975 + struct zt_pvt *exit, *start, *end;
5976 + ast_mutex_t *lock;
5977 +
5978 +// ast_log(LOG_NOTICE, "data = %s\n", (char *)data);
5979 + return AST_DEVICE_UNKNOWN;
5980 +
5981 + /* Assume we're locking the iflock */
5982 + lock = &iflock;
5983 + start = iflist;
5984 + end = ifend;
5985 +
5986 + if (data) {
5987 + dest = ast_strdupa((char *)data);
5988 + } else {
5989 + ast_log(LOG_WARNING, "Channel requested with no data\n");
5990 + return AST_DEVICE_INVALID;
5991 + }
5992 + if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
5993 + /* Retrieve the group number */
5994 + char *stringp=NULL;
5995 + stringp=dest + 1;
5996 + s = strsep(&stringp, "/");
5997 + if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
5998 + ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
5999 + return AST_DEVICE_INVALID;
6000 + }
6001 + groupmatch = 1 << x;
6002 + } else {
6003 + char *stringp=NULL;
6004 + stringp=dest;
6005 + s = strsep(&stringp, "/");
6006 + p = iflist;
6007 + if (!strcasecmp(s, "pseudo")) {
6008 + /* Special case for pseudo */
6009 + x = CHAN_PSEUDO;
6010 + channelmatch = x;
6011 + /* bail out */
6012 + return AST_DEVICE_INVALID;
6013 + }
6014 +
6015 + else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
6016 + ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
6017 + return AST_DEVICE_INVALID;
6018 + } else {
6019 + channelmatch = x;
6020 + ast_log(LOG_NOTICE, "channelmatch = %d\n", channelmatch);
6021 + }
6022 + }
6023 + /* Search for an unowned channel */
6024 + if (ast_mutex_lock(lock)) {
6025 + ast_log(LOG_ERROR, "Unable to lock interface list???\n");
6026 + return AST_DEVICE_INVALID;
6027 + }
6028 + p = iflist;
6029 + exit = iflist;
6030 + res = AST_DEVICE_INVALID; /* start pessimistic */
6031 + while(p) {
6032 + if (p) {
6033 + ast_mutex_lock(&p->lock);
6034 + if ((groupmatch && ((p->group & groupmatch) != 0)) || (channelmatch && (p->channel == channelmatch))) {
6035 +#ifdef ZAPATA_PRI
6036 + if (p->pri) {
6037 + for(d=0;d<NUM_DCHANS;d++) {
6038 + if (p->pri->dchanavail[d] & DCHAN_UP) {
6039 + res = AST_DEVICE_UNKNOWN;
6040 + }
6041 + }
6042 + }
6043 +#endif
6044 + 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))))) {
6045 + res = AST_DEVICE_UNKNOWN;
6046 + if (p->owner) {
6047 + if ((p->owner->_state == AST_STATE_RINGING) && (p->outgoing)) {
6048 + res = AST_DEVICE_RINGING;
6049 + }
6050 + 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)){
6051 + res = AST_DEVICE_INUSE;
6052 + }
6053 + }
6054 + if ((res == AST_DEVICE_INUSE) || (res == AST_DEVICE_RINGING)) {
6055 + /* stop searching now, one non-idle channel is sufficient */
6056 + ast_mutex_unlock(&p->lock);
6057 + break;
6058 + }
6059 + }
6060 + }
6061 + ast_mutex_unlock(&p->lock);
6062 + }
6063 + p = p->next;
6064 + }
6065 + ast_mutex_unlock(lock);
6066 +
6067 + return res;
6068 +
6069 +}
6070 +
6071 static int zt_get_index(struct ast_channel *ast, struct zt_pvt *p, int nullok)
6072 {
6073 int res;
6074 @@ -1381,12 +1535,16 @@
6075 int res;
6076 if (!p)
6077 return;
6078 + if (p->faxhandled) {
6079 + ast_log(LOG_DEBUG, "Not enabling echo cancellation on a fax/modem call\n");
6080 + return;
6081 + }
6082 if (p->echocanon) {
6083 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
6084 return;
6085 }
6086 if (p->digital) {
6087 - ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
6088 + ast_log(LOG_DEBUG, "Echo cancellation does not make any sense on digital connections!\n");
6089 return;
6090 }
6091 if (p->echocancel) {
6092 @@ -1412,7 +1570,7 @@
6093 {
6094 int x;
6095 int res;
6096 - if (p && p->echocancel && p->echotraining) {
6097 + if (p && p->echocancel && p->echotraining && (!p->digital) && (!p->faxhandled)) {
6098 x = p->echotraining;
6099 res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOTRAIN, &x);
6100 if (res)
6101 @@ -1774,7 +1932,13 @@
6102 ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", p->channel);
6103 p->outgoing = 1;
6104
6105 - set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
6106 + if (IS_DIGITAL(ast->transfercapability)) {
6107 + set_actual_gain(p->subs[SUB_REAL].zfd, 0, 0, 0, p->law);
6108 + } else {
6109 + set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
6110 + }
6111 +
6112 + disable_dtmf_detect(p);
6113
6114 switch(p->sig) {
6115 case SIG_FXOLS:
6116 @@ -2016,6 +2180,12 @@
6117 int ldp_strip;
6118 int exclusive;
6119
6120 + if ((p->pri->nodetype == BRI_NETWORK_PTMP) || (p->pri->nodetype == BRI_NETWORK)) {
6121 + // pass NO audio when ringing an isdn phone
6122 + p->dialing = 1;
6123 + // maybe we could allow passing audio when calling a p2p PBX, but well... ;-)
6124 + }
6125 +
6126 c = strchr(dest, '/');
6127 if (c)
6128 c++;
6129 @@ -2033,6 +2203,7 @@
6130 ast_mutex_unlock(&p->lock);
6131 return -1;
6132 }
6133 + strncpy(p->dnid, (c + p->stripmsd), sizeof(p->dnid)-1);
6134 if (p->sig != SIG_FXSKS) {
6135 p->dop.op = ZT_DIAL_OP_REPLACE;
6136 s = strchr(c + p->stripmsd, 'w');
6137 @@ -2056,6 +2227,8 @@
6138 pri_rel(p->pri);
6139 ast_mutex_unlock(&p->lock);
6140 return -1;
6141 + } else {
6142 + // ast_log(LOG_NOTICE, "call %d\n", p->call);
6143 }
6144 if (!(sr = pri_sr_new())) {
6145 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
6146 @@ -2287,8 +2460,10 @@
6147 }
6148 if (newslot < 0) {
6149 newslot = 0;
6150 - ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
6151 + if (pri->nodetype != BRI_CPE_PTMP) {
6152 + ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
6153 pri->dchannels[newslot]);
6154 + }
6155 }
6156 if (old && (oldslot != newslot))
6157 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
6158 @@ -2344,8 +2519,7 @@
6159
6160 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
6161 p->channel, index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
6162 - p->ignoredtmf = 0;
6163 -
6164 +
6165 if (index > -1) {
6166 /* Real channel, do some fixup */
6167 p->subs[index].owner = NULL;
6168 @@ -2442,6 +2616,7 @@
6169
6170
6171 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
6172 + int outgoing = p->outgoing;
6173 p->owner = NULL;
6174 p->ringt = 0;
6175 p->distinctivering = 0;
6176 @@ -2505,6 +2680,26 @@
6177 icause = atoi(cause);
6178 }
6179 pri_hangup(p->pri->pri, p->call, icause);
6180 +
6181 + /* if we send a release complete we wont ge no hangup event, so clear the call here */
6182 + if (icause == 34 || icause == 44 || icause == 82 || icause == 1 || icause == 81 || icause == 17) {
6183 + if ((ast->_state == AST_STATE_RING) || (ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING)) {
6184 + p->call = NULL;
6185 + } else {
6186 + ast_log(LOG_ERROR, "What is wrong with you? You cannot use cause %d number when in state %d!\n", icause, ast->_state);
6187 + icause = 16;
6188 + }
6189 + }
6190 +
6191 + if (p->pri->nodetype == BRI_NETWORK_PTMP) {
6192 + if ((icause == 16 || icause == -1) && (ast->_state != AST_STATE_UP)) {
6193 + if (outgoing) {
6194 + p->call = NULL;
6195 + }
6196 + }
6197 + }
6198 +
6199 +
6200 }
6201 if (res < 0)
6202 ast_log(LOG_WARNING, "pri_disconnect failed\n");
6203 @@ -2701,10 +2896,14 @@
6204 p->proceeding = 1;
6205 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
6206 pri_rel(p->pri);
6207 + /* stop ignoring inband dtmf */
6208 + enable_dtmf_detect(p);
6209 } else {
6210 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
6211 res= -1;
6212 }
6213 + /* the audio path is complete now, train the echo canceler */
6214 + zt_train_ec(p);
6215 break;
6216 #endif
6217 #ifdef ZAPATA_R2
6218 @@ -3274,6 +3473,15 @@
6219 {
6220 struct zt_pvt *p = newchan->tech_pvt;
6221 int x;
6222 + if (newchan && newchan->tech_pvt) {
6223 + p = newchan->tech_pvt;
6224 + }
6225 + if (!p) {
6226 + if (newchan) {
6227 + ast_log(LOG_ERROR, "channel %s has no tech_pvt structure\n", newchan->name);
6228 + }
6229 + return 0;
6230 + }
6231 ast_mutex_lock(&p->lock);
6232 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
6233 if (p->owner == oldchan) {
6234 @@ -4600,7 +4808,7 @@
6235 p->subs[index].f.data = NULL;
6236 p->subs[index].f.datalen= 0;
6237 }
6238 - if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
6239 + if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
6240 /* Perform busy detection. etc on the zap line */
6241 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
6242 if (f) {
6243 @@ -4612,8 +4820,9 @@
6244 }
6245 } else if (f->frametype == AST_FRAME_DTMF) {
6246 #ifdef ZAPATA_PRI
6247 - if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
6248 - /* Don't accept in-band DTMF when in overlap dial mode */
6249 + if (p->ignoredtmf) {
6250 + /* Don't accept in-band DTMF when in overlap dial mode
6251 + or when in non-overlap overlapdialing mode ... */
6252 f->frametype = AST_FRAME_NULL;
6253 f->subclass = 0;
6254 }
6255 @@ -4748,7 +4957,9 @@
6256 #endif
6257 /* Write a frame of (presumably voice) data */
6258 if (frame->frametype != AST_FRAME_VOICE) {
6259 - if (frame->frametype != AST_FRAME_IMAGE)
6260 + if (frame->frametype == AST_FRAME_TEXT) {
6261 + ast_log(LOG_NOTICE, "text\n");
6262 + } else if (frame->frametype != AST_FRAME_IMAGE)
6263 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
6264 return 0;
6265 }
6266 @@ -4819,7 +5030,7 @@
6267 switch(condition) {
6268 case AST_CONTROL_BUSY:
6269 #ifdef ZAPATA_PRI
6270 - if (p->priindication_oob && p->sig == SIG_PRI) {
6271 + if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
6272 chan->hangupcause = AST_CAUSE_USER_BUSY;
6273 chan->_softhangup |= AST_SOFTHANGUP_DEV;
6274 res = 0;
6275 @@ -4901,7 +5112,7 @@
6276 case AST_CONTROL_CONGESTION:
6277 chan->hangupcause = AST_CAUSE_CONGESTION;
6278 #ifdef ZAPATA_PRI
6279 - if (p->priindication_oob && p->sig == SIG_PRI) {
6280 + if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
6281 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
6282 chan->_softhangup |= AST_SOFTHANGUP_DEV;
6283 res = 0;
6284 @@ -5086,8 +5297,12 @@
6285 if (state == AST_STATE_RING)
6286 tmp->rings = 1;
6287 tmp->tech_pvt = i;
6288 - if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
6289 - /* Only FXO signalled stuff can be picked up */
6290 +#ifdef ZAPATA_PRI
6291 + if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS) || (i->sig == SIG_PRI)) {
6292 +#else
6293 + if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
6294 +#endif
6295 + /* Only FXO signalled stuff can be picked up */ /* i dont think so, mr. ulaw! we alaws like to pick up BRIs/PRIs */
6296 tmp->callgroup = i->callgroup;
6297 tmp->pickupgroup = i->pickupgroup;
6298 }
6299 @@ -5217,6 +5432,7 @@
6300 int len = 0;
6301 int res;
6302 int index;
6303 + int network;
6304 if (option_verbose > 2)
6305 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
6306 index = zt_get_index(chan, p, 1);
6307 @@ -5235,10 +5451,17 @@
6308 len = strlen(exten);
6309 res = 0;
6310 while((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
6311 - if (len && !ast_ignore_pattern(chan->context, exten))
6312 + if (len && !ast_ignore_pattern(chan->context, exten)) {
6313 tone_zone_play_tone(p->subs[index].zfd, -1);
6314 - else
6315 - tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
6316 + } else {
6317 + network = p->pri->nodetype == PRI_NETWORK || p->pri->nodetype == BRI_NETWORK || p->pri->nodetype == BRI_NETWORK_PTMP;
6318 + if (network) {
6319 + tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
6320 + } else {
6321 + /* cpe be quiet */
6322 + tone_zone_play_tone(p->subs[index].zfd, -1);
6323 + }
6324 + }
6325 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
6326 timeout = matchdigittimeout;
6327 else
6328 @@ -6720,6 +6943,8 @@
6329 } else {
6330 if (si->totalchans == 31) { /* if it's an E1 */
6331 pris[*span].dchannels[0] = 16 + offset;
6332 + } else if (si->totalchans == 3) { /* if it's an S0 ZAPBRI */
6333 + pris[*span].dchannels[0] = 3 + offset;
6334 } else {
6335 pris[*span].dchannels[0] = 24 + offset;
6336 }
6337 @@ -6965,6 +7190,11 @@
6338 destroy_zt_pvt(&tmp);
6339 return NULL;
6340 }
6341 + if ((pris[span].localdialplan) && (pris[span].localdialplan != localdialplan)) {
6342 + ast_log(LOG_ERROR, "Span %d is already a %s local dialing plan\n", span + 1, dialplan2str(pris[span].localdialplan));
6343 + destroy_zt_pvt(&tmp);
6344 + return NULL;
6345 + }
6346 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, idledial)) {
6347 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, idledial);
6348 destroy_zt_pvt(&tmp);
6349 @@ -6992,6 +7222,17 @@
6350 return NULL;
6351 }
6352 pris[span].nodetype = pritype;
6353 +// XXX
6354 + if (pritype == BRI_NETWORK_PTMP) {
6355 + pris[span].dchanavail[0] = DCHAN_AVAILABLE;
6356 + pri_find_dchan(&pris[span]);
6357 + }
6358 +// XXX tuev
6359 +
6360 + if ((pritype == BRI_CPE) || (pritype == BRI_CPE_PTMP)) {
6361 + pris[span].dchanavail[0] = DCHAN_AVAILABLE;
6362 + pri_find_dchan(&pris[span]);
6363 + }
6364 pris[span].switchtype = myswitchtype;
6365 pris[span].nsf = nsf;
6366 pris[span].dialplan = dialplan;
6367 @@ -7000,9 +7241,14 @@
6368 pris[span].minunused = minunused;
6369 pris[span].minidle = minidle;
6370 pris[span].overlapdial = overlapdial;
6371 + pris[span].usercid = usercid;
6372 + pris[span].suspended_calls = NULL;
6373 + pris[span].holded_calls = NULL;
6374 pris[span].facilityenable = facilityenable;
6375 ast_copy_string(pris[span].idledial, idledial, sizeof(pris[span].idledial));
6376 ast_copy_string(pris[span].idleext, idleext, sizeof(pris[span].idleext));
6377 + ast_copy_string(pris[span].nocid, nocid, sizeof(pris[span].nocid) - 1);
6378 + ast_copy_string(pris[span].withheldcid, withheldcid, sizeof(pris[span].withheldcid) - 1);
6379 ast_copy_string(pris[span].internationalprefix, internationalprefix, sizeof(pris[span].internationalprefix));
6380 ast_copy_string(pris[span].nationalprefix, nationalprefix, sizeof(pris[span].nationalprefix));
6381 ast_copy_string(pris[span].localprefix, localprefix, sizeof(pris[span].localprefix));
6382 @@ -7156,6 +7402,7 @@
6383 tmp->restrictcid = restrictcid;
6384 tmp->use_callingpres = use_callingpres;
6385 tmp->priindication_oob = priindication_oob;
6386 + tmp->pritransfer = pritransfer;
6387 tmp->priexclusive = cur_priexclusive;
6388 if (tmp->usedistinctiveringdetection) {
6389 if (!tmp->use_callerid) {
6390 @@ -7429,7 +7676,7 @@
6391 break;
6392 if (!backwards && (x >= pri->numchans))
6393 break;
6394 - if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
6395 + if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner && !pri->pvts[x]->call) {
6396 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
6397 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
6398 return x;
6399 @@ -7476,7 +7723,7 @@
6400 end = ifend;
6401 /* We do signed linear */
6402 oldformat = format;
6403 - format &= (AST_FORMAT_SLINEAR | AST_FORMAT_ULAW);
6404 + format &= (AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW);
6405 if (!format) {
6406 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
6407 return NULL;
6408 @@ -7636,6 +7883,11 @@
6409 p->digital = 1;
6410 if (tmp)
6411 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
6412 + } else if (opt == 'm') {
6413 + /* If this is a modem/fax call, pretend to have the fax handled and dont do EC */
6414 + p->faxhandled = 1;
6415 + if (tmp)
6416 + tmp->transfercapability = AST_TRANS_CAP_3_1K_AUDIO;
6417 } else {
6418 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
6419 }
6420 @@ -7689,6 +7941,57 @@
6421 return NULL;
6422 }
6423
6424 +static int pri_find_tei(struct zt_pri *pri, q931_call *c, int tei)
6425 +{
6426 + int x=0;
6427 + for (x=0;x<pri->numchans;x++) {
6428 + if (!pri->pvts[x]) continue;
6429 + if ((pri->pvts[x]->tei == tei) && (pri->pvts[x]-> call != c)) {
6430 + return x;
6431 + }
6432 + }
6433 + return -1;
6434 +}
6435 +
6436 +static struct zt_holded_call *pri_get_callonhold(struct zt_pri *pri, int cref, int tei) {
6437 + struct zt_holded_call *zhc = pri->holded_calls;
6438 + struct zt_holded_call *zhctemp = NULL;
6439 +
6440 + while (zhc) {
6441 + if ((zhc->tei == tei) && ((zhc->cref == cref) || (cref == -1))) {
6442 + return zhc;
6443 + }
6444 + zhctemp = zhc;
6445 + if (zhc) zhc = zhc->next;
6446 + }
6447 + return NULL;
6448 +}
6449 +
6450 +static int pri_destroy_callonhold(struct zt_pri *pri, struct zt_holded_call *onhold) {
6451 + struct zt_holded_call *zhc = pri->holded_calls;
6452 + struct zt_holded_call *zhctemp = NULL;
6453 +
6454 + while (zhc) {
6455 + if (zhc == onhold) {
6456 + if (zhctemp) {
6457 + zhctemp->next = zhc->next;
6458 + zhc = zhctemp;
6459 + } else {
6460 + pri->holded_calls = zhc->next;
6461 + zhc = pri->holded_calls;
6462 + zhctemp = NULL;
6463 + }
6464 + }
6465 + zhctemp = zhc;
6466 + if (zhc) zhc = zhc->next;
6467 + }
6468 + if (onhold) {
6469 + free(onhold);
6470 + onhold = NULL;
6471 + return 1;
6472 + }
6473 + return 0;
6474 +}
6475
6476 static int pri_find_principle(struct zt_pri *pri, int channel)
6477 {
6478 @@ -7721,7 +8024,9 @@
6479 static int pri_fixup_principle(struct zt_pri *pri, int principle, q931_call *c)
6480 {
6481 int x;
6482 + int res = 0;
6483 struct zt_pvt *crv;
6484 + char tmpname[256];
6485 if (!c) {
6486 if (principle < 0)
6487 return -1;
6488 @@ -7735,6 +8040,7 @@
6489 /* First, check for other bearers */
6490 for (x=0;x<pri->numchans;x++) {
6491 if (!pri->pvts[x]) continue;
6492 +// ast_log(LOG_NOTICE, "principle %d channel %d call %d channel[x]->call %d\n",principle, x, c, pri->pvts[x]->call);
6493 if (pri->pvts[x]->call == c) {
6494 /* Found our call */
6495 if (principle != x) {
6496 @@ -7748,19 +8054,56 @@
6497 }
6498 /* Fix it all up now */
6499 pri->pvts[principle]->owner = pri->pvts[x]->owner;
6500 + pri->pvts[principle]->outgoing = pri->pvts[x]->outgoing;
6501 if (pri->pvts[principle]->owner) {
6502 snprintf(pri->pvts[principle]->owner->name, sizeof(pri->pvts[principle]->owner->name),
6503 "Zap/%d:%d-%d", pri->trunkgroup, pri->pvts[principle]->channel, 1);
6504 pri->pvts[principle]->owner->tech_pvt = pri->pvts[principle];
6505 pri->pvts[principle]->owner->fds[0] = pri->pvts[principle]->subs[SUB_REAL].zfd;
6506 pri->pvts[principle]->subs[SUB_REAL].owner = pri->pvts[x]->subs[SUB_REAL].owner;
6507 - } else
6508 + } else {
6509 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);
6510 + }
6511 pri->pvts[principle]->call = pri->pvts[x]->call;
6512 + pri->pvts[principle]->dsp = pri->pvts[x]->dsp;
6513 + pri->pvts[principle]->alreadyhungup = pri->pvts[x]->alreadyhungup;
6514 + pri->pvts[principle]->digital = pri->pvts[x]->digital;
6515 + pri->pvts[principle]->faxhandled = pri->pvts[x]->faxhandled;
6516 +
6517 + if ((pri->nodetype == BRI_CPE_PTMP) || (pri->nodetype == BRI_CPE)) {
6518 + /* this might also apply for other pri types! */
6519 + pri->pvts[principle]->law = pri->pvts[x]->law;
6520 + if (ioctl(pri->pvts[principle]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &pri->pvts[principle]->law) == -1)
6521 + ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", pri->pvts[principle]->channel, pri->pvts[principle]->law);
6522 + res = zt_setlaw(pri->pvts[principle]->subs[SUB_REAL].zfd, pri->pvts[principle]->law);
6523 + if (res < 0)
6524 + ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[principle]->channel);
6525 + if (!pri->pvts[principle]->digital) {
6526 + res = set_actual_gain(pri->pvts[principle]->subs[SUB_REAL].zfd, 0, pri->pvts[principle]->rxgain, pri->pvts[principle]->txgain, pri->pvts[principle]->law);
6527 + } else {
6528 + res = set_actual_gain(pri->pvts[principle]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[principle]->law);
6529 + }
6530 + if (res < 0)
6531 + ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[principle]->channel);
6532 + zt_confmute(pri->pvts[x], 0);
6533 + update_conf(pri->pvts[x]);
6534 + reset_conf(pri->pvts[x]);
6535 + restore_gains(pri->pvts[x]);
6536 + zt_disable_ec(pri->pvts[x]);
6537 + zt_setlinear(pri->pvts[x]->subs[SUB_REAL].zfd, 0);
6538 + }
6539 +
6540 + if (pri->pvts[principle]->owner) {
6541 + snprintf(tmpname, sizeof(tmpname), "Zap/%d-1", pri->pvts[principle]->channel);
6542 + ast_change_name(pri->pvts[principle]->owner, tmpname);
6543 + }
6544 +
6545 +
6546 /* Free up the old channel, now not in use */
6547 pri->pvts[x]->subs[SUB_REAL].owner = NULL;
6548 pri->pvts[x]->owner = NULL;
6549 pri->pvts[x]->call = NULL;
6550 + pri->pvts[x]->dsp = NULL;
6551 }
6552 return principle;
6553 }
6554 @@ -7789,7 +8132,9 @@
6555 }
6556 crv = crv->next;
6557 }
6558 - ast_log(LOG_WARNING, "Call specified, but not found?\n");
6559 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
6560 + ast_log(LOG_WARNING, "Call specified, but not found?\n");
6561 + }
6562 return -1;
6563 }
6564
6565 @@ -7851,86 +8196,21 @@
6566 #ifndef PRI_RESTART
6567 #error "Upgrade your libpri"
6568 #endif
6569 -static void zt_pri_message(struct pri *pri, char *s)
6570 +static void zt_pri_message(char *s, int span)
6571 {
6572 - int x, y;
6573 - int dchan = -1, span = -1;
6574 - int dchancount = 0;
6575 -
6576 - if (pri) {
6577 - for (x = 0; x < NUM_SPANS; x++) {
6578 - for (y = 0; y < NUM_DCHANS; y++) {
6579 - if (pris[x].dchans[y])
6580 - dchancount++;
6581 -
6582 - if (pris[x].dchans[y] == pri)
6583 - dchan = y;
6584 - }
6585 - if (dchan >= 0) {
6586 - span = x;
6587 - break;
6588 - }
6589 - dchancount = 0;
6590 - }
6591 - if ((dchan >= 0) && (span >= 0)) {
6592 - if (dchancount > 1)
6593 - ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
6594 - else
6595 - ast_verbose("%s", s);
6596 - } else
6597 - ast_verbose("PRI debug error: could not find pri associated it with debug message output\n");
6598 - } else
6599 - ast_verbose("%s", s);
6600 -
6601 - ast_mutex_lock(&pridebugfdlock);
6602 -
6603 - if (pridebugfd >= 0)
6604 - write(pridebugfd, s, strlen(s));
6605 -
6606 - ast_mutex_unlock(&pridebugfdlock);
6607 + ast_verbose("%d %s", span, s);
6608 }
6609
6610 -static void zt_pri_error(struct pri *pri, char *s)
6611 +static void zt_pri_error(char *s, int span)
6612 {
6613 - int x, y;
6614 - int dchan = -1, span = -1;
6615 - int dchancount = 0;
6616 -
6617 - if (pri) {
6618 - for (x = 0; x < NUM_SPANS; x++) {
6619 - for (y = 0; y < NUM_DCHANS; y++) {
6620 - if (pris[x].dchans[y])
6621 - dchancount++;
6622 -
6623 - if (pris[x].dchans[y] == pri)
6624 - dchan = y;
6625 - }
6626 - if (dchan >= 0) {
6627 - span = x;
6628 - break;
6629 - }
6630 - dchancount = 0;
6631 - }
6632 - if ((dchan >= 0) && (span >= 0)) {
6633 - if (dchancount > 1)
6634 - ast_log(LOG_WARNING, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
6635 - else
6636 - ast_verbose("%s", s);
6637 - } else
6638 - ast_verbose("PRI debug error: could not find pri associated it with debug message output\n");
6639 - } else
6640 - ast_log(LOG_WARNING, "%s", s);
6641 -
6642 - ast_mutex_lock(&pridebugfdlock);
6643 -
6644 - if (pridebugfd >= 0)
6645 - write(pridebugfd, s, strlen(s));
6646 -
6647 - ast_mutex_unlock(&pridebugfdlock);
6648 + ast_log(LOG_WARNING, "%d %s", span, s);
6649 }
6650
6651 static int pri_check_restart(struct zt_pri *pri)
6652 {
6653 + if ((pri->nodetype != PRI_NETWORK) || (pri->nodetype != PRI_CPE)) {
6654 + return 0;
6655 + }
6656 do {
6657 pri->resetpos++;
6658 } while((pri->resetpos < pri->numchans) &&
6659 @@ -8013,6 +8293,32 @@
6660 }
6661 }
6662
6663 +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) {
6664 + if (callingnum && (callingnum_len > stripmsd)) {
6665 + callingnum += stripmsd;
6666 + }
6667 + switch (callingplan) {
6668 + case PRI_INTERNATIONAL_ISDN:
6669 + snprintf(callerid, callerid_len, "%s%s", pri->internationalprefix, callingnum);
6670 + break;
6671 + case PRI_NATIONAL_ISDN:
6672 + snprintf(callerid, callerid_len, "%s%s", pri->nationalprefix, callingnum);
6673 + break;
6674 + case PRI_LOCAL_ISDN:
6675 + snprintf(callerid, callerid_len, "%s%s", pri->localprefix, callingnum);
6676 + break;
6677 + case PRI_PRIVATE:
6678 + snprintf(callerid, callerid_len, "%s%s", pri->privateprefix, callingnum);
6679 + break;
6680 + case PRI_UNKNOWN:
6681 + snprintf(callerid, callerid_len, "%s%s", pri->unknownprefix, callingnum);
6682 + break;
6683 + default:
6684 + snprintf(callerid, callerid_len, "%s", callingnum);
6685 + break;
6686 + }
6687 +}
6688 +
6689 static void *pri_dchannel(void *vpri)
6690 {
6691 struct zt_pri *pri = vpri;
6692 @@ -8104,6 +8410,8 @@
6693 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
6694 activeidles++;
6695 }
6696 + // 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);
6697 +
6698 #if 0
6699 printf("nextidle: %d, haveidles: %d, minunsed: %d\n",
6700 nextidle, haveidles, minunused);
6701 @@ -8205,9 +8513,36 @@
6702 if (x == ZT_EVENT_ALARM) {
6703 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
6704 pri_find_dchan(pri);
6705 + if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
6706 + if (pri->pri) {
6707 + ast_log(LOG_NOTICE, "pri_shutdown\n");
6708 + for (i=0; i<pri->numchans; i++) {
6709 + struct zt_pvt *p = pri->pvts[i];
6710 + if (p) {
6711 + if (p->call) {
6712 + if (p->pri && p->pri->pri) {
6713 + pri_destroycall(p->pri->pri, p->call);
6714 + p->call = NULL;
6715 + p->tei = -1;
6716 + } else
6717 + ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
6718 + }
6719 + if (p->owner)
6720 + p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
6721 + p->inalarm = 1;
6722 + }
6723 + }
6724 + pri_shutdown(pri->pri);
6725 + }
6726 + }
6727 } else if (x == ZT_EVENT_NOALARM) {
6728 - pri->dchanavail[which] |= DCHAN_NOTINALARM;
6729 - pri_restart(pri->dchans[which]);
6730 + if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
6731 + pri->dchanavail[which] |= DCHAN_NOTINALARM;
6732 + pri->dchanavail[which] |= DCHAN_UP;
6733 + } else {
6734 + pri->dchanavail[which] |= DCHAN_NOTINALARM;
6735 + pri_restart(pri->dchans[which]);
6736 + }
6737 }
6738
6739 if (option_debug)
6740 @@ -8219,8 +8554,7 @@
6741 break;
6742 }
6743 } else if (errno != EINTR)
6744 - ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
6745 -
6746 + ast_log(LOG_WARNING, "pri_event returned error %d (%s) on span %d\n", errno, strerror(errno), pri->span);
6747 if (e) {
6748 if (pri->debug)
6749 pri_dump_event(pri->dchans[which], e);
6750 @@ -8228,32 +8562,101 @@
6751 pri->dchanavail[which] |= DCHAN_UP;
6752 switch(e->e) {
6753 case PRI_EVENT_DCHAN_UP:
6754 - if (option_verbose > 1)
6755 - ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
6756 - pri->dchanavail[which] |= DCHAN_UP;
6757 - if (!pri->pri) pri_find_dchan(pri);
6758 -
6759 - /* Note presense of D-channel */
6760 - time(&pri->lastreset);
6761 -
6762 - /* Restart in 5 seconds */
6763 - if (pri->resetinterval > -1) {
6764 - pri->lastreset -= pri->resetinterval;
6765 - pri->lastreset += 5;
6766 - }
6767 - pri->resetting = 0;
6768 - /* Take the channels from inalarm condition */
6769 - for (i=0; i<pri->numchans; i++)
6770 - if (pri->pvts[i]) {
6771 - pri->pvts[i]->inalarm = 0;
6772 - }
6773 + if (pri->nodetype == BRI_NETWORK_PTMP) {
6774 + if (option_verbose > 3)
6775 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
6776 + pri->dchanavail[which] |= (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP);
6777 + pri_find_dchan(pri);
6778 +
6779 + /* Note presense of D-channel */
6780 + time(&pri->lastreset);
6781 +
6782 + pri->resetting = 0;
6783 + /* Take the channels from inalarm condition */
6784 + for (i=0; i<pri->numchans; i++)
6785 + if (pri->pvts[i]) {
6786 + pri->pvts[i]->inalarm = 0;
6787 + }
6788 + } else {
6789 + if (pri->nodetype == BRI_CPE_PTMP) {
6790 + if (option_verbose > 3)
6791 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
6792 + } else {
6793 + if (option_verbose > 1)
6794 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
6795 + }
6796 + pri->dchanavail[which] |= (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP);
6797 + pri_find_dchan(pri);
6798 +
6799 + /* Note presense of D-channel */
6800 + time(&pri->lastreset);
6801 +
6802 + /* Restart in 5 seconds */
6803 + pri->lastreset -= pri->resetinterval;
6804 + pri->lastreset += 5;
6805 + pri->resetting = 0;
6806 + /* Take the channels from inalarm condition */
6807 + for (i=0; i<pri->numchans; i++) {
6808 + struct zt_pvt *p = pri->pvts[i];
6809 + if (p) {
6810 + p->inalarm = 0;
6811 + /* hang up calls that are not bridged yet, dont touch bridged calls */
6812 + if (p->call) {
6813 + if (p->pri && p->pri->pri) {
6814 + if (p->owner) {
6815 + if (p->owner->_state != AST_STATE_UP) {
6816 + p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
6817 + pri_destroycall(p->pri->pri, p->call);
6818 + }
6819 + } else {
6820 + pri_destroycall(p->pri->pri, p->call);
6821 + }
6822 + p->call = NULL;
6823 + }
6824 + }
6825 + }
6826 + }
6827 + }
6828 break;
6829 case PRI_EVENT_DCHAN_DOWN:
6830 - if (option_verbose > 1)
6831 - ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
6832 - pri->dchanavail[which] &= ~DCHAN_UP;
6833 - pri_find_dchan(pri);
6834 - if (!pri_is_up(pri)) {
6835 + if (pri->nodetype == BRI_NETWORK_PTMP) {
6836 + if (option_verbose > 3)
6837 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
6838 + // PTMP BRIs have N dchans, handled by libpri
6839 + if (e->gen.tei == 0) break;
6840 + /* Hangup active channels */
6841 + for (i=0; i<pri->numchans; i++) {
6842 + struct zt_pvt *p = pri->pvts[i];
6843 + if (p) {
6844 + // ast_log(LOG_NOTICE, "chan %d tei %d\n",i,p->tei);
6845 + if (p->tei == e->gen.tei) {
6846 + if (p->call) {
6847 + if (p->pri && p->pri->pri) {
6848 + pri_hangup(p->pri->pri, p->call, -1);
6849 + pri_destroycall(p->pri->pri, p->call);
6850 + p->tei = -1;
6851 + p->call = NULL;
6852 + } else
6853 + ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
6854 + }
6855 + if (p->owner)
6856 + p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
6857 + p->inalarm = 1;
6858 + p->tei = -1;
6859 + }
6860 + }
6861 + }
6862 + } else {
6863 + if (pri->nodetype == BRI_CPE_PTMP) {
6864 + if (option_verbose > 3)
6865 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
6866 + } else {
6867 + if (option_verbose > 1)
6868 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
6869 + }
6870 + pri->dchanavail[which] &= ~DCHAN_UP;
6871 + pri_find_dchan(pri);
6872 + if (!pri_is_up(pri)) {
6873 pri->resetting = 0;
6874 /* Hangup active channels and put them in alarm mode */
6875 for (i=0; i<pri->numchans; i++) {
6876 @@ -8261,7 +8664,7 @@
6877 if (p) {
6878 if (p->call) {
6879 if (p->pri && p->pri->pri) {
6880 - pri_hangup(p->pri->pri, p->call, -1);
6881 + // pri_hangup(p->pri->pri, p->call, -1);
6882 pri_destroycall(p->pri->pri, p->call);
6883 p->call = NULL;
6884 } else
6885 @@ -8274,6 +8677,7 @@
6886 p->inalarm = 1;
6887 }
6888 }
6889 + }
6890 }
6891 break;
6892 case PRI_EVENT_RESTART:
6893 @@ -8308,8 +8712,8 @@
6894 pri_destroycall(pri->pri, pri->pvts[x]->call);
6895 pri->pvts[x]->call = NULL;
6896 }
6897 - if (pri->pvts[chanpos]->realcall)
6898 - pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
6899 + if (pri->pvts[x]->realcall)
6900 + pri_hangup_all(pri->pvts[x]->realcall, pri);
6901 else if (pri->pvts[x]->owner)
6902 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
6903 ast_mutex_unlock(&pri->pvts[x]->lock);
6904 @@ -8343,7 +8747,6 @@
6905 }
6906 }
6907 break;
6908 -
6909 case PRI_EVENT_INFO_RECEIVED:
6910 chanpos = pri_find_principle(pri, e->ring.channel);
6911 if (chanpos < 0) {
6912 @@ -8352,9 +8755,11 @@
6913 } else {
6914 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
6915 if (chanpos > -1) {
6916 +// ast_log(LOG_NOTICE, "INFO received on channel %d/%d span %d\n",
6917 +// PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
6918 ast_mutex_lock(&pri->pvts[chanpos]->lock);
6919 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
6920 - if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
6921 + if (pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
6922 /* how to do that */
6923 int digitlen = strlen(e->ring.callednum);
6924 char digit;
6925 @@ -8366,6 +8771,14 @@
6926 zap_queue_frame(pri->pvts[chanpos], &f, pri);
6927 }
6928 }
6929 + if (!pri->overlapdial) {
6930 + strncat(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
6931 + if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
6932 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
6933 + } else {
6934 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
6935 + }
6936 + }
6937 }
6938 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
6939 }
6940 @@ -8373,39 +8786,55 @@
6941 break;
6942 case PRI_EVENT_RING:
6943 crv = NULL;
6944 - if (e->ring.channel == -1)
6945 + if (e->ring.channel == -1) {
6946 + /* if no channel specified find one empty */
6947 chanpos = pri_find_empty_chan(pri, 1);
6948 - else
6949 + } else {
6950 chanpos = pri_find_principle(pri, e->ring.channel);
6951 - /* if no channel specified find one empty */
6952 + }
6953 if (chanpos < 0) {
6954 - ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
6955 - PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
6956 + /* no channel specified and no free channel. this is a callwating SETUP */
6957 + if (e->ring.channel == -1) {
6958 + if (option_verbose > 2)
6959 + 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);
6960 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_USER_BUSY);
6961 + break;
6962 + }
6963 } else {
6964 + /* ok, we got a b channel for this call, lock it */
6965 ast_mutex_lock(&pri->pvts[chanpos]->lock);
6966 if (pri->pvts[chanpos]->owner) {
6967 - if (pri->pvts[chanpos]->call == e->ring.call) {
6968 - ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
6969 - PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
6970 - break;
6971 - } else {
6972 - ast_log(LOG_WARNING, "Ring requested on channel %d/%d already in use on span %d. Hanging up owner.\n",
6973 + /* safety check, for messed up retransmissions? */
6974 + if (pri->pvts[chanpos]->call == e->ring.call) {
6975 + ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
6976 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
6977 - if (pri->pvts[chanpos]->realcall)
6978 - pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
6979 - else
6980 - pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
6981 - ast_mutex_unlock(&pri->pvts[chanpos]->lock);
6982 - chanpos = -1;
6983 - }
6984 - }
6985 - if (chanpos > -1)
6986 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
6987 + chanpos = -1;
6988 + break;
6989 + } else {
6990 + ast_log(LOG_WARNING, "Ring requested on channel %d/%d already in use on span %d. Hanging up owner.\n",
6991 + PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
6992 + if (pri->pvts[chanpos]->realcall)
6993 + pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
6994 + else
6995 + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
6996 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
6997 + chanpos = -1;
6998 + break;
6999 + }
7000 + }
7001 + if (chanpos > -1) {
7002 + /* everything is ok with the b channel */
7003 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7004 + }
7005 }
7006 - if ((chanpos < 0) && (e->ring.flexible))
7007 - chanpos = pri_find_empty_chan(pri, 1);
7008 + /* actually, we already got a valid channel by now */
7009 if (chanpos > -1) {
7010 ast_mutex_lock(&pri->pvts[chanpos]->lock);
7011 + /* dont detect dtmfs before the signalling is done */
7012 + disable_dtmf_detect(pri->pvts[chanpos]);
7013 + /* this channel is owned by this TEI */
7014 + pri->pvts[chanpos]->tei = e->ring.tei;
7015 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
7016 /* Should be safe to lock CRV AFAIK while bearer is still locked */
7017 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
7018 @@ -8426,6 +8855,7 @@
7019 break;
7020 }
7021 }
7022 + /* assign call to b channel */
7023 pri->pvts[chanpos]->call = e->ring.call;
7024 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
7025 if (pri->pvts[chanpos]->use_callerid) {
7026 @@ -8450,29 +8880,78 @@
7027 }
7028 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
7029 e->ring.redirectingnum, e->ring.callingplanrdnis);
7030 + /* get callingpres */
7031 + pri->pvts[chanpos]->cid_pres = e->ring.callingpres;
7032 + switch (e->ring.callingpres) {
7033 + case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
7034 + case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
7035 + case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
7036 + case PRES_PROHIB_NETWORK_NUMBER:
7037 + strncpy(pri->pvts[chanpos]->cid_name, pri->withheldcid, sizeof(pri->pvts[chanpos]->cid_name));
7038 + break;
7039 + case PRES_NUMBER_NOT_AVAILABLE:
7040 + strncpy(pri->pvts[chanpos]->cid_name, pri->nocid, sizeof(pri->pvts[chanpos]->cid_name));
7041 + break;
7042 + }
7043 /* If immediate=yes go to s|1 */
7044 if (pri->pvts[chanpos]->immediate) {
7045 if (option_verbose > 2)
7046 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
7047 pri->pvts[chanpos]->exten[0] = 's';
7048 pri->pvts[chanpos]->exten[1] = '\0';
7049 - }
7050 - /* Get called number */
7051 - else if (!ast_strlen_zero(e->ring.callednum)) {
7052 - ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
7053 - ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
7054 - } else
7055 - pri->pvts[chanpos]->exten[0] = '\0';
7056 - /* Set DNID on all incoming calls -- even immediate */
7057 - if (!ast_strlen_zero(e->ring.callednum))
7058 - ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
7059 - /* No number yet, but received "sending complete"? */
7060 - if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
7061 + } else if (ast_strlen_zero(e->ring.callednum)) {
7062 + /* called party number is empty */
7063 + if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
7064 + if (!pri->overlapdial) {
7065 + // be able to set digittimeout for BRI phones
7066 + pri->pvts[chanpos]->exten[0] = 's';
7067 + pri->pvts[chanpos]->exten[1] = '\0';
7068 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
7069 + } else {
7070 + pri->pvts[chanpos]->exten[0] = '\0';
7071 + }
7072 + } else {
7073 + if (pri->nodetype == BRI_CPE) {
7074 + /* fix for .at p2p bri lines */
7075 + pri->pvts[chanpos]->exten[0] = 's';
7076 + pri->pvts[chanpos]->exten[1] = '\0';
7077 + } else {
7078 + pri->pvts[chanpos]->exten[0] = '\0';
7079 + }
7080 + }
7081 + /* No number yet, but received "sending complete"? */
7082 + if (e->ring.complete) {
7083 if (option_verbose > 2)
7084 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
7085 pri->pvts[chanpos]->exten[0] = 's';
7086 pri->pvts[chanpos]->exten[1] = '\0';
7087 - }
7088 + }
7089 + } else {
7090 + /* Get called number */
7091 + 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);
7092 + 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);
7093 + if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
7094 + /* if we get the next digit we should stop the dialtone */
7095 + if (!pri->overlapdial) {
7096 + // with overlapdial=no the exten is always prefixed by "s"
7097 + if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
7098 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
7099 + } else {
7100 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
7101 + }
7102 + } else {
7103 + if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten)) {
7104 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
7105 + } else {
7106 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
7107 + }
7108 + }
7109 + }
7110 + }
7111 + /* Part 3: create channel, setup audio... */
7112 + /* Set DNID on all incoming calls -- even immediate */
7113 + if (!ast_strlen_zero(e->ring.callednum))
7114 + strncpy(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid) - 1);
7115 /* Make sure extension exists (or in overlap dial mode, can exist) */
7116 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
7117 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
7118 @@ -8491,22 +8970,38 @@
7119 res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
7120 if (res < 0)
7121 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
7122 - res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
7123 + if (IS_DIGITAL(e->ring.ctype)) {
7124 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[chanpos]->law);
7125 + } else {
7126 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
7127 + }
7128 if (res < 0)
7129 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
7130 - if (e->ring.complete || !pri->overlapdial)
7131 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
7132 + if (e->ring.complete || !pri->overlapdial) {
7133 /* Just announce proceeding */
7134 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
7135 - else {
7136 + // pri->pvts[chanpos]->ignoredtmf = 0;
7137 + } else {
7138 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
7139 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
7140 else
7141 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
7142 + }
7143 + } else {
7144 + /* BRI_NETWORK | BRI_NETWORK_PTMP */
7145 + if (pri->overlapdial || (!strcasecmp(pri->pvts[chanpos]->exten, "s"))) {
7146 + /* send a SETUP_ACKNOWLEDGE */
7147 + pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
7148 + } else {
7149 + /* send an ALERTING ??? wtf */
7150 + // pri_acknowledge(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
7151 + pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
7152 + }
7153 }
7154 - /* Get the use_callingpres state */
7155 - pri->pvts[chanpos]->callingpres = e->ring.callingpres;
7156 -
7157 - /* Start PBX */
7158 +
7159 + /* overlapdial = yes and the extension can be valid */
7160 +
7161 if (pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
7162 /* Release the PRI lock while we create the channel */
7163 ast_mutex_unlock(&pri->lock);
7164 @@ -8518,10 +9013,21 @@
7165 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
7166 } else {
7167 c = zt_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
7168 + zt_enable_ec(pri->pvts[chanpos]);
7169 }
7170 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
7171 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
7172 }
7173 + if (!ast_strlen_zero(e->ring.callingnum)) {
7174 + char tmpstr[256];
7175 + pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
7176 + pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
7177 + }
7178 + if (!ast_strlen_zero(e->ring.callingani)) {
7179 + char tmpstr[256];
7180 + pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
7181 + pbx_builtin_setvar_helper(c, "PRI_USER_CID", e->ring.callednum);
7182 + }
7183 if(e->ring.ani2 >= 0) {
7184 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
7185 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
7186 @@ -8541,8 +9047,8 @@
7187 ast_mutex_lock(&pri->lock);
7188 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
7189 if (option_verbose > 2)
7190 - ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
7191 - plancallingnum, !ast_strlen_zero(pri->pvts[chanpos]->exten) ? pri->pvts[chanpos]->exten : "<unspecified>",
7192 + ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap %s call from '%s' to '%s' on channel %d/%d, span %d\n",
7193 + pri->pvts[chanpos]->digital ? "data" : "voice", plancallingnum, !ast_strlen_zero(pri->pvts[chanpos]->exten) ? pri->pvts[chanpos]->exten : "<unspecified>",
7194 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
7195 } else {
7196 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
7197 @@ -8555,6 +9061,7 @@
7198 }
7199 }
7200 } else {
7201 + /* overlapdial = no */
7202 ast_mutex_unlock(&pri->lock);
7203 /* Release PRI lock while we create the channel */
7204 c = zt_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
7205 @@ -8578,10 +9085,26 @@
7206 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
7207 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
7208 if (option_verbose > 2)
7209 - ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
7210 - plancallingnum, pri->pvts[chanpos]->exten,
7211 + ast_verbose(VERBOSE_PREFIX_3 "Accepting %s call from '%s' to '%s' on channel %d/%d, span %d\n",
7212 + pri->pvts[chanpos]->digital ? "data" : "voice", e->ring.callingnum, pri->pvts[chanpos]->exten,
7213 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
7214 zt_enable_ec(pri->pvts[chanpos]);
7215 + if(!ast_strlen_zero(e->ring.callingsubaddr)) {
7216 + pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
7217 + }
7218 + if (!ast_strlen_zero(e->ring.callingnum)) {
7219 + char tmpstr[256];
7220 + pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
7221 + pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
7222 + }
7223 + if (!ast_strlen_zero(e->ring.callingani)) {
7224 + char tmpstr[256];
7225 + pri_make_callerid(pri, tmpstr,sizeof(tmpstr), e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
7226 + pbx_builtin_setvar_helper(c, "PRI_USER_CID", e->ring.callednum);
7227 + }
7228 + if (!ast_strlen_zero(e->ring.useruserinfo)) {
7229 + pbx_builtin_setvar_helper(c, "UUI", e->ring.useruserinfo);
7230 + }
7231 } else {
7232 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
7233 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
7234 @@ -8590,6 +9113,7 @@
7235 }
7236 }
7237 } else {
7238 + /* invalid extension */
7239 if (option_verbose > 2)
7240 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
7241 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
7242 @@ -8620,7 +9144,7 @@
7243 } else {
7244 ast_mutex_lock(&pri->pvts[chanpos]->lock);
7245 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
7246 - zt_enable_ec(pri->pvts[chanpos]);
7247 + // XXX zt_enable_ec(pri->pvts[chanpos]);
7248 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
7249 pri->pvts[chanpos]->alerting = 1;
7250 } else
7251 @@ -8649,9 +9173,15 @@
7252 }
7253 break;
7254 case PRI_EVENT_PROGRESS:
7255 - /* Get chan value if e->e is not PRI_EVNT_RINGING */
7256 + /* Get chan value if e->e is not PRI_EVENT_RINGING */
7257 chanpos = pri_find_principle(pri, e->proceeding.channel);
7258 if (chanpos > -1) {
7259 + if ((pri->pvts[chanpos]->priindication_oob == 2) && (e->proceeding.cause == PRI_CAUSE_USER_BUSY)) {
7260 + /* received PROGRESS with cause BUSY, no inband callprogress wanted => hang up! */
7261 + if (pri->pvts[chanpos]->owner) {
7262 + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7263 + }
7264 + } else {
7265 #ifdef PRI_PROGRESS_MASK
7266 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
7267 #else
7268 @@ -8698,6 +9228,12 @@
7269 case PRI_EVENT_PROCEEDING:
7270 chanpos = pri_find_principle(pri, e->proceeding.channel);
7271 if (chanpos > -1) {
7272 + chanpos = pri_fixup_principle(pri, chanpos, e->proceeding.call);
7273 + if (chanpos < 0) {
7274 + ast_log(LOG_WARNING, "Received PROCEEDING on channel %d/%d not in use on span %d\n",
7275 + PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), pri->span);
7276 + chanpos = -1;
7277 + } else {
7278 if (!pri->pvts[chanpos]->proceeding) {
7279 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
7280
7281 @@ -8748,6 +9284,295 @@
7282 }
7283 }
7284 break;
7285 + case PRI_EVENT_SUSPEND_REQ:
7286 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
7287 + pri_suspend_reject(pri->pri, e->suspend_req.call, "");
7288 + break;
7289 + }
7290 + chanpos = pri_find_principle(pri, e->suspend_req.channel);
7291 + if (chanpos < 0) {
7292 + ast_log(LOG_WARNING, "Suspend requested on unconfigured channel %d span %d\n", chanpos, pri->span);
7293 + chanpos = -1;
7294 + }
7295 +
7296 + if (chanpos > -1) {
7297 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
7298 + if (pri->pvts[chanpos]->owner) {
7299 + if (ast_bridged_channel(pri->pvts[chanpos]->owner)) {
7300 + struct zt_suspended_call *zpc;
7301 + char tmpstr[256];
7302 + zpc = malloc(sizeof(struct zt_suspended_call));
7303 + if (!zpc) {
7304 + ast_log(LOG_ERROR, "unable to malloc zt_suspended_call\n");
7305 + break;
7306 + }
7307 + strncpy(zpc->msn, pri->pvts[chanpos]->cid_num, sizeof(zpc->msn));
7308 + strncpy(zpc->callid, e->suspend_req.callid, sizeof(zpc->callid));
7309 + ast_masq_park_call(ast_bridged_channel(pri->pvts[chanpos]->owner), NULL, 0, &zpc->parked_at);
7310 + zpc->next = pri->suspended_calls;
7311 + pri->suspended_calls = zpc;
7312 + snprintf(tmpstr, sizeof(tmpstr), "Parked at %d", zpc->parked_at);
7313 + pri_suspend_acknowledge(pri->pri, e->suspend_req.call,tmpstr);
7314 + pri->pvts[chanpos]->call = NULL;
7315 + pri->pvts[chanpos]->tei = -1;
7316 + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7317 + } else {
7318 + pri_suspend_reject(pri->pri, e->suspend_req.call, "cant park a non-bridge");
7319 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7320 + break;
7321 + }
7322 + } else {
7323 + pri_suspend_reject(pri->pri, e->suspend_req.call, "");
7324 + }
7325 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7326 + }
7327 + break;
7328 + case PRI_EVENT_RESUME_REQ:
7329 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
7330 + break;
7331 + }
7332 + chanpos = pri_find_empty_chan(pri, 1);
7333 + if (chanpos < 0) {
7334 + pri_resume_reject(pri->pri, e->resume_req.call,"All channels busy");
7335 + ast_log(LOG_WARNING, "Resume requested on odd channel number %d span %d\n", chanpos, pri->span);
7336 + chanpos = -1;
7337 + } else if (!pri->pvts[chanpos]) {
7338 + pri_resume_reject(pri->pri, e->resume_req.call,"General protection fault in module 0x0BRI");
7339 + chanpos = -1;
7340 + }
7341 +
7342 + if (chanpos > -1) {
7343 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
7344 + if (!pri->pvts[chanpos]->owner) {
7345 + struct zt_suspended_call *zpc, *zpcl;
7346 + int unparked=0;
7347 + char extenstr[255], temp[255];
7348 + zpc = NULL;
7349 + zpcl = pri->suspended_calls;
7350 + while (zpcl) {
7351 + // ast_log(LOG_NOTICE, "zpc->parked_at %d zpcl->callid %s\n",zpcl->parked_at, zpcl->callid);
7352 + if (((strlen(zpcl->callid) == 0) && (strlen(e->resume_req.callid)==0)) || (!strcmp(zpcl->callid,e->resume_req.callid))) {
7353 + int law;
7354 + // found a parked call
7355 + snprintf(extenstr, sizeof(extenstr), "%d", zpcl->parked_at);
7356 + strncpy(pri->pvts[chanpos]->exten, extenstr, sizeof(pri->pvts[chanpos]->exten));
7357 + // strncpy(pri->pvts[chanpos]->context, ast_parking_con(), sizeof(pri->pvts[chanpos]->context));
7358 + pri->pvts[chanpos]->call = e->resume_req.call;
7359 + law = 1;
7360 + if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
7361 + ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]), law);
7362 + // uhh ohh...what shall we do without the bearer cap???
7363 + law = ZT_LAW_ALAW;
7364 + res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
7365 + if (res < 0)
7366 + ast_log(LOG_WARNING, "Unable to set law on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
7367 + if (!pri->pvts[chanpos]->digital) {
7368 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
7369 + } else {
7370 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[chanpos]->law);
7371 + }
7372 + if (res < 0)
7373 + ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
7374 + /* Start PBX */
7375 + c = zt_new(pri->pvts[chanpos], AST_STATE_UP, 1, SUB_REAL, law, PRI_TRANS_CAP_SPEECH);
7376 + if (c) {
7377 + pri->pvts[chanpos]->owner = c;
7378 + pri->pvts[chanpos]->call = e->resume_req.call;
7379 + zt_enable_ec(pri->pvts[chanpos]);
7380 + zt_train_ec(pri->pvts[chanpos]);
7381 + } else {
7382 + ast_log(LOG_ERROR, "unable to start pbx\n");
7383 + }
7384 +
7385 + if (zpc) {
7386 + zpc->next = zpcl->next;
7387 + free(zpcl);
7388 + zpcl = zpc->next;
7389 + } else {
7390 + // remove head
7391 + pri->suspended_calls = zpcl->next;
7392 + free(zpcl);
7393 + zpcl = pri->suspended_calls;
7394 + zpc = NULL;
7395 + }
7396 + unparked = 1;
7397 + snprintf(temp, sizeof(temp), "Unparked %s", extenstr);
7398 + pri_resume_acknowledge(pri->pri, e->resume_req.call, chanpos + 1, temp);
7399 + break;
7400 + }
7401 + zpc = zpcl;
7402 + if (zpcl) zpcl = zpcl->next;
7403 + }
7404 + if (!unparked)
7405 + pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
7406 + } else {
7407 + pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
7408 + }
7409 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7410 + }
7411 + break;
7412 + case PRI_EVENT_HOLD_REQ:
7413 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
7414 + pri_hold_reject(pri->pri, e->hold_req.call);
7415 + break;
7416 + }
7417 + chanpos = pri_find_principle(pri, e->hold_req.channel);
7418 + if (chanpos < 0) {
7419 + ast_log(LOG_WARNING, "Hold requested on unconfigured channel %d span %d\n", chanpos, pri->span);
7420 + chanpos = -1;
7421 + }
7422 + if (chanpos > -1) {
7423 + // ast_log(LOG_NOTICE, "Hold request for channel number %d span %d\n", chanpos, pri->span);
7424 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
7425 + if (pri->pvts[chanpos]->owner) {
7426 + struct zt_pvt *p = pri->pvts[chanpos];
7427 + struct zt_holded_call *zhc;
7428 + int holdacked=0;
7429 +
7430 +// ast_log(LOG_NOTICE,"HOLD request from channel %s tei %d\n",p->owner->name, e->hold_req.tei);
7431 + if (ast_bridged_channel(p->owner)) {
7432 + zhc = malloc(sizeof(struct zt_holded_call));
7433 + if (!zhc) {
7434 + ast_log(LOG_ERROR, "unable to malloc zt_holded_call\n");
7435 + break;
7436 + }
7437 + memset(zhc, 0, sizeof(zhc));
7438 + strncpy(zhc->msn, pri->pvts[chanpos]->cid_num, sizeof(zhc->msn));
7439 + strncpy(zhc->uniqueid, ast_bridged_channel(p->owner)->uniqueid, sizeof(zhc->uniqueid));
7440 + zhc->tei = e->hold_req.tei;
7441 + zhc->cref = e->hold_req.cref;
7442 + zhc->call = e->hold_req.call;
7443 + zhc->channel = p->owner;
7444 + zhc->alreadyhungup = 0;
7445 + zhc->bridge = ast_bridged_channel(p->owner);
7446 + zhc->next = pri->holded_calls;
7447 + pri->holded_calls = zhc;
7448 +
7449 + /* put channel on hold */
7450 + ast_masq_hold_call(ast_bridged_channel(p->owner), p->owner);
7451 +
7452 + pri_hold_acknowledge(pri->pri, e->hold_req.call);
7453 + holdacked = 1;
7454 + p->call = NULL; // free the bchannel withouth destroying the call
7455 + p->tei = -1;
7456 + } else {
7457 + // cant hold a non-bridge,...yet
7458 +
7459 + // make a fake channel
7460 +
7461 + // masquerade
7462 +
7463 + // put on hold
7464 + pri_hold_reject(pri->pri, e->hold_req.call);
7465 + }
7466 + } else {
7467 + pri_hold_reject(pri->pri, e->hold_req.call);
7468 + }
7469 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7470 + } else {
7471 + pri_hold_reject(pri->pri, e->hold_req.call);
7472 + }
7473 + break;
7474 + case PRI_EVENT_RETRIEVE_REQ:
7475 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
7476 + pri_retrieve_reject(pri->pri, e->retrieve_req.call);
7477 + break;
7478 + }
7479 + chanpos = pri_find_empty_chan(pri, 1);
7480 + if (chanpos < 0) {
7481 + pri_retrieve_reject(pri->pri, e->retrieve_req.call);
7482 + ast_log(LOG_WARNING, "Retrieve requested on odd channel number %d span %d\n", chanpos, pri->span);
7483 + chanpos = -1;
7484 + break;
7485 + } else if (!pri->pvts[chanpos]) {
7486 + ast_log(LOG_WARNING, "Retrieve requested on unconfigured channel number %d span %d\n", chanpos, pri->span);
7487 + pri_retrieve_reject(pri->pri, e->retrieve_req.call);
7488 + chanpos = -1;
7489 + break;
7490 + }
7491 + if (chanpos > -1) {
7492 + struct zt_holded_call *onhold = NULL;
7493 + int retrieved = 0;
7494 + int res = -1;
7495 + struct app_tmp *tmp;
7496 + pthread_attr_t attr;
7497 + int law;
7498 +
7499 + onhold = pri_get_callonhold(pri, e->retrieve_req.cref, e->retrieve_req.tei);
7500 +
7501 + if (!onhold) {
7502 + pri_retrieve_reject(pri->pri, e->retrieve_req.call);
7503 + break;
7504 + }
7505 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
7506 + // found a parked call
7507 + law = 1;
7508 + if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
7509 + ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]), law);
7510 + // uhh ohh...what shall we do without the bearer cap???
7511 + law = ZT_LAW_ALAW;
7512 + res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
7513 + if (res < 0)
7514 + ast_log(LOG_WARNING, "Unable to set law on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
7515 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
7516 + if (res < 0)
7517 + ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
7518 + /* Start PBX */
7519 + c = zt_new(pri->pvts[chanpos], AST_STATE_UP, 0, SUB_REAL, law, PRI_TRANS_CAP_SPEECH);
7520 + if (c) {
7521 + pri->pvts[chanpos]->owner = c;
7522 + pri->pvts[chanpos]->outgoing = 1; /* for not sending proceedings... */
7523 + pri->pvts[chanpos]->call = e->retrieve_req.call;
7524 + pri->pvts[chanpos]->tei = e->retrieve_req.tei;
7525 + zt_enable_ec(pri->pvts[chanpos]);
7526 + zt_train_ec(pri->pvts[chanpos]);
7527 + } else {
7528 + ast_log(LOG_ERROR, "unable to start pbx\n");
7529 + }
7530 +
7531 + retrieved = 1;
7532 + // 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);
7533 + pri_retrieve_acknowledge(pri->pri, e->retrieve_req.call, chanpos + 1);
7534 +
7535 + // the magic begins here: ....
7536 + tmp = malloc(sizeof(struct app_tmp));
7537 + if (tmp) {
7538 + memset(tmp, 0, sizeof(struct app_tmp));
7539 + strncpy(tmp->app, "holdedcall", sizeof(tmp->app) - 1);
7540 + strncpy(tmp->data, onhold->uniqueid, sizeof(tmp->data) - 1);
7541 + tmp->chan = c;
7542 + }
7543 + pri_destroy_callonhold(pri, onhold);
7544 + onhold = NULL;
7545 +
7546 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7547 + pthread_attr_init(&attr);
7548 + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
7549 + if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
7550 + ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", c->name, strerror(errno));
7551 + free(tmp);
7552 + ast_hangup(c);
7553 + retrieved = 0;
7554 + }
7555 +
7556 + if (!retrieved) {
7557 + pri_retrieve_reject(pri->pri, e->retrieve_req.call);
7558 + }
7559 + }
7560 + break;
7561 + case PRI_EVENT_DISPLAY_RECEIVED:
7562 + ast_log(LOG_NOTICE, "DISPLAY IE: [ %s ] received\n",e->display.text);
7563 + chanpos = pri_find_principle(pri, e->display.channel);
7564 + if (chanpos < 0) {
7565 + ast_log(LOG_WARNING, "odd channel number %d span %d\n", chanpos, pri->span);
7566 + chanpos = -1;
7567 + }
7568 + if (chanpos > -1) {
7569 + if (pri->pvts[chanpos]->owner) {
7570 + // ast_sendtext(pri->pvt[chanpos]->owner, e->display.text);
7571 + }
7572 + }
7573 + break;
7574 case PRI_EVENT_ANSWER:
7575 chanpos = pri_find_principle(pri, e->answer.channel);
7576 if (chanpos < 0) {
7577 @@ -8763,6 +9588,7 @@
7578 chanpos = -1;
7579 } else {
7580 ast_mutex_lock(&pri->pvts[chanpos]->lock);
7581 + pri->pvts[chanpos]->tei = e->answer.tei;
7582 /* Now we can do call progress detection */
7583
7584 /* We changed this so it turns on the DSP no matter what... progress or no progress.
7585 @@ -8792,11 +9618,15 @@
7586 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
7587 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
7588 } else if (pri->pvts[chanpos]->confirmanswer) {
7589 - ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
7590 + ast_log(LOG_DEBUG, "Waiting for answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
7591 } else {
7592 + pri->pvts[chanpos]->dialing = 0;
7593 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
7594 /* Enable echo cancellation if it's not on already */
7595 zt_enable_ec(pri->pvts[chanpos]);
7596 + zt_train_ec(pri->pvts[chanpos]);
7597 + /* stop ignoring inband dtmf */
7598 + enable_dtmf_detect(pri->pvts[chanpos]);
7599 }
7600
7601 #ifdef SUPPORT_USERUSER
7602 @@ -8845,18 +9675,21 @@
7603 }
7604 }
7605 if (option_verbose > 2)
7606 - ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup\n",
7607 - pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
7608 + ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
7609 + pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
7610 } else {
7611 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
7612 pri->pvts[chanpos]->call = NULL;
7613 + pri->pvts[chanpos]->tei = -1;
7614 }
7615 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
7616 - if (option_verbose > 2)
7617 + if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
7618 + if (option_verbose > 2)
7619 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
7620 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
7621 - pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
7622 - pri->pvts[chanpos]->resetting = 1;
7623 + pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
7624 + pri->pvts[chanpos]->resetting = 1;
7625 + }
7626 }
7627 if (e->hangup.aoc_units > -1)
7628 if (option_verbose > 2)
7629 @@ -8871,8 +9704,20 @@
7630
7631 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7632 } else {
7633 - ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
7634 - PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
7635 + struct zt_holded_call *onhold = NULL;
7636 + /* check calls on hold */
7637 + onhold = pri_get_callonhold(pri, e->hangup.cref, e->hangup.tei);
7638 +
7639 + if (onhold) {
7640 + // ast_log(LOG_NOTICE, "hangup, found cref %d, tei %d\n",e->hangup.cref, e->hangup.tei);
7641 + pri_hangup(pri->pri, onhold->call, e->hangup.cause);
7642 + pri_destroy_callonhold(pri, onhold);
7643 + onhold = NULL;
7644 + } else {
7645 + ast_log(LOG_NOTICE, "Hangup, did not find cref %d, tei %d\n",e->hangup.cref, e->hangup.tei);
7646 + ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
7647 + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
7648 + }
7649 }
7650 }
7651 break;
7652 @@ -8882,17 +9727,25 @@
7653 case PRI_EVENT_HANGUP_REQ:
7654 chanpos = pri_find_principle(pri, e->hangup.channel);
7655 if (chanpos < 0) {
7656 - ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
7657 - PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
7658 + if (pri->nodetype == BRI_NETWORK_PTMP) {
7659 + pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
7660 + } else {
7661 + ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
7662 + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
7663 + }
7664 chanpos = -1;
7665 }
7666 - if (chanpos > -1) {
7667 + /* dont hang up if we want to hear inband call progress */
7668 + if ((chanpos > -1) && ((pri->pvts[chanpos]->priindication_oob != 2) || (!e->hangup.inband_progress) || (!pri->pvts[chanpos]->outgoing))){
7669 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
7670 if (chanpos > -1) {
7671 ast_mutex_lock(&pri->pvts[chanpos]->lock);
7672 if (pri->pvts[chanpos]->realcall)
7673 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
7674 else if (pri->pvts[chanpos]->owner) {
7675 + char tmpstr[256];
7676 + snprintf(tmpstr, sizeof(tmpstr), "%d", e->hangup.cause);
7677 + pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "PRI_CAUSE", tmpstr);
7678 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
7679 switch(e->hangup.cause) {
7680 case PRI_CAUSE_USER_BUSY:
7681 @@ -8915,16 +9768,73 @@
7682 if (option_verbose > 2)
7683 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
7684 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
7685 + if (pri->nodetype == BRI_NETWORK_PTMP) {
7686 + // check for bri transfers, not everybody uses ECT...
7687 + if (pri->pvts[chanpos]->owner) {
7688 + // find on hold call
7689 + struct zt_holded_call *onhold = NULL;
7690 + struct ast_channel *transferee = NULL;
7691 + int transfer_ok = 0;
7692 +
7693 + onhold = pri_get_callonhold(pri, -1, e->hangup.tei);
7694 +
7695 + if (onhold) {
7696 + if (pri->pvts[chanpos]->pritransfer == 2) {
7697 + 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))))) {
7698 + transferee = ast_get_holded_call(onhold->uniqueid);
7699 +
7700 + if (transferee) {
7701 + if (pri->pvts[chanpos]->owner->_state == AST_STATE_RINGING) {
7702 + ast_indicate(transferee, AST_CONTROL_RINGING);
7703 + }
7704 +
7705 + pri->pvts[chanpos]->owner->_softhangup &= ~AST_SOFTHANGUP_DEV;
7706 +
7707 + ast_mutex_unlock(&transferee->lock);
7708 + if (ast_channel_masquerade(pri->pvts[chanpos]->owner, transferee)) {
7709 + ast_log(LOG_WARNING, "unable to masquerade\n");
7710 + } else {
7711 + /* beware of zombies!!! */
7712 + ast_set_flag(transferee, AST_FLAG_ZOMBIE);
7713 + pri->pvts[chanpos]->owner = NULL;
7714 + pri->pvts[chanpos]->tei = -1;
7715 + transfer_ok = 1;
7716 + }
7717 + }
7718 + }
7719 + } else if (pri->pvts[chanpos]->pritransfer == 0) {
7720 + ast_log(LOG_NOTICE, "killing channel %s \n", onhold->uniqueid);
7721 + ast_retrieve_call_to_death(onhold->uniqueid);
7722 + transfer_ok = 1;
7723 + } else if (pri->pvts[chanpos]->pritransfer == 1) {
7724 + /* we use ECT transfers, so just ignore this */
7725 + transfer_ok = 0;
7726 + }
7727 +
7728 + if (transfer_ok) {
7729 + onhold->alreadyhungup = 1;
7730 + pri_hangup(pri->pri, onhold->call, e->hangup.cause);
7731 + onhold = NULL;
7732 + }
7733 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7734 + break;
7735 + }
7736 + }
7737 + }
7738 } else {
7739 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
7740 pri->pvts[chanpos]->call = NULL;
7741 + pri->pvts[chanpos]->tei = -1;
7742 }
7743 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
7744 - if (option_verbose > 2)
7745 - ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
7746 - PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
7747 - pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
7748 - pri->pvts[chanpos]->resetting = 1;
7749 + if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
7750 + if (option_verbose > 2)
7751 + ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
7752 + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
7753 + pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
7754 + pri->pvts[chanpos]->resetting = 1;
7755 + }
7756 +
7757 }
7758
7759 #ifdef SUPPORT_USERUSER
7760 @@ -8935,9 +9845,28 @@
7761
7762 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7763 } else {
7764 - 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);
7765 + if (pri->nodetype != BRI_NETWORK_PTMP) {
7766 + 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);
7767 + } else {
7768 + // check holded_calls!!!
7769 + struct zt_holded_call *onhold = NULL;
7770 +
7771 + onhold = pri_get_callonhold(pri, e->hangup.cref, e->hangup.tei);
7772 +
7773 + if (onhold) {
7774 + pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
7775 + ast_retrieve_call_to_death(onhold->uniqueid);
7776 + pri_destroy_callonhold(pri, onhold);
7777 + onhold = NULL;
7778 + } else {
7779 + 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);
7780 + }
7781 + }
7782 }
7783 }
7784 + if ((chanpos > -1) && (pri->pvts[chanpos]->owner) && (pri->pvts[chanpos]->priindication_oob == 2) && (e->hangup.inband_progress) && (pri->pvts[chanpos]->outgoing)) {
7785 + ast_channel_setwhentohangup(pri->pvts[chanpos]->owner, 5);
7786 + }
7787 break;
7788 case PRI_EVENT_HANGUP_ACK:
7789 chanpos = pri_find_principle(pri, e->hangup.channel);
7790 @@ -8951,6 +9880,7 @@
7791 if (chanpos > -1) {
7792 ast_mutex_lock(&pri->pvts[chanpos]->lock);
7793 pri->pvts[chanpos]->call = NULL;
7794 + pri->pvts[chanpos]->tei = -1;
7795 pri->pvts[chanpos]->resetting = 0;
7796 if (pri->pvts[chanpos]->owner) {
7797 if (option_verbose > 2)
7798 @@ -8964,7 +9894,9 @@
7799 #endif
7800
7801 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7802 + }
7803 }
7804 + }
7805 }
7806 break;
7807 case PRI_EVENT_CONFIG_ERR:
7808 @@ -9031,15 +9963,25 @@
7809 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
7810 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
7811 } else {
7812 - ast_mutex_lock(&pri->pvts[chanpos]->lock);
7813 - pri->pvts[chanpos]->setup_ack = 1;
7814 - /* Send any queued digits */
7815 - for (x=0;x<strlen(pri->pvts[chanpos]->dialdest);x++) {
7816 + chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
7817 + if (chanpos < 0) {
7818 + ast_log(LOG_WARNING, "Received SETUP_ACK on channel %d/%d not in use on span %d\n",
7819 + PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
7820 + chanpos = -1;
7821 + } else {
7822 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
7823 + pri->pvts[chanpos]->setup_ack = 1;
7824 + if (pri->pvts[chanpos]->owner) {
7825 + // ast_log(LOG_NOTICE, "SETUP_ACK for '%s'\n", pri->pvts[chanpos]->owner->name);
7826 + }
7827 + /* Send any queued digits */
7828 + for (x=0;x<strlen(pri->pvts[chanpos]->dialdest);x++) {
7829 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
7830 pri_information(pri->pri, pri->pvts[chanpos]->call,
7831 pri->pvts[chanpos]->dialdest[x]);
7832 + }
7833 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7834 }
7835 - ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7836 }
7837 break;
7838 case PRI_EVENT_NOTIFY:
7839 @@ -9063,6 +10005,78 @@
7840 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7841 }
7842 break;
7843 + case PRI_EVENT_FACILITY:
7844 + if (e->facility.operation == 0x06) {
7845 + struct ast_channel *chan = NULL;
7846 + struct zt_holded_call *onhold = NULL;
7847 + if (option_verbose > 2) {
7848 + ast_verbose(VERBOSE_PREFIX_3 "ECT requested by TEI %d for cref %d\n", e->facility.tei, e->facility.cref);
7849 + }
7850 + /* search for cref/tei in held calls */
7851 + onhold = pri_get_callonhold(pri, e->facility.cref, e->facility.tei);
7852 + if (onhold) {
7853 + chan = ast_get_holded_call(onhold->uniqueid);
7854 + onhold->alreadyhungup = 1;
7855 + onhold = NULL;
7856 + if (!chan) {
7857 + /* hang up */
7858 + pri_hangup(pri->pri, e->facility.call, 16);
7859 + break;
7860 + }
7861 + } else {
7862 + /* unknown cref/tei */
7863 + ast_log(LOG_WARNING, "did not find call on hold for cref %d tei %d\n", e->facility.tei, e->facility.cref);
7864 + /* hang up */
7865 + pri_hangup(pri->pri, e->facility.call, 16);
7866 + break;
7867 + }
7868 +
7869 + /* find an active call for the same tei */
7870 + chanpos = pri_find_tei(pri, e->facility.call, e->facility.tei);
7871 + if (chanpos < 0) {
7872 + /* did not find active call, hangup call on hold */
7873 + if (chan) {
7874 + ast_hangup(chan);
7875 + chan = NULL;
7876 + }
7877 + } else {
7878 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
7879 + /* transfer */
7880 + if (pri->pvts[chanpos]->owner) {
7881 + if (option_verbose > 3) {
7882 + ast_verbose(VERBOSE_PREFIX_3 "ECT: found %s on channel %d for tei %d\n", pri->pvts[chanpos]->owner->name ,chanpos, e->facility.tei);
7883 + }
7884 + /* pass callprogress if the channel is not up yet */
7885 + if (pri->pvts[chanpos]->owner->_state == AST_STATE_RINGING) {
7886 + ast_indicate(chan, AST_CONTROL_RINGING);
7887 + }
7888 + /* unlock the channel we removed from hold */
7889 + ast_mutex_unlock(&chan->lock);
7890 + if (ast_channel_masquerade(pri->pvts[chanpos]->owner, chan)) {
7891 + ast_log(LOG_WARNING, "unable to masquerade\n");
7892 + } else {
7893 + /* beware of zombies !!! */
7894 + ast_set_flag(chan, AST_FLAG_ZOMBIE);
7895 + // chan->zombie = 1;
7896 + }
7897 + }
7898 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7899 + }
7900 + /* disconnect */
7901 + pri_hangup(pri->pri, e->facility.call, 16);
7902 + } else if (e->facility.operation == 0x0D) {
7903 + ast_log(LOG_NOTICE, "call deflection to %s requested.\n", e->facility.forwardnum);
7904 + /* mmmmmkay */
7905 +
7906 + /* lock the channel */
7907 +
7908 + /* async goto */
7909 +
7910 + /* disconnect isdn layer */
7911 + } else {
7912 + ast_log(LOG_WARNING, "Unknown facility operation %#x requested.\n", e->facility.operation);
7913 + }
7914 + break;
7915 default:
7916 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
7917 }
7918 @@ -9124,7 +10138,7 @@
7919 pri->fds[i] = -1;
7920 return -1;
7921 }
7922 - pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
7923 + pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype, pri->span);
7924 /* Force overlap dial if we're doing GR-303! */
7925 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
7926 pri->overlapdial = 1;
7927 @@ -9193,39 +10207,77 @@
7928
7929 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
7930 {
7931 - int myfd;
7932 + int myfd, x, d;
7933 + int span;
7934 +
7935 + if (argc < 6)
7936 + return RESULT_SHOWUSAGE;
7937
7938 if (!strncasecmp(argv[1], "set", 3)) {
7939 - if (argc < 5)
7940 + if (argc < 7)
7941 return RESULT_SHOWUSAGE;
7942
7943 - if (ast_strlen_zero(argv[4]))
7944 + if (!argv[4] || ast_strlen_zero(argv[4]))
7945 return RESULT_SHOWUSAGE;
7946
7947 + if (!argv[5])
7948 + return RESULT_SHOWUSAGE;
7949 +
7950 + if (!argv[6] || ast_strlen_zero(argv[6]))
7951 + return RESULT_SHOWUSAGE;
7952 +
7953 + span = atoi(argv[6]);
7954 + if ((span < 1) && (span > NUM_SPANS)) {
7955 + return RESULT_SUCCESS;
7956 + }
7957 +
7958 +
7959 myfd = open(argv[4], O_CREAT|O_WRONLY);
7960 if (myfd < 0) {
7961 - ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
7962 - return RESULT_SUCCESS;
7963 + ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
7964 + return RESULT_SUCCESS;
7965 }
7966 -
7967 - ast_mutex_lock(&pridebugfdlock);
7968 -
7969 - if (pridebugfd >= 0)
7970 - close(pridebugfd);
7971 -
7972 - pridebugfd = myfd;
7973 - ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
7974 -
7975 - ast_mutex_unlock(&pridebugfdlock);
7976 -
7977 - ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
7978 + for (x=0; x < NUM_SPANS; x++) {
7979 + ast_mutex_lock(&pris[x].lock);
7980 +
7981 + if (pris[x].span == span) {
7982 + if (pris[x].debugfd >= 0)
7983 + close(pris[x].debugfd);
7984 + pris[x].debugfd = myfd;
7985 + for (d=0; d < NUM_DCHANS; d++) {
7986 + if (pris[x].dchans[d])
7987 + pri_set_debug_fd(pris[x].dchans[d], myfd);
7988 + }
7989 + }
7990 + ast_mutex_unlock(&pris[x].lock);
7991 + }
7992 +
7993 + ast_cli(fd, "PRI debug output for span %d will be sent to '%s'\n", span, argv[4]);
7994 } else {
7995 + if (!argv[5] || ast_strlen_zero(argv[5]))
7996 + return RESULT_SHOWUSAGE;
7997 /* Assume it is unset */
7998 - ast_mutex_lock(&pridebugfdlock);
7999 - close(pridebugfd);
8000 - pridebugfd = -1;
8001 - ast_cli(fd, "PRI debug output to file disabled\n");
8002 - ast_mutex_unlock(&pridebugfdlock);
8003 + span = atoi(argv[5]);
8004 + if ((span < 1) && (span > NUM_SPANS)) {
8005 + return RESULT_SUCCESS;
8006 + }
8007 +
8008 + for (x=0; x < NUM_SPANS; x++) {
8009 + ast_mutex_lock(&pris[x].lock);
8010 +
8011 + if (pris[x].span == span) {
8012 + if (pris[x].debugfd >= 0)
8013 + close(pris[x].debugfd);
8014 + pris[x].debugfd = -1;
8015 + for (d=0; d < NUM_DCHANS; d++) {
8016 + if (pris[x].dchans[d])
8017 + pri_set_debug_fd(pris[x].dchans[d], -1);
8018 + }
8019 + }
8020 + ast_mutex_unlock(&pris[x].lock);
8021 + }
8022 +
8023 + ast_cli(fd, "PRI debug output to file for span %d disabled\n", span);
8024 }
8025
8026 return RESULT_SUCCESS;
8027 @@ -9257,6 +10309,7 @@
8028
8029
8030
8031 +
8032 static int handle_pri_no_debug(int fd, int argc, char *argv[])
8033 {
8034 int span;
8035 @@ -9363,36 +10416,6 @@
8036 return RESULT_SUCCESS;
8037 }
8038
8039 -static int handle_pri_show_debug(int fd, int argc, char *argv[])
8040 -{
8041 - int x;
8042 - int span;
8043 - int count=0;
8044 - int debug=0;
8045 -
8046 - for(span=0;span<NUM_SPANS;span++) {
8047 - if (pris[span].pri) {
8048 - for(x=0;x<NUM_DCHANS;x++) {
8049 - debug=0;
8050 - if (pris[span].dchans[x]) {
8051 - debug = pri_get_debug(pris[span].dchans[x]);
8052 - 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" );
8053 - count++;
8054 - }
8055 - }
8056 - }
8057 -
8058 - }
8059 - ast_mutex_lock(&pridebugfdlock);
8060 - if (pridebugfd >= 0)
8061 - ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
8062 - ast_mutex_unlock(&pridebugfdlock);
8063 -
8064 - if (!count)
8065 - ast_cli(fd, "No debug set or no PRI running\n");
8066 - return RESULT_SUCCESS;
8067 -}
8068 -
8069 static char pri_debug_help[] =
8070 "Usage: pri debug span <span>\n"
8071 " Enables debugging on a given PRI span\n";
8072 @@ -9409,6 +10432,18 @@
8073 "Usage: pri show span <span>\n"
8074 " Displays PRI Information\n";
8075
8076 +static char bri_debug_help[] =
8077 + "Usage: bri debug span <span>\n"
8078 + " Enables debugging on a given BRI span\n";
8079 +
8080 +static char bri_no_debug_help[] =
8081 + "Usage: bri no debug span <span>\n"
8082 + " Disables debugging on a given BRI span\n";
8083 +
8084 +static char bri_really_debug_help[] =
8085 + "Usage: bri intensive debug span <span>\n"
8086 + " Enables debugging down to the Q.921 level\n";
8087 +
8088 static struct ast_cli_entry zap_pri_cli[] = {
8089 { { "pri", "debug", "span", NULL }, handle_pri_debug,
8090 "Enables PRI debugging on a span", pri_debug_help, complete_span_4 },
8091 @@ -9416,19 +10451,77 @@
8092 "Disables PRI debugging on a span", pri_no_debug_help, complete_span_5 },
8093 { { "pri", "intense", "debug", "span", NULL }, handle_pri_really_debug,
8094 "Enables REALLY INTENSE PRI debugging", pri_really_debug_help, complete_span_5 },
8095 + { { "bri", "debug", "span", NULL }, handle_pri_debug,
8096 + "Enables BRI debugging on a span", bri_debug_help, complete_span_4 },
8097 + { { "bri", "no", "debug", "span", NULL }, handle_pri_no_debug,
8098 + "Disables BRI debugging on a span", bri_no_debug_help, complete_span_5 },
8099 + { { "bri", "intense", "debug", "span", NULL }, handle_pri_really_debug,
8100 + "Enables REALLY INTENSE BRI debugging", bri_really_debug_help, complete_span_5 },
8101 { { "pri", "show", "span", NULL }, handle_pri_show_span,
8102 "Displays PRI Information", pri_show_span_help, complete_span_4 },
8103 - { { "pri", "show", "debug", NULL }, handle_pri_show_debug,
8104 - "Displays current PRI debug settings" },
8105 { { "pri", "set", "debug", "file", NULL }, handle_pri_set_debug_file,
8106 "Sends PRI debug output to the specified file" },
8107 - { { "pri", "unset", "debug", "file", NULL }, handle_pri_set_debug_file,
8108 + { { "pri", "unset", "debug", "file", "span", NULL }, handle_pri_set_debug_file,
8109 "Ends PRI debug output to file" },
8110 };
8111
8112 +static int app_zapCD(struct ast_channel *chan, void *data)
8113 +{
8114 + struct zt_pvt *p = chan->tech_pvt;
8115 +
8116 + if(!data) {
8117 + ast_log(LOG_WARNING, "zapCD wants a number to deflect to\n");
8118 + return -1;
8119 + }
8120 + return pri_deflect(p->pri->pri, p->call, data);
8121 +}
8122 +
8123 +static char *zapCD_tdesc = "Call Deflection";
8124 +static char *zapCD_app = "zapCD";
8125 +static char *zapCD_synopsis = "Call Deflection";
8126 #endif /* ZAPATA_PRI */
8127
8128
8129 +static int app_zapEC(struct ast_channel *chan, void *data)
8130 +{
8131 + int res=-1;
8132 + struct zt_pvt *p = NULL;
8133 +
8134 + if (!data) {
8135 + ast_log(LOG_WARNING, "zapEC requires one argument (on | off)\n");
8136 + }
8137 + if (chan && !strcasecmp("ZAP",chan->type)) {
8138 + p = chan->tech_pvt;
8139 + if (!p) return res;
8140 + if (!strcasecmp("on",(char *)data)) {
8141 + zt_enable_ec(p);
8142 + res = 0;
8143 + if (option_verbose > 3) {
8144 + ast_verbose(VERBOSE_PREFIX_3 "Enabled echo cancelation on channel %s.\n", chan->name);
8145 + }
8146 + } else if (!strcasecmp("off",(char *)data)) {
8147 + zt_disable_ec(p);
8148 + res = 0;
8149 + if (option_verbose > 3) {
8150 + ast_verbose(VERBOSE_PREFIX_3 "Disabled echo cancelation on channel %s.\n", chan->name);
8151 + }
8152 + } else {
8153 + ast_log(LOG_WARNING, "Unknown argument %s to zapEC\n", (char *)data);
8154 + }
8155 + } else {
8156 + ast_log(LOG_WARNING, "zapNoEC only works on ZAP channels, check your extensions.conf!\n");
8157 + res = 0;
8158 + }
8159 +
8160 + return res;
8161 +}
8162 +
8163 +static char *zapEC_tdesc = "Enable/disable Echo cancelation";
8164 +static char *zapEC_app = "zapEC";
8165 +static char *zapEC_synopsis = "Enable/Disable Echo Cancelation on a Zap channel";
8166 +
8167 +
8168 +
8169 #ifdef ZAPATA_R2
8170 static int handle_r2_no_debug(int fd, int argc, char *argv[])
8171 {
8172 @@ -10051,6 +11144,7 @@
8173 ast_manager_unregister( "ZapDNDoff" );
8174 ast_manager_unregister( "ZapDNDon" );
8175 ast_manager_unregister("ZapShowChannels");
8176 + ast_unregister_application(zapEC_app);
8177 ast_channel_unregister(&zap_tech);
8178 if (!ast_mutex_lock(&iflock)) {
8179 /* Hangup all interfaces if they have an owner */
8180 @@ -10409,8 +11503,8 @@
8181 }
8182 } else if (!strcasecmp(v->name, "echotraining")) {
8183 if (sscanf(v->value, "%d", &y) == 1) {
8184 - if ((y < 10) || (y > 4000)) {
8185 - ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 2000 ms at line %d\n", v->lineno);
8186 + if ((y < 10) || (y > 1000)) {
8187 + ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 1000 ms at line %d\n", v->lineno);
8188 } else {
8189 echotraining = y;
8190 }
8191 @@ -10596,6 +11690,22 @@
8192 cur_signalling = SIG_GR303FXSKS;
8193 cur_radio = 0;
8194 pritype = PRI_CPE;
8195 + } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
8196 + cur_radio = 0;
8197 + cur_signalling = SIG_PRI;
8198 + pritype = BRI_NETWORK_PTMP;
8199 + } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
8200 + cur_signalling = SIG_PRI;
8201 + cur_radio = 0;
8202 + pritype = BRI_CPE_PTMP;
8203 + } else if (!strcasecmp(v->value, "bri_net")) {
8204 + cur_radio = 0;
8205 + cur_signalling = SIG_PRI;
8206 + pritype = BRI_NETWORK;
8207 + } else if (!strcasecmp(v->value, "bri_cpe")) {
8208 + cur_signalling = SIG_PRI;
8209 + cur_radio = 0;
8210 + pritype = BRI_CPE;
8211 #endif
8212 #ifdef ZAPATA_R2
8213 } else if (!strcasecmp(v->value, "r2")) {
8214 @@ -10684,8 +11794,20 @@
8215 priindication_oob = 1;
8216 else if (!strcasecmp(v->value, "inband"))
8217 priindication_oob = 0;
8218 + else if (!strcasecmp(v->value, "passthrough"))
8219 + priindication_oob = 2;
8220 else
8221 - ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
8222 + ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' , 'outofband' or 'passthrough' at line %d\n",
8223 + v->value, v->lineno);
8224 + } else if (!strcasecmp(v->name, "pritransfer")) {
8225 + if (!strcasecmp(v->value, "no"))
8226 + pritransfer = 0;
8227 + else if (!strcasecmp(v->value, "ect"))
8228 + pritransfer = 1;
8229 + else if (!strcasecmp(v->value, "hangup"))
8230 + pritransfer = 2;
8231 + else
8232 + ast_log(LOG_WARNING, "'%s' is not a valid pri transfer value, should be 'no' , 'ect' or 'hangup' at line %d\n",
8233 v->value, v->lineno);
8234 } else if (!strcasecmp(v->name, "priexclusive")) {
8235 cur_priexclusive = ast_true(v->value);
8236 @@ -10699,6 +11821,10 @@
8237 ast_copy_string(privateprefix, v->value, sizeof(privateprefix));
8238 } else if (!strcasecmp(v->name, "unknownprefix")) {
8239 ast_copy_string(unknownprefix, v->value, sizeof(unknownprefix));
8240 + } else if (!strcasecmp(v->name, "nocid")) {
8241 + ast_copy_string(nocid, v->value, sizeof(nocid) - 1);
8242 + } else if (!strcasecmp(v->name, "withheldcid")) {
8243 + ast_copy_string(withheldcid, v->value, sizeof(withheldcid) - 1);
8244 } else if (!strcasecmp(v->name, "resetinterval")) {
8245 if (!strcasecmp(v->value, "never"))
8246 resetinterval = -1;
8247 @@ -10713,6 +11839,8 @@
8248 ast_copy_string(idleext, v->value, sizeof(idleext));
8249 } else if (!strcasecmp(v->name, "idledial")) {
8250 ast_copy_string(idledial, v->value, sizeof(idledial));
8251 + } else if (!strcasecmp(v->name, "pritrustusercid")) {
8252 + usercid = ast_true(v->value);
8253 } else if (!strcasecmp(v->name, "overlapdial")) {
8254 overlapdial = ast_true(v->value);
8255 } else if (!strcasecmp(v->name, "pritimer")) {
8256 @@ -10898,6 +12026,7 @@
8257 #ifdef ZAPATA_PRI
8258 if (!reload) {
8259 for (x=0;x<NUM_SPANS;x++) {
8260 + pris[x].debugfd = -1;
8261 if (pris[x].pvts[0]) {
8262 if (start_pri(pris + x)) {
8263 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
8264 @@ -10955,11 +12084,46 @@
8265 ast_manager_register( "ZapDNDon", 0, action_zapdndon, "Toggle Zap channel Do Not Disturb status ON" );
8266 ast_manager_register( "ZapDNDoff", 0, action_zapdndoff, "Toggle Zap channel Do Not Disturb status OFF" );
8267 ast_manager_register("ZapShowChannels", 0, action_zapshowchannels, "Show status zapata channels");
8268 -
8269 + ast_register_application(zapEC_app, app_zapEC, zapEC_synopsis, zapEC_tdesc);
8270 +#ifdef ZAPATA_PRI
8271 + ast_register_application(zapCD_app, app_zapCD, zapCD_synopsis, zapCD_tdesc);
8272 +#endif
8273 return res;
8274 }
8275
8276 +#ifdef ZAPATA_PRI
8277 +static int zt_tdd_sendtext(struct ast_channel *c, const char *text);
8278 +
8279 +static int zt_pri_sendtext(struct ast_channel *c, const char *text) {
8280 + struct zt_pvt *p = c->tech_pvt;
8281 + if (!p) return -1;
8282 + if (!p->pri) return -1;
8283 + if (strlen(text)) {
8284 + if (p->pri) {
8285 + if (!pri_grab(p, p->pri)) {
8286 + // ast_log(LOG_NOTICE, "Sending Display IE '%s'\n", text);
8287 + pri_information_display(p->pri->pri,p->call,(char *)text);
8288 + pri_rel(p->pri);
8289 + } else ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
8290 + }
8291 + }
8292 + return 0;
8293 +}
8294 +
8295 +static int zt_sendtext(struct ast_channel *c, const char *text) {
8296 + struct zt_pvt *p = c->tech_pvt;
8297 + if (!p) return -1;
8298 + if (p->sig == SIG_PRI) {
8299 + return zt_pri_sendtext(c, text);
8300 + } else {
8301 + return zt_tdd_sendtext(c, text);
8302 + }
8303 +}
8304 +
8305 +static int zt_tdd_sendtext(struct ast_channel *c, const char *text)
8306 +#else
8307 static int zt_sendtext(struct ast_channel *c, const char *text)
8308 +#endif
8309 {
8310 #define END_SILENCE_LEN 400
8311 #define HEADER_MS 50
8312 @@ -10978,6 +12142,7 @@
8313 float scont = 0.0;
8314 int index;
8315
8316 +
8317 index = zt_get_index(c, p, 0);
8318 if (index < 0) {
8319 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
8320 diff -urN asterisk-1.2.4.orig/codecs/codec_ilbc.c asterisk-1.2.4/codecs/codec_ilbc.c
8321 --- asterisk-1.2.4.orig/codecs/codec_ilbc.c 2005-11-29 19:24:39.000000000 +0100
8322 +++ asterisk-1.2.4/codecs/codec_ilbc.c 2006-01-31 09:41:43.000000000 +0100
8323 @@ -49,7 +49,7 @@
8324 #include "slin_ilbc_ex.h"
8325 #include "ilbc_slin_ex.h"
8326
8327 -#define USE_ILBC_ENHANCER 0
8328 +#define USE_ILBC_ENHANCER 1
8329 #define ILBC_MS 30
8330 /* #define ILBC_MS 20 */
8331
8332 diff -urN asterisk-1.2.4.orig/configs/capi.conf.sample asterisk-1.2.4/configs/capi.conf.sample
8333 --- asterisk-1.2.4.orig/configs/capi.conf.sample 1970-01-01 01:00:00.000000000 +0100
8334 +++ asterisk-1.2.4/configs/capi.conf.sample 2006-01-31 09:41:43.000000000 +0100
8335 @@ -0,0 +1,44 @@
8336 +;
8337 +; CAPI config
8338 +;
8339 +;
8340 +[general]
8341 +nationalprefix=0
8342 +internationalprefix=00
8343 +rxgain=0.8
8344 +txgain=0.8
8345 +
8346 +[interfaces]
8347 +
8348 +; mode: ptmp (point-to-multipoint) or ptp (point-to-point)
8349 +isdnmode=ptmp
8350 +; allow incoming calls to this list of MSNs, * == any
8351 +incomingmsn=*
8352 +; capi controller number
8353 +controller=1
8354 +; dialout group
8355 +group=1
8356 +; enable/disable software dtmf detection, recommended for AVM cards
8357 +softdtmf=1
8358 +; accountcode to use in CDRs
8359 +accountcode=
8360 +; context for incoming calls
8361 +context=capi-in
8362 +; _VERY_PRIMITIVE_ echo suppression
8363 +;echosquelch=1
8364 +; EICON DIVA SERVER echo cancelation
8365 +;echocancel=yes
8366 +;echotail=64
8367 +; call group
8368 +;callgroup=1
8369 +; deflect incoming calls to 12345678 if all B channels are busy
8370 +;deflect=12345678
8371 +; number of concurrent calls on this controller (2 makes sense for single BRI)
8372 +devices => 2
8373 +
8374 +
8375 +;PointToPoint (55512-0)
8376 +;isdnmode=ptp
8377 +;msn=55512
8378 +;controller=2
8379 +;devices => 30
8380 diff -urN asterisk-1.2.4.orig/configs/modules.conf.sample asterisk-1.2.4/configs/modules.conf.sample
8381 --- asterisk-1.2.4.orig/configs/modules.conf.sample 2005-11-29 19:24:39.000000000 +0100
8382 +++ asterisk-1.2.4/configs/modules.conf.sample 2006-01-31 09:41:43.000000000 +0100
8383 @@ -51,3 +51,4 @@
8384 ; exported to modules loaded after them.
8385 ;
8386 [global]
8387 +chan_capi.so=yes
8388 diff -urN asterisk-1.2.4.orig/configs/watchdog.conf.sample asterisk-1.2.4/configs/watchdog.conf.sample
8389 --- asterisk-1.2.4.orig/configs/watchdog.conf.sample 1970-01-01 01:00:00.000000000 +0100
8390 +++ asterisk-1.2.4/configs/watchdog.conf.sample 2006-01-31 09:41:43.000000000 +0100
8391 @@ -0,0 +1,22 @@
8392 +;
8393 +; Configuration file for res_watchdog
8394 +;
8395 +; type = isdnguard | watchdog
8396 +; device = /dev/...
8397 +; interval = interval to trigger the watchdog in ms
8398 +
8399 +;[ISDNguard-direct]
8400 +;type = isdnguard
8401 +;device = /dev/ttyS0
8402 +;interval = 200
8403 +
8404 +;[ISDNguard-with-daemon]
8405 +;type = isdnguard
8406 +;device = /var/run/guard.ctl
8407 +;interval = 200
8408 +
8409 +;[kernel_watchdog]
8410 +;type = watchdog
8411 +;device = /dev/watchdog
8412 +;interval = 100
8413 +
8414 diff -urN asterisk-1.2.4.orig/configs/zapata.conf.sample asterisk-1.2.4/configs/zapata.conf.sample
8415 --- asterisk-1.2.4.orig/configs/zapata.conf.sample 2005-11-29 19:24:39.000000000 +0100
8416 +++ asterisk-1.2.4/configs/zapata.conf.sample 2006-01-31 09:41:43.000000000 +0100
8417 @@ -121,9 +121,20 @@
8418 ;
8419 ; outofband: Signal Busy/Congestion out of band with RELEASE/DISCONNECT
8420 ; inband: Signal Busy/Congestion using in-band tones
8421 +; passthrough: Listen to the telco
8422 ;
8423 ; priindication = outofband
8424 ;
8425 +; PRI/BRI transfers (HOLD -> SETUP -> ECT/Hangup)
8426 +;
8427 +; Configure how transfers are initiated. ECT should be preferred
8428 +;
8429 +; no: no transfers allowed (results in hangup)
8430 +; ect: use ECT (facility)
8431 +: hangup: transfer on hangup (if your phones dont support ECT)
8432 +;
8433 +; pritransfer = ect
8434 +;
8435 ; If you need to override the existing channels selection routine and force all
8436 ; PRI channels to be marked as exclusively selected, set this to yes.
8437 ; priexclusive = yes
8438 diff -urN asterisk-1.2.4.orig/db.c asterisk-1.2.4/db.c
8439 --- asterisk-1.2.4.orig/db.c 2006-01-09 19:09:53.000000000 +0100
8440 +++ asterisk-1.2.4/db.c 2006-01-31 09:41:43.000000000 +0100
8441 @@ -516,11 +516,18 @@
8442 struct ast_cli_entry cli_database_deltree =
8443 { { "database", "deltree", NULL }, database_deltree, "Removes database keytree/values", database_deltree_usage };
8444
8445 +static char mandescr_dbput[] =
8446 +"Description: Put a value into astdb\n"
8447 +"Variables: \n"
8448 +" Family: ...\n"
8449 +" Key: ...\n"
8450 +" Value: ...\n";
8451 +
8452 static int manager_dbput(struct mansession *s, struct message *m)
8453 {
8454 char *family = astman_get_header(m, "Family");
8455 char *key = astman_get_header(m, "Key");
8456 - char *val = astman_get_header(m, "Val");
8457 + char *val = astman_get_header(m, "Value");
8458 int res;
8459
8460 if (!strlen(family)) {
8461 @@ -545,6 +552,12 @@
8462 return 0;
8463 }
8464
8465 +static char mandescr_dbget[] =
8466 +"Description: Get a value from astdb\n"
8467 +"Variables: \n"
8468 +" Family: ...\n"
8469 +" Key: ...\n";
8470 +
8471 static int manager_dbget(struct mansession *s, struct message *m)
8472 {
8473 char *id = astman_get_header(m,"ActionID");
8474 @@ -574,7 +587,7 @@
8475 ast_cli(s->fd, "Event: DBGetResponse\r\n"
8476 "Family: %s\r\n"
8477 "Key: %s\r\n"
8478 - "Val: %s\r\n"
8479 + "Value: %s\r\n"
8480 "%s"
8481 "\r\n",
8482 family, key, tmp, idText);
8483 @@ -582,6 +595,39 @@
8484 return 0;
8485 }
8486
8487 +static char mandescr_dbdel[] =
8488 +"Description: remove value from astdb\n"
8489 +"Variables: \n"
8490 +" Family: ...\n"
8491 +" Key: ...\n";
8492 +
8493 +static int manager_dbdel(struct mansession *s, struct message *m)
8494 +{
8495 + char *family = astman_get_header(m, "Family");
8496 + char *key = astman_get_header(m, "Key");
8497 + char *id = astman_get_header(m,"ActionID");
8498 +
8499 + if (!strlen(family)) {
8500 + astman_send_error(s, m, "No family specified");
8501 + return 0;
8502 + }
8503 + if (!strlen(key)) {
8504 + astman_send_error(s, m, "No key specified");
8505 + return 0;
8506 + }
8507 +
8508 + if (ast_db_del(family, key)) {
8509 + ast_cli(s->fd, "Response: Failed\r\n");
8510 + } else {
8511 + ast_cli(s->fd, "Response: Success\r\n");
8512 + }
8513 + if (id && !ast_strlen_zero(id))
8514 + ast_cli(s->fd, "ActionID: %s\r\n",id);
8515 + ast_cli(s->fd, "\r\n");
8516 +
8517 + return 0;
8518 +}
8519 +
8520 int astdb_init(void)
8521 {
8522 dbinit();
8523 @@ -591,7 +637,8 @@
8524 ast_cli_register(&cli_database_put);
8525 ast_cli_register(&cli_database_del);
8526 ast_cli_register(&cli_database_deltree);
8527 - ast_manager_register("DBGet", EVENT_FLAG_SYSTEM, manager_dbget, "Get DB Entry");
8528 - ast_manager_register("DBPut", EVENT_FLAG_SYSTEM, manager_dbput, "Put DB Entry");
8529 + ast_manager_register("DBget", EVENT_FLAG_SYSTEM, manager_dbget, mandescr_dbget);
8530 + ast_manager_register("DBput", EVENT_FLAG_SYSTEM, manager_dbput, mandescr_dbput);
8531 + ast_manager_register("DBdel", EVENT_FLAG_SYSTEM, manager_dbdel, mandescr_dbdel);
8532 return 0;
8533 }
8534 diff -urN asterisk-1.2.4.orig/devicestate.c asterisk-1.2.4/devicestate.c
8535 --- asterisk-1.2.4.orig/devicestate.c 2005-11-29 19:24:39.000000000 +0100
8536 +++ asterisk-1.2.4/devicestate.c 2006-01-31 09:41:43.000000000 +0100
8537 @@ -62,6 +62,8 @@
8538
8539 struct state_change {
8540 AST_LIST_ENTRY(state_change) list;
8541 + char cid_num[AST_MAX_EXTENSION];
8542 + char cid_name[AST_MAX_EXTENSION];
8543 char device[1];
8544 };
8545
8546 @@ -177,7 +179,7 @@
8547 }
8548
8549 /*--- do_state_change: Notify callback watchers of change, and notify PBX core for hint updates */
8550 -static void do_state_change(const char *device)
8551 +static void do_state_change(const char *device, char *cid_num, char *cid_name)
8552 {
8553 int state;
8554 struct devstate_cb *devcb;
8555 @@ -188,13 +190,13 @@
8556
8557 AST_LIST_LOCK(&devstate_cbs);
8558 AST_LIST_TRAVERSE(&devstate_cbs, devcb, list)
8559 - devcb->callback(device, state, devcb->data);
8560 + devcb->callback(device, state, devcb->data, cid_num, cid_name);
8561 AST_LIST_UNLOCK(&devstate_cbs);
8562
8563 - ast_hint_state_changed(device);
8564 + ast_hint_state_changed(device, cid_num, cid_name);
8565 }
8566
8567 -static int __ast_device_state_changed_literal(char *buf)
8568 +static int __ast_device_state_changed_literal(char *buf, char *cid_num, char *cid_name)
8569 {
8570 char *device, *tmp;
8571 struct state_change *change = NULL;
8572 @@ -209,10 +211,16 @@
8573 if (!change) {
8574 /* we could not allocate a change struct, or */
8575 /* there is no background thread, so process the change now */
8576 - do_state_change(device);
8577 + do_state_change(device, cid_num, cid_name);
8578 } else {
8579 /* queue the change */
8580 strcpy(change->device, device);
8581 + if (cid_num && (!ast_strlen_zero(cid_num))) {
8582 + strncpy(change->cid_num, cid_num, sizeof(change->cid_num) - 1);
8583 + }
8584 + if (cid_name && (!ast_strlen_zero(cid_name))) {
8585 + strncpy(change->cid_name, cid_name, sizeof(change->cid_name) - 1);
8586 + }
8587 AST_LIST_LOCK(&state_changes);
8588 AST_LIST_INSERT_TAIL(&state_changes, change, list);
8589 if (AST_LIST_FIRST(&state_changes) == change)
8590 @@ -224,23 +232,49 @@
8591 return 1;
8592 }
8593
8594 -int ast_device_state_changed_literal(const char *dev)
8595 +int ast_device_state_changed_literal(const char *dev, const char *cid_num, const char *cid_name)
8596 {
8597 char *buf;
8598 + char *buf2 = NULL;
8599 + char *buf3 = NULL;
8600 buf = ast_strdupa(dev);
8601 - return __ast_device_state_changed_literal(buf);
8602 + if (cid_num)
8603 + buf2 = ast_strdupa(cid_num);
8604 + if (cid_name)
8605 + buf3 = ast_strdupa(cid_name);
8606 + return __ast_device_state_changed_literal(buf, buf2, buf3);
8607 }
8608
8609 /*--- ast_device_state_changed: Accept change notification, add it to change queue */
8610 int ast_device_state_changed(const char *fmt, ...)
8611 {
8612 char buf[AST_MAX_EXTENSION];
8613 + char cid_num[AST_MAX_EXTENSION];
8614 + char cid_name[AST_MAX_EXTENSION];
8615 + char *s = NULL;
8616 va_list ap;
8617
8618 va_start(ap, fmt);
8619 - vsnprintf(buf, sizeof(buf), fmt, ap);
8620 + if (*fmt == 's') {
8621 + s = va_arg(ap, char *);
8622 + snprintf(buf, sizeof(buf), s);
8623 + *fmt++;
8624 + if (*fmt == 's') {
8625 + s = va_arg(ap, char *);
8626 + if (s) {
8627 + snprintf(cid_num, sizeof(cid_num), s);
8628 + }
8629 + *fmt++;
8630 + if (*fmt == 's') {
8631 + s = va_arg(ap, char *);
8632 + if (s) {
8633 + snprintf(cid_name, sizeof(cid_name), s);
8634 + }
8635 + }
8636 + }
8637 + }
8638 va_end(ap);
8639 - return __ast_device_state_changed_literal(buf);
8640 + return __ast_device_state_changed_literal(buf, cid_num, cid_name);
8641 }
8642
8643 /*--- do_devstate_changes: Go through the dev state change queue and update changes in the dev state thread */
8644 @@ -255,7 +289,7 @@
8645 if (cur) {
8646 /* we got an entry, so unlock the list while we process it */
8647 AST_LIST_UNLOCK(&state_changes);
8648 - do_state_change(cur->device);
8649 + do_state_change(cur->device, cur->cid_num, cur->cid_name);
8650 free(cur);
8651 AST_LIST_LOCK(&state_changes);
8652 } else {
8653 diff -urN asterisk-1.2.4.orig/doc/README.asterisk.conf asterisk-1.2.4/doc/README.asterisk.conf
8654 --- asterisk-1.2.4.orig/doc/README.asterisk.conf 2005-11-29 19:24:39.000000000 +0100
8655 +++ asterisk-1.2.4/doc/README.asterisk.conf 2006-01-31 09:41:43.000000000 +0100
8656 @@ -62,6 +62,7 @@
8657 maxcalls = 255 ; The maximum number of concurrent calls you want to allow
8658 execincludes = yes | no ; Allow #exec entries in configuration files
8659 dontwarn = yes | no ; Don't over-inform the Asterisk sysadm, he's a guru
8660 +uniquename = asterisk ; host name part to be included in the uniqueid
8661
8662 [files]
8663 ; Changing the following lines may compromise your security
8664 diff -urN asterisk-1.2.4.orig/editline/cygdef.h asterisk-1.2.4/editline/cygdef.h
8665 --- asterisk-1.2.4.orig/editline/cygdef.h 1970-01-01 01:00:00.000000000 +0100
8666 +++ asterisk-1.2.4/editline/cygdef.h 2006-01-31 09:41:43.000000000 +0100
8667 @@ -0,0 +1,11 @@
8668 +/* cygdef.h. Generated automatically by configure. */
8669 +#ifndef _CYGDEF_H_
8670 +#define _CYGDEF_H_ 1
8671 +#include <sys/ioctl.h>
8672 +#define __linux__ 1
8673 +
8674 +
8675 +typedef void (*sig_t)(int);
8676 +
8677 +
8678 +#endif /* _CYGDEF_H_ */
8679 diff -urN asterisk-1.2.4.orig/include/asterisk/agi.h asterisk-1.2.4/include/asterisk/agi.h
8680 --- asterisk-1.2.4.orig/include/asterisk/agi.h 2005-11-29 19:24:39.000000000 +0100
8681 +++ asterisk-1.2.4/include/asterisk/agi.h 2006-01-31 09:41:43.000000000 +0100
8682 @@ -29,7 +29,8 @@
8683
8684 typedef struct agi_state {
8685 int fd; /* FD for general output */
8686 - int audio; /* FD for audio output */
8687 + int audio_out; /* FD for audio output */
8688 + int audio_in; /* FD for audio output */
8689 int ctrl; /* FD for input control */
8690 } AGI;
8691
8692 diff -urN asterisk-1.2.4.orig/include/asterisk/chan_capi.h asterisk-1.2.4/include/asterisk/chan_capi.h
8693 --- asterisk-1.2.4.orig/include/asterisk/chan_capi.h 1970-01-01 01:00:00.000000000 +0100
8694 +++ asterisk-1.2.4/include/asterisk/chan_capi.h 2006-01-31 09:41:43.000000000 +0100
8695 @@ -0,0 +1,276 @@
8696 +/*
8697 + * (CAPI*)
8698 + *
8699 + * An implementation of Common ISDN API 2.0 for Asterisk
8700 + *
8701 + * Copyright (C) 2002, 2003, 2004, Junghanns.NET GmbH
8702 + *
8703 + * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
8704 + *
8705 + * This program is free software and may be modified and
8706 + * distributed under the terms of the GNU Public License.
8707 + */
8708 +
8709 +#ifndef _ASTERISK_CAPI_H
8710 +#define _ASTERISK_CAPI_H
8711 +
8712 +#define AST_CAPI_MAX_CONTROLLERS 16
8713 +#define AST_CAPI_MAX_DEVICES 30
8714 +#define AST_CAPI_MAX_BUF 160
8715 +
8716 +#define AST_CAPI_MAX_B3_BLOCKS 7
8717 +
8718 +/* was : 130 bytes Alaw = 16.25 ms audio not suitable for VoIP */
8719 +/* now : 160 bytes Alaw = 20 ms audio */
8720 +/* you can tune this to your need. higher value == more latency */
8721 +#define AST_CAPI_MAX_B3_BLOCK_SIZE 160
8722 +
8723 +#define AST_CAPI_BCHANS 120
8724 +#define ALL_SERVICES 0x1FFF03FF
8725 +
8726 +/* duration in ms for sending and detecting dtmfs */
8727 +#define AST_CAPI_DTMF_DURATION 0x40
8728 +
8729 +#define AST_CAPI_NATIONAL_PREF "0"
8730 +#define AST_CAPI_INTERNAT_PREF "00"
8731 +
8732 +#ifdef CAPI_ES
8733 +#define ECHO_TX_COUNT 5 // 5 x 20ms = 100ms
8734 +#define ECHO_EFFECTIVE_TX_COUNT 3 // 2 x 20ms = 40ms == 40-100ms ... ignore first 40ms
8735 +#define ECHO_TXRX_RATIO 2.3 // if( rx < (txavg/ECHO_TXRX_RATIO) ) rx=0;
8736 +#endif
8737 +
8738 +/*
8739 + * state combination for a normal incoming call:
8740 + * DIS -> ALERT -> CON -> BCON -> CON -> DIS
8741 + *
8742 + * outgoing call:
8743 + * DIS -> CONP -> BCONNECTED -> CON -> DIS
8744 + */
8745 +
8746 +#define CAPI_STATE_ALERTING 1
8747 +#define CAPI_STATE_CONNECTED 2
8748 +#define CAPI_STATE_BCONNECTED 3
8749 +
8750 +#define CAPI_STATE_DISCONNECTING 4
8751 +#define CAPI_STATE_DISCONNECTED 5
8752 +#define CAPI_STATE_REMOTE_HANGUP 6
8753 +
8754 +#define CAPI_STATE_CONNECTPENDING 7
8755 +#define CAPI_STATE_ONHOLD 8
8756 +#define CAPI_STATE_NETWORKHANGUP 9
8757 +#define CAPI_STATE_ANSWERING 10
8758 +#define CAPI_STATE_PUTTINGONHOLD 11
8759 +#define CAPI_STATE_RETRIEVING 12
8760 +
8761 +#define CAPI_STATE_DID 13
8762 +
8763 +#define AST_CAPI_B3_DONT 0
8764 +#define AST_CAPI_B3_ALWAYS 1
8765 +#define AST_CAPI_B3_ON_SUCCESS 2
8766 +
8767 +#ifdef CAPI_GAIN
8768 +struct ast_capi_gains {
8769 + unsigned char txgains[256];
8770 + unsigned char rxgains[256];
8771 +};
8772 +#endif
8773 +
8774 +#define PRES_ALLOWED_USER_NUMBER_NOT_SCREENED 0x00
8775 +#define PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN 0x01
8776 +#define PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN 0x02
8777 +#define PRES_ALLOWED_NETWORK_NUMBER 0x03
8778 +#define PRES_PROHIB_USER_NUMBER_NOT_SCREENED 0x20
8779 +#define PRES_PROHIB_USER_NUMBER_PASSED_SCREEN 0x21
8780 +#define PRES_PROHIB_USER_NUMBER_FAILED_SCREEN 0x22
8781 +#define PRES_PROHIB_NETWORK_NUMBER 0x23
8782 +#define PRES_NUMBER_NOT_AVAILABLE 0x43
8783 +
8784 +
8785 +//! Private data for a capi device
8786 +struct ast_capi_pvt {
8787 + ast_mutex_t lock;
8788 + int fd;
8789 +
8790 + /*! Channel we belong to, possibly NULL */
8791 + struct ast_channel *owner;
8792 + /*! Frame */
8793 + struct ast_frame fr;
8794 +
8795 + char offset[AST_FRIENDLY_OFFSET];
8796 +
8797 + // capi message number
8798 + _cword MessageNumber;
8799 + int NCCI;
8800 + int PLCI;
8801 + /* on which controller we do live */
8802 + int controller;
8803 +
8804 + /* we could live on those */
8805 + unsigned long controllers;
8806 +
8807 + int datahandle;
8808 +
8809 + short buf[AST_CAPI_MAX_BUF];
8810 + int buflen;
8811 + /*! Immediate, or wait for an answer */
8812 + int mode;
8813 + /*! State of modem in miniature */
8814 + int state;
8815 + /*! Digits to strip on outgoing numbers */
8816 + int stripmsd;
8817 + /*! ringer timeout */
8818 + int ringt;
8819 + /*! actual time of last ring */
8820 + time_t lastring;
8821 + /*! dtmf receive state/data */
8822 + char dtmfrx;
8823 +
8824 + char context[AST_MAX_EXTENSION];
8825 + /*! Multiple Subscriber Number we listen to (, seperated list) */
8826 + char incomingmsn[AST_MAX_EXTENSION];
8827 + /*! Prefix to Build CID */
8828 + char prefix[AST_MAX_EXTENSION];
8829 + /*! Caller ID if available */
8830 + char cid[AST_MAX_EXTENSION];
8831 + /*! Dialed Number if available */
8832 + char dnid[AST_MAX_EXTENSION];
8833 +
8834 + char accountcode[20];
8835 +
8836 + unsigned int callgroup;
8837 + unsigned int group;
8838 +
8839 + /*! default language */
8840 + char language[MAX_LANGUAGE];
8841 + /*! Static response buffer */
8842 + char response[256];
8843 +
8844 + int calledPartyIsISDN;
8845 + // this is an outgoing channel
8846 + int outgoing;
8847 + // use CLIR
8848 + int CLIR;
8849 + // are we doing early B3 connect on this interface?
8850 + int earlyB3;
8851 + // should we do early B3 on this interface?
8852 + int doB3;
8853 + // store plci here for the call that is onhold
8854 + int onholdPLCI;
8855 + // do software dtmf detection
8856 + int doDTMF;
8857 + // CAPI echo cancellation
8858 + int doEC;
8859 + int ecOption;
8860 + int ecTail;
8861 + // isdnmode ptp or ptm
8862 + int isdnmode;
8863 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
8864 + // deflect on circuitbusy
8865 + char deflect2[AST_MAX_EXTENSION];
8866 +#endif
8867 +
8868 + // not all codecs supply frames in nice 320 byte chunks
8869 + struct ast_smoother *smoother;
8870 + // ok, we stop to be nice and give them the lowest possible latency 130 samples * 2 = 260 bytes */
8871 +#ifdef CAPI_SYNC
8872 + int B3in;
8873 + ast_mutex_t lockB3in;
8874 +#endif
8875 +
8876 + // do ECHO SURPRESSION
8877 + int doES;
8878 +#ifdef CAPI_ES
8879 + short txavg[ECHO_TX_COUNT];
8880 + float rxmin;
8881 + float txmin;
8882 +#endif
8883 +#ifdef CAPI_GAIN
8884 + struct ast_capi_gains g;
8885 +#endif
8886 + float txgain;
8887 + float rxgain;
8888 + struct ast_dsp *vad;
8889 +
8890 +
8891 + struct capi_pipe *mypipe;
8892 + /*! Next channel in list */
8893 + struct ast_capi_pvt *next;
8894 +};
8895 +
8896 +
8897 +struct ast_capi_profile {
8898 + unsigned short ncontrollers;
8899 + unsigned short nbchannels;
8900 + unsigned char globaloptions;
8901 + unsigned char globaloptions2;
8902 + unsigned char globaloptions3;
8903 + unsigned char globaloptions4;
8904 + unsigned int b1protocols;
8905 + unsigned int b2protocols;
8906 + unsigned int b3protocols;
8907 + unsigned int reserved3[6];
8908 + unsigned int manufacturer[5];
8909 +};
8910 +
8911 +struct capi_pipe {
8912 + // lock
8913 + ast_mutex_t lock;
8914 +
8915 + // fd for writing to the channel
8916 + int fd;
8917 +
8918 + // PLCI and NCCI of the B3 CON
8919 + int PLCI;
8920 + int NCCI;
8921 + // pointer to the interface
8922 + struct ast_capi_pvt *i;
8923 + // pointer to the channel
8924 + struct ast_channel *c;
8925 + // next pipe
8926 + struct capi_pipe *next;
8927 +};
8928 +
8929 +struct ast_capi_controller {
8930 + // which controller is this?
8931 + int controller;
8932 + // how many bchans?
8933 + int nbchannels;
8934 + // free bchans
8935 + int nfreebchannels;
8936 + // DID
8937 + int isdnmode;
8938 + // features:
8939 + int dtmf;
8940 + int echocancel;
8941 + int sservices; // supplementray services
8942 + // supported sservices:
8943 + int holdretrieve;
8944 + int terminalportability;
8945 + int ECT;
8946 + int threePTY;
8947 + int CF;
8948 + int CD;
8949 + int MCID;
8950 + int CCBS;
8951 + int MWI;
8952 + int CCNR;
8953 + int CONF;
8954 +};
8955 +
8956 +
8957 +// ETSI 300 102-1 information element identifiers
8958 +#define CAPI_ETSI_IE_CAUSE 0x08;
8959 +#define CAPI_ETSI_IE_PROGRESS_INDICATOR 0x1e;
8960 +#define CAPI_ETSI_IE_CALLED_PARTY_NUMBER 0x70;
8961 +
8962 +// ETIS 300 102-1 message types
8963 +#define CAPI_ETSI_ALERTING 0x01;
8964 +#define CAPI_ETSI_SETUP_ACKKNOWLEDGE 0x0d;
8965 +#define CAPI_ETSI_DISCONNECT 0x45;
8966 +
8967 +// ETSI 300 102-1 Numbering Plans
8968 +#define CAPI_ETSI_NPLAN_NATIONAL 0x20
8969 +#define CAPI_ETSI_NPLAN_INTERNAT 0x10
8970 +
8971 +#endif
8972 diff -urN asterisk-1.2.4.orig/include/asterisk/chan_capi_app.h asterisk-1.2.4/include/asterisk/chan_capi_app.h
8973 --- asterisk-1.2.4.orig/include/asterisk/chan_capi_app.h 1970-01-01 01:00:00.000000000 +0100
8974 +++ asterisk-1.2.4/include/asterisk/chan_capi_app.h 2006-01-31 09:41:43.000000000 +0100
8975 @@ -0,0 +1,30 @@
8976 +/*
8977 + * (CAPI*)
8978 + *
8979 + * An implementation of Common ISDN API 2.0 for Asterisk
8980 + *
8981 + * include file for helper applications
8982 + *
8983 + * Copyright (C) 2002, 2003, 2004, Junghanns.NET GmbH
8984 + *
8985 + * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
8986 + *
8987 + * This program is free software and may be modified and
8988 + * distributed under the terms of the GNU Public License.
8989 + */
8990 +
8991 +#ifndef _ASTERISK_CAPI_IF_H
8992 +#define _ASTERISK_CAPI_IF_H
8993 +
8994 +// exported symbols from chan_capi
8995 +
8996 +// important things we need
8997 +extern unsigned ast_capi_ApplID;
8998 +extern unsigned ast_capi_MessageNumber;
8999 +extern int capidebug;
9000 +
9001 +extern int capi_call(struct ast_channel *c, char *idest, int timeout);
9002 +extern int capi_detect_dtmf(struct ast_channel *c, int flag);
9003 +extern MESSAGE_EXCHANGE_ERROR _capi_put_cmsg(_cmsg *CMSG);
9004 +
9005 +#endif
9006 diff -urN asterisk-1.2.4.orig/include/asterisk/channel.h asterisk-1.2.4/include/asterisk/channel.h
9007 --- asterisk-1.2.4.orig/include/asterisk/channel.h 2005-11-29 19:24:39.000000000 +0100
9008 +++ asterisk-1.2.4/include/asterisk/channel.h 2006-01-31 09:41:43.000000000 +0100
9009 @@ -86,6 +86,9 @@
9010 #ifndef _ASTERISK_CHANNEL_H
9011 #define _ASTERISK_CHANNEL_H
9012
9013 +/* Max length of the uniqueid */
9014 +#define AST_MAX_UNIQUEID 64
9015 +
9016 #include <unistd.h>
9017 #include <setjmp.h>
9018 #ifdef POLLCOMPAT
9019 @@ -380,7 +383,7 @@
9020 unsigned int fout;
9021
9022 /* Unique Channel Identifier */
9023 - char uniqueid[32];
9024 + char uniqueid[AST_MAX_UNIQUEID];
9025
9026 /* Why is the channel hanged up */
9027 int hangupcause;
9028 @@ -531,6 +534,11 @@
9029 #define AST_STATE_MUTE (1 << 16)
9030 /*! @} */
9031
9032 +extern ast_mutex_t uniquelock;
9033 +
9034 +/*! \brief Change the state of a channel and the callerid of the calling channel*/
9035 +int ast_setstate_and_cid(struct ast_channel *chan, int state, char *cid_num, char *cid_name);
9036 +
9037 /*! \brief Change the state of a channel */
9038 int ast_setstate(struct ast_channel *chan, int state);
9039
9040 @@ -567,7 +575,7 @@
9041 * by the low level module
9042 * \return Returns an ast_channel on success, NULL on failure.
9043 */
9044 -struct ast_channel *ast_request(const char *type, int format, void *data, int *status);
9045 +struct ast_channel *ast_request(const char *type, int format, void *data, int *status, char *uniqueid);
9046
9047 /*!
9048 * \brief Request a channel of a given type, with data as optional information used
9049 @@ -582,9 +590,9 @@
9050 * \return Returns an ast_channel on success or no answer, NULL on failure. Check the value of chan->_state
9051 * to know if the call was answered or not.
9052 */
9053 -struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, const char *cidnum, const char *cidname);
9054 +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);
9055
9056 -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);
9057 +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);
9058
9059 /*!\brief Register a channel technology (a new channel driver)
9060 * Called by a channel module to register the kind of channels it supports.
9061 @@ -837,6 +845,10 @@
9062 /*--- ast_get_channel_by_exten_locked: Get channel by exten (and optionally context) and lock it */
9063 struct ast_channel *ast_get_channel_by_exten_locked(const char *exten, const char *context);
9064
9065 +/*! Get channel by uniqueid (locks channel) */
9066 +struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid);
9067 +
9068 +
9069 /*! Waits for a digit */
9070 /*!
9071 * \param c channel to wait for a digit on
9072 @@ -907,6 +919,9 @@
9073 p->owner pointer) that is affected by the change. The physical layer of the original
9074 channel is hung up. */
9075 int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone);
9076 +int ast_channel_masquerade_locked(struct ast_channel *original, struct ast_channel *clone);
9077 +
9078 +char *ast_alloc_uniqueid(void);
9079
9080 /*! Gives the string form of a given cause code */
9081 /*!
9082 diff -urN asterisk-1.2.4.orig/include/asterisk/devicestate.h asterisk-1.2.4/include/asterisk/devicestate.h
9083 --- asterisk-1.2.4.orig/include/asterisk/devicestate.h 2005-11-29 19:24:39.000000000 +0100
9084 +++ asterisk-1.2.4/include/asterisk/devicestate.h 2006-01-31 09:41:43.000000000 +0100
9085 @@ -42,7 +42,7 @@
9086 /*! Device is ringing */
9087 #define AST_DEVICE_RINGING 6
9088
9089 -typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data);
9090 +typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data, char *cid_num, char *cid_name);
9091
9092 /*! \brief Convert device state to text string for output
9093 * \param devstate Current device state
9094 @@ -84,7 +84,7 @@
9095 * callbacks for the changed extensions
9096 * Returns 0 on success, -1 on failure
9097 */
9098 -int ast_device_state_changed_literal(const char *device);
9099 +int ast_device_state_changed_literal(const char *device, const char *cid_num, const char *cid_name);
9100
9101 /*! \brief Registers a device state change callback
9102 * \param callback Callback
9103 diff -urN asterisk-1.2.4.orig/include/asterisk/features.h asterisk-1.2.4/include/asterisk/features.h
9104 --- asterisk-1.2.4.orig/include/asterisk/features.h 2005-11-29 19:24:39.000000000 +0100
9105 +++ asterisk-1.2.4/include/asterisk/features.h 2006-01-31 09:41:43.000000000 +0100
9106 @@ -45,6 +45,8 @@
9107 };
9108
9109
9110 +extern int ast_autoanswer_login(struct ast_channel *chan, void *data);
9111 +extern int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data);
9112
9113 /*! \brief Park a call and read back parked location
9114 * \param chan the channel to actually be parked
9115 @@ -68,11 +70,19 @@
9116 */
9117 extern int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *host, int timeout, int *extout);
9118
9119 +extern int ast_hold_call(struct ast_channel *chan, struct ast_channel *host);
9120 +extern int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *host);
9121 +extern int ast_retrieve_call(struct ast_channel *chan, char *uniqueid);
9122 +extern int ast_retrieve_call_to_death(char *uniqueid);
9123 +extern struct ast_channel *ast_get_holded_call(char *uniqueid);
9124 +
9125 /*! \brief Determine system parking extension
9126 * Returns the call parking extension for drivers that provide special
9127 call parking help */
9128 extern char *ast_parking_ext(void);
9129
9130 +extern char *ast_parking_con(void);
9131 +
9132 /*! \brief Determine system call pickup extension */
9133 extern char *ast_pickup_ext(void);
9134
9135 @@ -92,4 +102,12 @@
9136 \param feature the ast_call_feature object which was registered before*/
9137 extern void ast_unregister_feature(struct ast_call_feature *feature);
9138
9139 +/*! \brief find a feature by name
9140 + \param name of the feature to be returned */
9141 +extern struct ast_call_feature *ast_find_feature(char *name);
9142 +
9143 +/*! \brief find a builtin feature by name
9144 + \param name of the feature to be returned */
9145 +extern struct ast_call_feature *ast_find_builtin_feature(char *name);
9146 +
9147 #endif /* _AST_FEATURES_H */
9148 diff -urN asterisk-1.2.4.orig/include/asterisk/pbx.h asterisk-1.2.4/include/asterisk/pbx.h
9149 --- asterisk-1.2.4.orig/include/asterisk/pbx.h 2005-11-29 19:24:39.000000000 +0100
9150 +++ asterisk-1.2.4/include/asterisk/pbx.h 2006-01-31 09:41:43.000000000 +0100
9151 @@ -57,7 +57,7 @@
9152 AST_EXTENSION_BUSY = 1 << 1,
9153 /*! All devices UNAVAILABLE/UNREGISTERED */
9154 AST_EXTENSION_UNAVAILABLE = 1 << 2,
9155 - /*! All devices RINGING */
9156 + /*! One or more devices RINGING */
9157 AST_EXTENSION_RINGING = 1 << 3,
9158 };
9159
9160 @@ -80,7 +80,7 @@
9161 struct ast_ignorepat;
9162 struct ast_sw;
9163
9164 -typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data);
9165 +typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data, char *cid_num, char *cid_name);
9166
9167 /*! Data structure associated with a custom function */
9168 struct ast_custom_function {
9169 @@ -156,6 +156,8 @@
9170 */
9171 extern struct ast_app *pbx_findapp(const char *app);
9172
9173 +void *ast_pbx_run_app(void *data);
9174 +
9175 /*! executes an application */
9176 /*!
9177 * \param c channel to execute on
9178 @@ -563,11 +565,11 @@
9179
9180 /* Synchronously or asynchronously make an outbound call and send it to a
9181 particular extension */
9182 -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, struct ast_channel **locked_channel);
9183 +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, struct ast_channel **locked_channel, char *uniqueid);
9184
9185 /* Synchronously or asynchronously make an outbound call and send it to a
9186 particular application with given extension */
9187 -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, struct ast_channel **locked_channel);
9188 +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, struct ast_channel **locked_channel, char *uniqueid);
9189
9190 /* Functions for returning values from structures */
9191 const char *ast_get_context_name(struct ast_context *con);
9192 @@ -656,7 +658,7 @@
9193 */
9194 void ast_func_write(struct ast_channel *chan, const char *in, const char *value);
9195
9196 -void ast_hint_state_changed(const char *device);
9197 +void ast_hint_state_changed(const char *device, const char *cid_num, const char *cid_name);
9198
9199 #if defined(__cplusplus) || defined(c_plusplus)
9200 }
9201 diff -urN asterisk-1.2.4.orig/include/asterisk/xlaw.h asterisk-1.2.4/include/asterisk/xlaw.h
9202 --- asterisk-1.2.4.orig/include/asterisk/xlaw.h 1970-01-01 01:00:00.000000000 +0100
9203 +++ asterisk-1.2.4/include/asterisk/xlaw.h 2006-01-31 09:41:43.000000000 +0100
9204 @@ -0,0 +1,1665 @@
9205 +#ifndef _ASTERISK_XLAW_H
9206 +#define _ASTERISK_XLAW_H
9207 +
9208 +#ifdef CAPI_ULAW
9209 +#define capiXLAW2INT(x) capiULAW2INT[x]
9210 +#define capiINT2XLAW(x) capiINT2ULAW[((unsigned short)x) >> 2]
9211 +#else
9212 +#define capiXLAW2INT(x) capiALAW2INT[x]
9213 +#define capiINT2XLAW(x) capiINT2ALAW[(x>>4)+4096]
9214 +#endif
9215 +
9216 +static unsigned char reversebits[256] =
9217 +{
9218 +0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
9219 +0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
9220 +0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
9221 +0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
9222 +0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
9223 +0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
9224 +0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
9225 +0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
9226 +0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
9227 +0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
9228 +0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
9229 +0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
9230 +0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
9231 +0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
9232 +0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
9233 +0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
9234 +0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
9235 +0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
9236 +0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
9237 +0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
9238 +0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
9239 +0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
9240 +0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
9241 +0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
9242 +0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
9243 +0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
9244 +0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
9245 +0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
9246 +0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
9247 +0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
9248 +0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
9249 +0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
9250 +};
9251 +
9252 +#ifdef CAPI_ULAW
9253 +static short capiULAW2INT[] =
9254 +{
9255 +0x8284, 0x7d7c, 0xf8a4, 0x075c, 0xe104, 0x1efc, 0xfe8c, 0x0174,
9256 +0xc184, 0x3e7c, 0xfc94, 0x036c, 0xf0c4, 0x0f3c, 0xff88, 0x0078,
9257 +0xa284, 0x5d7c, 0xfaa4, 0x055c, 0xe904, 0x16fc, 0xff0c, 0x00f4,
9258 +0xd184, 0x2e7c, 0xfd94, 0x026c, 0xf4c4, 0x0b3c, 0xffc8, 0x0038,
9259 +0x9284, 0x6d7c, 0xf9a4, 0x065c, 0xe504, 0x1afc, 0xfecc, 0x0134,
9260 +0xc984, 0x367c, 0xfd14, 0x02ec, 0xf2c4, 0x0d3c, 0xffa8, 0x0058,
9261 +0xb284, 0x4d7c, 0xfba4, 0x045c, 0xed04, 0x12fc, 0xff4c, 0x00b4,
9262 +0xd984, 0x267c, 0xfe14, 0x01ec, 0xf6c4, 0x093c, 0xffe8, 0x0018,
9263 +0x8a84, 0x757c, 0xf924, 0x06dc, 0xe304, 0x1cfc, 0xfeac, 0x0154,
9264 +0xc584, 0x3a7c, 0xfcd4, 0x032c, 0xf1c4, 0x0e3c, 0xff98, 0x0068,
9265 +0xaa84, 0x557c, 0xfb24, 0x04dc, 0xeb04, 0x14fc, 0xff2c, 0x00d4,
9266 +0xd584, 0x2a7c, 0xfdd4, 0x022c, 0xf5c4, 0x0a3c, 0xffd8, 0x0028,
9267 +0x9a84, 0x657c, 0xfa24, 0x05dc, 0xe704, 0x18fc, 0xfeec, 0x0114,
9268 +0xcd84, 0x327c, 0xfd54, 0x02ac, 0xf3c4, 0x0c3c, 0xffb8, 0x0048,
9269 +0xba84, 0x457c, 0xfc24, 0x03dc, 0xef04, 0x10fc, 0xff6c, 0x0094,
9270 +0xdd84, 0x227c, 0xfe54, 0x01ac, 0xf7c4, 0x083c, 0xfff8, 0x0008,
9271 +0x8684, 0x797c, 0xf8e4, 0x071c, 0xe204, 0x1dfc, 0xfe9c, 0x0164,
9272 +0xc384, 0x3c7c, 0xfcb4, 0x034c, 0xf144, 0x0ebc, 0xff90, 0x0070,
9273 +0xa684, 0x597c, 0xfae4, 0x051c, 0xea04, 0x15fc, 0xff1c, 0x00e4,
9274 +0xd384, 0x2c7c, 0xfdb4, 0x024c, 0xf544, 0x0abc, 0xffd0, 0x0030,
9275 +0x9684, 0x697c, 0xf9e4, 0x061c, 0xe604, 0x19fc, 0xfedc, 0x0124,
9276 +0xcb84, 0x347c, 0xfd34, 0x02cc, 0xf344, 0x0cbc, 0xffb0, 0x0050,
9277 +0xb684, 0x497c, 0xfbe4, 0x041c, 0xee04, 0x11fc, 0xff5c, 0x00a4,
9278 +0xdb84, 0x247c, 0xfe34, 0x01cc, 0xf744, 0x08bc, 0xfff0, 0x0010,
9279 +0x8e84, 0x717c, 0xf964, 0x069c, 0xe404, 0x1bfc, 0xfebc, 0x0144,
9280 +0xc784, 0x387c, 0xfcf4, 0x030c, 0xf244, 0x0dbc, 0xffa0, 0x0060,
9281 +0xae84, 0x517c, 0xfb64, 0x049c, 0xec04, 0x13fc, 0xff3c, 0x00c4,
9282 +0xd784, 0x287c, 0xfdf4, 0x020c, 0xf644, 0x09bc, 0xffe0, 0x0020,
9283 +0x9e84, 0x617c, 0xfa64, 0x059c, 0xe804, 0x17fc, 0xfefc, 0x0104,
9284 +0xcf84, 0x307c, 0xfd74, 0x028c, 0xf444, 0x0bbc, 0xffc0, 0x0040,
9285 +0xbe84, 0x417c, 0xfc64, 0x039c, 0xf004, 0x0ffc, 0xff7c, 0x0084,
9286 +0xdf84, 0x207c, 0xfe74, 0x018c, 0xf844, 0x07bc, 0x0000, 0x0000
9287 +};
9288 +
9289 +const unsigned char capiINT2ULAW[16384] = {
9290 +255,127,127,191,191,63,63,223,223,95,95,159,159,31,31,239,
9291 +239,111,111,175,175,47,47,207,207,79,79,143,143,15,15,247,
9292 +247,247,247,119,119,119,119,183,183,183,183,55,55,55,55,215,
9293 +215,215,215,87,87,87,87,151,151,151,151,23,23,23,23,231,
9294 +231,231,231,103,103,103,103,167,167,167,167,39,39,39,39,199,
9295 +199,199,199,71,71,71,71,135,135,135,135,7,7,7,7,251,
9296 +251,251,251,251,251,251,251,123,123,123,123,123,123,123,123,187,
9297 +187,187,187,187,187,187,187,59,59,59,59,59,59,59,59,219,
9298 +219,219,219,219,219,219,219,91,91,91,91,91,91,91,91,155,
9299 +155,155,155,155,155,155,155,27,27,27,27,27,27,27,27,235,
9300 +235,235,235,235,235,235,235,107,107,107,107,107,107,107,107,171,
9301 +171,171,171,171,171,171,171,43,43,43,43,43,43,43,43,203,
9302 +203,203,203,203,203,203,203,75,75,75,75,75,75,75,75,139,
9303 +139,139,139,139,139,139,139,11,11,11,11,11,11,11,11,243,
9304 +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,115,
9305 +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,179,
9306 +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,51,
9307 +51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,211,
9308 +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,83,
9309 +83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,147,
9310 +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,19,
9311 +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,227,
9312 +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,99,
9313 +99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,163,
9314 +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,35,
9315 +35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,195,
9316 +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,67,
9317 +67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,131,
9318 +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,3,
9319 +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,253,
9320 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
9321 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,125,
9322 +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
9323 +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,189,
9324 +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
9325 +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,61,
9326 +61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,
9327 +61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,221,
9328 +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
9329 +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,93,
9330 +93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,
9331 +93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,157,
9332 +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
9333 +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,29,
9334 +29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,
9335 +29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,237,
9336 +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,
9337 +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,109,
9338 +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
9339 +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,173,
9340 +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
9341 +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,45,
9342 +45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,
9343 +45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,205,
9344 +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
9345 +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,77,
9346 +77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
9347 +77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,141,
9348 +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
9349 +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,13,
9350 +13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
9351 +13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,245,
9352 +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
9353 +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
9354 +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
9355 +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,117,
9356 +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
9357 +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
9358 +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
9359 +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,181,
9360 +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
9361 +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
9362 +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
9363 +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,53,
9364 +53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
9365 +53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
9366 +53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
9367 +53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,213,
9368 +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
9369 +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
9370 +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
9371 +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,85,
9372 +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
9373 +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
9374 +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
9375 +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,149,
9376 +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
9377 +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
9378 +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
9379 +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,21,
9380 +21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
9381 +21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
9382 +21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
9383 +21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,229,
9384 +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
9385 +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
9386 +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
9387 +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,101,
9388 +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
9389 +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
9390 +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
9391 +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,165,
9392 +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
9393 +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
9394 +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
9395 +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,37,
9396 +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
9397 +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
9398 +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
9399 +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,197,
9400 +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
9401 +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
9402 +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
9403 +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,69,
9404 +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
9405 +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
9406 +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
9407 +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,133,
9408 +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
9409 +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
9410 +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
9411 +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,5,
9412 +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
9413 +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
9414 +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
9415 +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,249,
9416 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
9417 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
9418 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
9419 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
9420 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
9421 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
9422 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
9423 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,121,
9424 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
9425 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
9426 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
9427 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
9428 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
9429 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
9430 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
9431 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,185,
9432 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
9433 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
9434 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
9435 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
9436 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
9437 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
9438 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
9439 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,57,
9440 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
9441 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
9442 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
9443 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
9444 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
9445 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
9446 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
9447 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,217,
9448 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
9449 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
9450 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
9451 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
9452 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
9453 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
9454 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
9455 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,89,
9456 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
9457 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
9458 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
9459 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
9460 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
9461 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
9462 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
9463 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,153,
9464 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
9465 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
9466 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
9467 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
9468 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
9469 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
9470 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
9471 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,25,
9472 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
9473 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
9474 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
9475 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
9476 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
9477 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
9478 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
9479 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,233,
9480 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
9481 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
9482 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
9483 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
9484 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
9485 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
9486 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
9487 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,105,
9488 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
9489 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
9490 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
9491 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
9492 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
9493 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
9494 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
9495 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,169,
9496 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
9497 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
9498 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
9499 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
9500 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
9501 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
9502 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
9503 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,41,
9504 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
9505 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
9506 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
9507 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
9508 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
9509 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
9510 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
9511 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,201,
9512 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
9513 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
9514 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
9515 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
9516 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
9517 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
9518 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
9519 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,73,
9520 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
9521 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
9522 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
9523 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
9524 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
9525 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
9526 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
9527 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,137,
9528 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
9529 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
9530 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
9531 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
9532 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
9533 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
9534 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
9535 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,9,
9536 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9537 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9538 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9539 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9540 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9541 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9542 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9543 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,241,
9544 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
9545 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
9546 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
9547 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
9548 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
9549 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
9550 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
9551 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
9552 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
9553 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
9554 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
9555 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
9556 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
9557 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
9558 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
9559 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,113,
9560 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
9561 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
9562 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
9563 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
9564 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
9565 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
9566 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
9567 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
9568 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
9569 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
9570 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
9571 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
9572 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
9573 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
9574 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
9575 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,177,
9576 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
9577 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
9578 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
9579 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
9580 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
9581 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
9582 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
9583 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
9584 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
9585 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
9586 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
9587 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
9588 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
9589 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
9590 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
9591 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,49,
9592 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
9593 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
9594 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
9595 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
9596 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
9597 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
9598 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
9599 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
9600 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
9601 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
9602 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
9603 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
9604 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
9605 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
9606 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
9607 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,209,
9608 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
9609 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
9610 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
9611 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
9612 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
9613 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
9614 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
9615 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
9616 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
9617 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
9618 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
9619 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
9620 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
9621 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
9622 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
9623 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,81,
9624 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
9625 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
9626 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
9627 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
9628 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
9629 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
9630 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
9631 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
9632 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
9633 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
9634 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
9635 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
9636 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
9637 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
9638 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
9639 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,145,
9640 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
9641 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
9642 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
9643 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
9644 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
9645 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
9646 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
9647 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
9648 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
9649 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
9650 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
9651 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
9652 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
9653 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
9654 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
9655 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,17,
9656 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
9657 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
9658 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
9659 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
9660 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
9661 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
9662 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
9663 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
9664 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
9665 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
9666 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
9667 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
9668 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
9669 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
9670 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
9671 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,225,
9672 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
9673 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
9674 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
9675 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
9676 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
9677 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
9678 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
9679 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
9680 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
9681 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
9682 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
9683 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
9684 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
9685 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
9686 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
9687 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,97,
9688 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
9689 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
9690 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
9691 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
9692 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
9693 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
9694 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
9695 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
9696 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
9697 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
9698 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
9699 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
9700 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
9701 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
9702 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
9703 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,161,
9704 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
9705 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
9706 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
9707 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
9708 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
9709 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
9710 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
9711 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
9712 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
9713 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
9714 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
9715 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
9716 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
9717 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
9718 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
9719 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,33,
9720 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
9721 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
9722 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
9723 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
9724 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
9725 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
9726 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
9727 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
9728 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
9729 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
9730 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
9731 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
9732 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
9733 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
9734 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
9735 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,193,
9736 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
9737 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
9738 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
9739 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
9740 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
9741 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
9742 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
9743 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
9744 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
9745 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
9746 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
9747 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
9748 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
9749 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
9750 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
9751 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,65,
9752 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
9753 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
9754 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
9755 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
9756 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
9757 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
9758 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
9759 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
9760 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
9761 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
9762 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
9763 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
9764 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
9765 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
9766 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
9767 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,129,
9768 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
9769 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
9770 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
9771 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
9772 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
9773 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
9774 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
9775 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
9776 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
9777 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
9778 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
9779 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
9780 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
9781 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
9782 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
9783 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,1,
9784 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9785 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9786 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9787 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9788 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9789 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9790 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9791 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9792 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9793 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9794 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9795 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9796 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9797 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9798 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9799 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9800 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9801 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9802 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9803 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9804 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9805 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9806 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9807 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9808 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9809 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9810 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9811 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9812 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9813 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9814 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9815 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9816 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9817 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9818 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9819 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9820 +64,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
9821 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
9822 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
9823 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
9824 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
9825 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
9826 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
9827 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
9828 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
9829 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
9830 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
9831 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
9832 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
9833 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
9834 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
9835 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
9836 +128,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9837 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9838 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9839 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9840 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9841 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9842 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9843 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9844 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9845 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9846 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9847 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9848 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9849 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9850 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9851 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
9852 +64,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
9853 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
9854 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
9855 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
9856 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
9857 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
9858 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
9859 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
9860 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
9861 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
9862 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
9863 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
9864 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
9865 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
9866 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
9867 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
9868 +192,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
9869 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
9870 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
9871 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
9872 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
9873 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
9874 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
9875 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
9876 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
9877 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
9878 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
9879 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
9880 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
9881 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
9882 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
9883 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
9884 +32,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
9885 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
9886 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
9887 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
9888 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
9889 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
9890 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
9891 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
9892 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
9893 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
9894 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
9895 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
9896 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
9897 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
9898 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
9899 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
9900 +160,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
9901 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
9902 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
9903 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
9904 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
9905 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
9906 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
9907 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
9908 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
9909 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
9910 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
9911 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
9912 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
9913 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
9914 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
9915 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
9916 +96,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
9917 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
9918 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
9919 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
9920 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
9921 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
9922 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
9923 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
9924 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
9925 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
9926 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
9927 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
9928 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
9929 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
9930 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
9931 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
9932 +224,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
9933 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
9934 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
9935 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
9936 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
9937 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
9938 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
9939 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
9940 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
9941 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
9942 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
9943 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
9944 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
9945 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
9946 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
9947 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
9948 +16,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
9949 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
9950 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
9951 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
9952 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
9953 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
9954 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
9955 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
9956 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
9957 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
9958 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
9959 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
9960 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
9961 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
9962 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
9963 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
9964 +144,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
9965 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
9966 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
9967 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
9968 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
9969 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
9970 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
9971 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
9972 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
9973 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
9974 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
9975 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
9976 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
9977 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
9978 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
9979 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
9980 +80,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
9981 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
9982 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
9983 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
9984 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
9985 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
9986 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
9987 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
9988 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
9989 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
9990 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
9991 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
9992 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
9993 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
9994 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
9995 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
9996 +208,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
9997 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
9998 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
9999 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10000 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10001 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10002 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10003 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10004 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10005 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10006 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10007 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10008 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10009 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10010 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10011 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10012 +48,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10013 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10014 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10015 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10016 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10017 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10018 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10019 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10020 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10021 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10022 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10023 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10024 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10025 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10026 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10027 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10028 +176,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10029 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10030 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10031 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10032 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10033 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10034 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10035 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10036 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10037 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10038 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10039 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10040 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10041 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10042 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10043 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10044 +112,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10045 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10046 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10047 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10048 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10049 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10050 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10051 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10052 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10053 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10054 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10055 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10056 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10057 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10058 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10059 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10060 +240,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
10061 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
10062 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
10063 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
10064 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
10065 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
10066 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
10067 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
10068 +8,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
10069 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
10070 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
10071 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
10072 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
10073 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
10074 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
10075 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
10076 +136,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
10077 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
10078 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
10079 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
10080 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
10081 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
10082 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
10083 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
10084 +72,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
10085 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
10086 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
10087 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
10088 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
10089 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
10090 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
10091 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
10092 +200,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
10093 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
10094 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
10095 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
10096 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
10097 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
10098 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
10099 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
10100 +40,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
10101 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
10102 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
10103 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
10104 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
10105 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
10106 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
10107 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
10108 +168,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
10109 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
10110 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
10111 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
10112 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
10113 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
10114 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
10115 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
10116 +104,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
10117 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
10118 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
10119 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
10120 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
10121 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
10122 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
10123 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
10124 +232,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
10125 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
10126 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
10127 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
10128 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
10129 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
10130 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
10131 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
10132 +24,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
10133 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
10134 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
10135 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
10136 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
10137 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
10138 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
10139 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
10140 +152,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
10141 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
10142 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
10143 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
10144 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
10145 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
10146 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
10147 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
10148 +88,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
10149 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
10150 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
10151 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
10152 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
10153 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
10154 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
10155 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
10156 +216,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
10157 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
10158 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
10159 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
10160 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
10161 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
10162 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
10163 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
10164 +56,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
10165 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
10166 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
10167 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
10168 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
10169 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
10170 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
10171 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
10172 +184,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
10173 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
10174 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
10175 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
10176 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
10177 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
10178 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
10179 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
10180 +120,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
10181 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
10182 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
10183 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
10184 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
10185 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
10186 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
10187 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
10188 +248,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
10189 +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
10190 +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
10191 +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
10192 +4,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
10193 +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
10194 +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
10195 +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
10196 +132,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
10197 +68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
10198 +68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
10199 +68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
10200 +68,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
10201 +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
10202 +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
10203 +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
10204 +196,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
10205 +36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
10206 +36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
10207 +36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
10208 +36,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
10209 +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
10210 +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
10211 +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
10212 +164,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
10213 +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
10214 +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
10215 +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
10216 +100,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
10217 +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
10218 +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
10219 +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
10220 +228,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
10221 +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
10222 +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
10223 +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
10224 +20,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
10225 +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
10226 +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
10227 +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
10228 +148,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10229 +84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10230 +84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10231 +84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10232 +84,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
10233 +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
10234 +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
10235 +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
10236 +212,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
10237 +52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
10238 +52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
10239 +52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
10240 +52,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
10241 +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
10242 +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
10243 +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
10244 +180,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
10245 +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
10246 +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
10247 +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
10248 +116,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
10249 +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
10250 +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
10251 +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
10252 +244,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
10253 +12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
10254 +12,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
10255 +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
10256 +140,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
10257 +76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
10258 +76,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
10259 +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
10260 +204,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
10261 +44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
10262 +44,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
10263 +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
10264 +172,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
10265 +108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
10266 +108,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
10267 +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
10268 +236,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
10269 +28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
10270 +28,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
10271 +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
10272 +156,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
10273 +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
10274 +92,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
10275 +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
10276 +220,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
10277 +60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
10278 +60,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
10279 +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
10280 +188,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
10281 +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
10282 +124,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
10283 +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
10284 +252,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
10285 +2,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,
10286 +130,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
10287 +66,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,
10288 +194,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
10289 +34,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,
10290 +162,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,
10291 +98,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,
10292 +226,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,
10293 +18,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,
10294 +146,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,
10295 +82,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,
10296 +210,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
10297 +50,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,
10298 +178,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
10299 +114,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,
10300 +242,10,10,10,10,10,10,10,10,138,138,138,138,138,138,138,
10301 +138,74,74,74,74,74,74,74,74,202,202,202,202,202,202,202,
10302 +202,42,42,42,42,42,42,42,42,170,170,170,170,170,170,170,
10303 +170,106,106,106,106,106,106,106,106,234,234,234,234,234,234,234,
10304 +234,26,26,26,26,26,26,26,26,154,154,154,154,154,154,154,
10305 +154,90,90,90,90,90,90,90,90,218,218,218,218,218,218,218,
10306 +218,58,58,58,58,58,58,58,58,186,186,186,186,186,186,186,
10307 +186,122,122,122,122,122,122,122,122,250,250,250,250,250,250,250,
10308 +250,6,6,6,6,134,134,134,134,70,70,70,70,198,198,198,
10309 +198,38,38,38,38,166,166,166,166,102,102,102,102,230,230,230,
10310 +230,22,22,22,22,150,150,150,150,86,86,86,86,214,214,214,
10311 +214,54,54,54,54,182,182,182,182,118,118,118,118,246,246,246,
10312 +246,14,14,142,142,78,78,206,206,46,46,174,174,110,110,238,
10313 +238,30,30,158,158,94,94,222,222,62,62,190,190,126,126,254,
10314 +};
10315 +#else
10316 +static short capiALAW2INT[] =
10317 +{
10318 + 0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4,
10319 + 0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74,
10320 + 0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4,
10321 + 0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64,
10322 + 0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4,
10323 + 0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4,
10324 + 0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4,
10325 + 0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4,
10326 + 0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64,
10327 + 0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34,
10328 + 0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844,
10329 + 0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24,
10330 + 0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64,
10331 + 0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4,
10332 + 0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964,
10333 + 0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4,
10334 + 0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24,
10335 + 0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94,
10336 + 0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924,
10337 + 0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94,
10338 + 0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24,
10339 + 0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14,
10340 + 0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24,
10341 + 0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14,
10342 + 0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4,
10343 + 0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54,
10344 + 0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4,
10345 + 0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64,
10346 + 0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4,
10347 + 0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4,
10348 + 0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4,
10349 + 0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4
10350 +};
10351 +
10352 +const unsigned char capiINT2ALAW[8192] = {
10353 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10354 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10355 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10356 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10357 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10358 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10359 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10360 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10361 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10362 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10363 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10364 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10365 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10366 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10367 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10368 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10369 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10370 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10371 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10372 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10373 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10374 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10375 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10376 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10377 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10378 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10379 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10380 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10381 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10382 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10383 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10384 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10385 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10386 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10387 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10388 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10389 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10390 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10391 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10392 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10393 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10394 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10395 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10396 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10397 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10398 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10399 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10400 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10401 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10402 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10403 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10404 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10405 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10406 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10407 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10408 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10409 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10410 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10411 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10412 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10413 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10414 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10415 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10416 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10417 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10418 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10419 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10420 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10421 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10422 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10423 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10424 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10425 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10426 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10427 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10428 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10429 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10430 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10431 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10432 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10433 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10434 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10435 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10436 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10437 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10438 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10439 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10440 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10441 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10442 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10443 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10444 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10445 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10446 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10447 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10448 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10449 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10450 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10451 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10452 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10453 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10454 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10455 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10456 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10457 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10458 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10459 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10460 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10461 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10462 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10463 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10464 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10465 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10466 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10467 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10468 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10469 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10470 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10471 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10472 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10473 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10474 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10475 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10476 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10477 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10478 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10479 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10480 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10481 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10482 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10483 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10484 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
10485 + 212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
10486 + 212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
10487 + 212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
10488 + 212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
10489 + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
10490 + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
10491 + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
10492 + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
10493 + 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
10494 + 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
10495 + 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
10496 + 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
10497 + 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
10498 + 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
10499 + 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
10500 + 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
10501 + 244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
10502 + 244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
10503 + 244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
10504 + 244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
10505 + 52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
10506 + 52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
10507 + 52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
10508 + 52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
10509 + 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
10510 + 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
10511 + 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
10512 + 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
10513 + 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
10514 + 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
10515 + 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
10516 + 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
10517 + 196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
10518 + 196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
10519 + 196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
10520 + 196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
10521 + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
10522 + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
10523 + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
10524 + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
10525 + 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
10526 + 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
10527 + 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
10528 + 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
10529 + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
10530 + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
10531 + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
10532 + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
10533 + 228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
10534 + 228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
10535 + 228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
10536 + 228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
10537 + 36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
10538 + 36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
10539 + 36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
10540 + 36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
10541 + 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
10542 + 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
10543 + 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
10544 + 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
10545 + 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
10546 + 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
10547 + 220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
10548 + 220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
10549 + 28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
10550 + 28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
10551 + 156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
10552 + 156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
10553 + 124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
10554 + 124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
10555 + 252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
10556 + 252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
10557 + 60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
10558 + 60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
10559 + 188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
10560 + 188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
10561 + 76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
10562 + 76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
10563 + 204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
10564 + 204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
10565 + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
10566 + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
10567 + 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
10568 + 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
10569 + 108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
10570 + 108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
10571 + 236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
10572 + 236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
10573 + 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
10574 + 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
10575 + 172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
10576 + 172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
10577 + 80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
10578 + 208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
10579 + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
10580 + 144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
10581 + 112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
10582 + 240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
10583 + 48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
10584 + 176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
10585 + 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
10586 + 192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
10587 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
10588 + 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
10589 + 96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
10590 + 224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
10591 + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
10592 + 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
10593 + 88,88,88,88,88,88,88,88,216,216,216,216,216,216,216,216,
10594 + 24,24,24,24,24,24,24,24,152,152,152,152,152,152,152,152,
10595 + 120,120,120,120,120,120,120,120,248,248,248,248,248,248,248,248,
10596 + 56,56,56,56,56,56,56,56,184,184,184,184,184,184,184,184,
10597 + 72,72,72,72,72,72,72,72,200,200,200,200,200,200,200,200,
10598 + 8,8,8,8,8,8,8,8,136,136,136,136,136,136,136,136,
10599 + 104,104,104,104,104,104,104,104,232,232,232,232,232,232,232,232,
10600 + 40,40,40,40,40,40,40,40,168,168,168,168,168,168,168,168,
10601 + 86,86,86,86,214,214,214,214,22,22,22,22,150,150,150,150,
10602 + 118,118,118,118,246,246,246,246,54,54,54,54,182,182,182,182,
10603 + 70,70,70,70,198,198,198,198,6,6,6,6,134,134,134,134,
10604 + 102,102,102,102,230,230,230,230,38,38,38,38,166,166,166,166,
10605 + 94,94,222,222,30,30,158,158,126,126,254,254,62,62,190,190,
10606 + 78,78,206,206,14,14,142,142,110,110,238,238,46,46,174,174,
10607 + 82,210,18,146,114,242,50,178,66,194,2,130,98,226,34,162,
10608 + 90,218,26,154,122,250,58,186,74,202,10,138,106,234,42,170,
10609 + 171,43,235,107,139,11,203,75,187,59,251,123,155,27,219,91,
10610 + 163,35,227,99,131,3,195,67,179,51,243,115,147,19,211,83,
10611 + 175,175,47,47,239,239,111,111,143,143,15,15,207,207,79,79,
10612 + 191,191,63,63,255,255,127,127,159,159,31,31,223,223,95,95,
10613 + 167,167,167,167,39,39,39,39,231,231,231,231,103,103,103,103,
10614 + 135,135,135,135,7,7,7,7,199,199,199,199,71,71,71,71,
10615 + 183,183,183,183,55,55,55,55,247,247,247,247,119,119,119,119,
10616 + 151,151,151,151,23,23,23,23,215,215,215,215,87,87,87,87,
10617 + 169,169,169,169,169,169,169,169,41,41,41,41,41,41,41,41,
10618 + 233,233,233,233,233,233,233,233,105,105,105,105,105,105,105,105,
10619 + 137,137,137,137,137,137,137,137,9,9,9,9,9,9,9,9,
10620 + 201,201,201,201,201,201,201,201,73,73,73,73,73,73,73,73,
10621 + 185,185,185,185,185,185,185,185,57,57,57,57,57,57,57,57,
10622 + 249,249,249,249,249,249,249,249,121,121,121,121,121,121,121,121,
10623 + 153,153,153,153,153,153,153,153,25,25,25,25,25,25,25,25,
10624 + 217,217,217,217,217,217,217,217,89,89,89,89,89,89,89,89,
10625 + 161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
10626 + 33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
10627 + 225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
10628 + 97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
10629 + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
10630 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
10631 + 193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
10632 + 65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
10633 + 177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
10634 + 49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
10635 + 241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
10636 + 113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
10637 + 145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
10638 + 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
10639 + 209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
10640 + 81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
10641 + 173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
10642 + 173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
10643 + 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,
10644 + 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,
10645 + 237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,
10646 + 237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,
10647 + 109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
10648 + 109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
10649 + 141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
10650 + 141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
10651 + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
10652 + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
10653 + 205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
10654 + 205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
10655 + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
10656 + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
10657 + 189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
10658 + 189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
10659 + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,
10660 + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,
10661 + 253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
10662 + 253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
10663 + 125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
10664 + 125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
10665 + 157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
10666 + 157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
10667 + 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,
10668 + 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,
10669 + 221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
10670 + 221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
10671 + 93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,
10672 + 93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,
10673 + 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
10674 + 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
10675 + 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
10676 + 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
10677 + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
10678 + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
10679 + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
10680 + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
10681 + 229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
10682 + 229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
10683 + 229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
10684 + 229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
10685 + 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
10686 + 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
10687 + 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
10688 + 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
10689 + 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
10690 + 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
10691 + 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
10692 + 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
10693 + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
10694 + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
10695 + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
10696 + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
10697 + 197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
10698 + 197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
10699 + 197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
10700 + 197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
10701 + 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
10702 + 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
10703 + 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
10704 + 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
10705 + 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
10706 + 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
10707 + 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
10708 + 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
10709 + 53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
10710 + 53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
10711 + 53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
10712 + 53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
10713 + 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
10714 + 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
10715 + 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
10716 + 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
10717 + 117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
10718 + 117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
10719 + 117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
10720 + 117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
10721 + 149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
10722 + 149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
10723 + 149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
10724 + 149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
10725 + 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
10726 + 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
10727 + 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
10728 + 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
10729 + 213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
10730 + 213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
10731 + 213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
10732 + 213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
10733 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10734 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10735 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10736 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10737 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10738 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10739 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10740 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10741 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10742 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10743 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10744 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10745 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10746 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10747 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10748 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10749 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10750 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10751 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10752 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10753 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10754 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10755 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10756 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10757 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10758 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10759 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10760 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10761 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10762 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10763 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10764 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10765 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10766 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10767 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10768 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10769 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10770 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10771 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10772 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10773 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10774 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10775 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10776 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10777 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10778 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10779 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10780 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10781 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10782 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10783 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10784 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10785 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10786 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10787 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10788 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10789 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10790 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10791 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10792 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10793 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10794 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10795 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10796 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10797 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10798 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10799 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10800 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10801 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10802 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10803 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10804 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10805 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10806 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10807 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10808 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10809 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10810 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10811 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10812 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10813 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10814 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10815 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10816 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10817 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10818 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10819 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10820 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10821 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10822 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10823 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10824 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10825 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10826 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10827 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10828 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10829 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10830 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10831 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10832 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10833 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10834 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10835 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10836 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10837 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10838 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10839 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10840 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10841 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10842 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10843 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10844 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10845 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10846 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10847 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10848 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10849 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10850 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10851 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10852 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10853 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10854 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10855 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10856 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10857 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10858 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10859 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10860 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10861 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10862 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10863 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
10864 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85
10865 +};
10866 +
10867 +#endif // CAPI_ULAW
10868 +#endif
10869 +
10870 diff -urN asterisk-1.2.4.orig/include/asterisk.h asterisk-1.2.4/include/asterisk.h
10871 --- asterisk-1.2.4.orig/include/asterisk.h 2005-11-30 04:37:37.000000000 +0100
10872 +++ asterisk-1.2.4/include/asterisk.h 2006-01-31 09:41:43.000000000 +0100
10873 @@ -36,6 +36,7 @@
10874 extern char ast_config_AST_PID[AST_CONFIG_MAX_PATH];
10875 extern char ast_config_AST_SOCKET[AST_CONFIG_MAX_PATH];
10876 extern char ast_config_AST_RUN_DIR[AST_CONFIG_MAX_PATH];
10877 +extern char ast_config_AST_SYMBOLIC_NAME[20];
10878 extern char ast_config_AST_CTL_PERMISSIONS[AST_CONFIG_MAX_PATH];
10879 extern char ast_config_AST_CTL_OWNER[AST_CONFIG_MAX_PATH];
10880 extern char ast_config_AST_CTL_GROUP[AST_CONFIG_MAX_PATH];
10881 diff -urN asterisk-1.2.4.orig/manager.c asterisk-1.2.4/manager.c
10882 --- asterisk-1.2.4.orig/manager.c 2006-01-09 05:52:16.000000000 +0100
10883 +++ asterisk-1.2.4/manager.c 2006-01-31 09:41:43.000000000 +0100
10884 @@ -11,6 +11,9 @@
10885 * the project provides a web site, mailing lists and IRC
10886 * channels for your use.
10887 *
10888 + * Copyright (C) 2003-2004, Junghanns.NET Gmbh
10889 + * Klaus-Peter Junghanns <kpj@junghanns.net>
10890 + *
10891 * This program is free software, distributed under the terms of
10892 * the GNU General Public License Version 2. See the LICENSE file
10893 * at the top of the source tree.
10894 @@ -62,6 +65,7 @@
10895 #include "asterisk/md5.h"
10896 #include "asterisk/acl.h"
10897 #include "asterisk/utils.h"
10898 +#include "asterisk/astdb.h"
10899
10900 struct fast_originate_helper {
10901 char tech[256];
10902 @@ -75,6 +79,8 @@
10903 char exten[256];
10904 char idtext[256];
10905 int priority;
10906 + int callingpres;
10907 + char uniqueid[64];
10908 struct ast_variable *vars;
10909 };
10910
10911 @@ -656,11 +662,17 @@
10912 {
10913 struct ast_channel *c = NULL;
10914 char *name = astman_get_header(m, "Channel");
10915 - if (ast_strlen_zero(name)) {
10916 - astman_send_error(s, m, "No channel specified");
10917 + char *uniqueid = astman_get_header(m, "Uniqueid");
10918 + if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
10919 + astman_send_error(s, m, "No channel or uniqueid specified");
10920 return 0;
10921 }
10922 - c = ast_get_channel_by_name_locked(name);
10923 + if (!ast_strlen_zero(uniqueid)) {
10924 + c = ast_get_channel_by_uniqueid_locked(uniqueid);
10925 + } else {
10926 + if (!ast_strlen_zero(name))
10927 + c = ast_get_channel_by_name_locked(name);
10928 + }
10929 if (!c) {
10930 astman_send_error(s, m, "No such channel");
10931 return 0;
10932 @@ -759,6 +771,7 @@
10933 }
10934
10935
10936 +
10937 /*! \brief action_status: Manager "status" command to show channels */
10938 /* Needs documentation... */
10939 static int action_status(struct mansession *s, struct message *m)
10940 @@ -865,32 +878,50 @@
10941 char *exten = astman_get_header(m, "Exten");
10942 char *context = astman_get_header(m, "Context");
10943 char *priority = astman_get_header(m, "Priority");
10944 + char *uniqueid = astman_get_header(m, "Uniqueid");
10945 + char *uniqueid2 = astman_get_header(m, "ExtraUniqueid");
10946 + char *exten2 = astman_get_header(m, "ExtraExten");
10947 + char *context2 = astman_get_header(m, "ExtraContext");
10948 + char *priority2 = astman_get_header(m, "ExtraPriority");
10949 struct ast_channel *chan, *chan2 = NULL;
10950 int pi = 0;
10951 + int pi2 = 0;
10952 int res;
10953
10954 - if (ast_strlen_zero(name)) {
10955 - astman_send_error(s, m, "Channel not specified");
10956 + if ((!name || ast_strlen_zero(name)) && (!uniqueid || ast_strlen_zero(uniqueid))) {
10957 + astman_send_error(s, m, "Channel or Uniqueid not specified");
10958 return 0;
10959 }
10960 if (!ast_strlen_zero(priority) && (sscanf(priority, "%d", &pi) != 1)) {
10961 astman_send_error(s, m, "Invalid priority\n");
10962 return 0;
10963 }
10964 - chan = ast_get_channel_by_name_locked(name);
10965 + if (uniqueid && (!ast_strlen_zero(uniqueid))) {
10966 + chan = ast_get_channel_by_uniqueid_locked(uniqueid);
10967 + } else {
10968 + chan = ast_get_channel_by_name_locked(name);
10969 + }
10970 if (!chan) {
10971 char buf[BUFSIZ];
10972 snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
10973 astman_send_error(s, m, buf);
10974 return 0;
10975 }
10976 - if (!ast_strlen_zero(name2))
10977 + if (!ast_strlen_zero(uniqueid2)) {
10978 + chan2 = ast_get_channel_by_uniqueid_locked(uniqueid2);
10979 + if (!ast_strlen_zero(priority2) && (sscanf(priority, "%d", &pi2) != 1)) {
10980 + astman_send_error(s, m, "Invalid priority2\n");
10981 + return 0;
10982 + }
10983 + } else {
10984 + if (!ast_strlen_zero(name2))
10985 chan2 = ast_get_channel_by_name_locked(name2);
10986 + }
10987 res = ast_async_goto(chan, context, exten, pi);
10988 if (!res) {
10989 - if (!ast_strlen_zero(name2)) {
10990 + if ((!ast_strlen_zero(name2)) || (!ast_strlen_zero(uniqueid2))){
10991 if (chan2)
10992 - res = ast_async_goto(chan2, context, exten, pi);
10993 + res = ast_async_goto(chan2, context2, exten2, pi2);
10994 else
10995 res = -1;
10996 if (!res)
10997 @@ -936,15 +967,15 @@
10998 struct ast_channel *chan = NULL;
10999
11000 if (!ast_strlen_zero(in->app)) {
11001 - res = ast_pbx_outgoing_app(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1,
11002 + res = ast_pbx_outgoing_app(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1, in->callingpres,
11003 !ast_strlen_zero(in->cid_num) ? in->cid_num : NULL,
11004 !ast_strlen_zero(in->cid_name) ? in->cid_name : NULL,
11005 - in->vars, &chan);
11006 + in->vars, &chan, in->uniqueid);
11007 } else {
11008 - res = ast_pbx_outgoing_exten(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1,
11009 + res = ast_pbx_outgoing_exten(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1, in->callingpres,
11010 !ast_strlen_zero(in->cid_num) ? in->cid_num : NULL,
11011 !ast_strlen_zero(in->cid_name) ? in->cid_name : NULL,
11012 - in->vars, &chan);
11013 + in->vars, &chan, in->uniqueid);
11014 }
11015 if (!res)
11016 manager_event(EVENT_FLAG_CALL,
11017 @@ -955,7 +986,7 @@
11018 "Exten: %s\r\n"
11019 "Reason: %d\r\n"
11020 "Uniqueid: %s\r\n",
11021 - in->idtext, in->tech, in->data, in->context, in->exten, reason, chan ? chan->uniqueid : "<null>");
11022 + in->idtext, in->tech, in->data, in->context, in->exten, reason, in->uniqueid ? in->uniqueid : (chan ? chan->uniqueid : "<null>"));
11023 else
11024 manager_event(EVENT_FLAG_CALL,
11025 "OriginateFailure",
11026 @@ -965,7 +996,7 @@
11027 "Exten: %s\r\n"
11028 "Reason: %d\r\n"
11029 "Uniqueid: %s\r\n",
11030 - in->idtext, in->tech, in->data, in->context, in->exten, reason, chan ? chan->uniqueid : "<null>");
11031 + in->idtext, in->tech, in->data, in->context, in->exten, reason, in->uniqueid ? in->uniqueid : (chan ? chan->uniqueid : "<null>"));
11032
11033 /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */
11034 if (chan)
11035 @@ -998,6 +1029,7 @@
11036 char *priority = astman_get_header(m, "Priority");
11037 char *timeout = astman_get_header(m, "Timeout");
11038 char *callerid = astman_get_header(m, "CallerID");
11039 + char *callingpres = astman_get_header(m, "CallingPres");
11040 char *account = astman_get_header(m, "Account");
11041 char *app = astman_get_header(m, "Application");
11042 char *appdata = astman_get_header(m, "Data");
11043 @@ -1006,12 +1038,15 @@
11044 struct ast_variable *vars = astman_get_variables(m);
11045 char *tech, *data;
11046 char *l=NULL, *n=NULL;
11047 + char *uniqueid;
11048 int pi = 0;
11049 + int cpresi = 0;
11050 int res;
11051 int to = 30000;
11052 int reason = 0;
11053 char tmp[256];
11054 char tmp2[256];
11055 + char idText[256] = "";
11056
11057 pthread_t th;
11058 pthread_attr_t attr;
11059 @@ -1027,6 +1062,10 @@
11060 astman_send_error(s, m, "Invalid timeout\n");
11061 return 0;
11062 }
11063 + if (!ast_strlen_zero(callingpres) && (sscanf(callingpres, "%d", &cpresi) != 1)) {
11064 + astman_send_error(s, m, "Invalid CallingPres\n");
11065 + return 0;
11066 + }
11067 ast_copy_string(tmp, name, sizeof(tmp));
11068 tech = tmp;
11069 data = strchr(tmp, '/');
11070 @@ -1053,6 +1092,7 @@
11071 newvar->next = vars;
11072 vars = newvar;
11073 }
11074 + uniqueid = ast_alloc_uniqueid();
11075 if (ast_true(async)) {
11076 struct fast_originate_helper *fast = malloc(sizeof(struct fast_originate_helper));
11077 if (!fast) {
11078 @@ -1072,8 +1112,10 @@
11079 fast->vars = vars;
11080 ast_copy_string(fast->context, context, sizeof(fast->context));
11081 ast_copy_string(fast->exten, exten, sizeof(fast->exten));
11082 + ast_copy_string(fast->uniqueid, uniqueid, sizeof(fast->uniqueid));
11083 fast->timeout = to;
11084 fast->priority = pi;
11085 + fast->callingpres = cpresi;
11086 pthread_attr_init(&attr);
11087 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11088 if (ast_pthread_create(&th, &attr, fast_originate, fast)) {
11089 @@ -1083,19 +1125,28 @@
11090 }
11091 }
11092 } else if (!ast_strlen_zero(app)) {
11093 - res = ast_pbx_outgoing_app(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, l, n, vars, NULL);
11094 + res = ast_pbx_outgoing_app(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, cpresi, l, n, vars, NULL, uniqueid);
11095 } else {
11096 if (exten && context && pi)
11097 - res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, l, n, vars, NULL);
11098 + res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, cpresi, l, n, vars, NULL, uniqueid);
11099 else {
11100 astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
11101 return 0;
11102 }
11103 }
11104 - if (!res)
11105 - astman_send_ack(s, m, "Originate successfully queued");
11106 - else
11107 + if (!res) {
11108 + if (id && !ast_strlen_zero(id)) {
11109 + snprintf(idText,256,"ActionID: %s\r\n",id);
11110 + }
11111 + ast_cli(s->fd, "Response: Success\r\n"
11112 + "%s"
11113 + "Message: Originate successfully queued\r\n"
11114 + "Uniqueid: %s\r\n"
11115 + "\r\n",
11116 + idText, uniqueid);
11117 + } else {
11118 astman_send_error(s, m, "Originate failed");
11119 + }
11120 return 0;
11121 }
11122
11123 @@ -1569,10 +1620,10 @@
11124 return 0;
11125 }
11126
11127 -static int manager_state_cb(char *context, char *exten, int state, void *data)
11128 +static int manager_state_cb(char *context, char *exten, int state, void *data, char *cid_num, char *cid_name)
11129 {
11130 /* Notify managers of change */
11131 - manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nStatus: %d\r\n", exten, context, state);
11132 + 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);
11133 return 0;
11134 }
11135
11136 diff -urN asterisk-1.2.4.orig/pbx/pbx_spool.c asterisk-1.2.4/pbx/pbx_spool.c
11137 --- asterisk-1.2.4.orig/pbx/pbx_spool.c 2006-01-09 21:08:24.000000000 +0100
11138 +++ asterisk-1.2.4/pbx/pbx_spool.c 2006-01-31 09:41:43.000000000 +0100
11139 @@ -260,11 +260,11 @@
11140 if (!ast_strlen_zero(o->app)) {
11141 if (option_verbose > 2)
11142 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);
11143 - 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, NULL);
11144 + 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, NULL, NULL);
11145 } else {
11146 if (option_verbose > 2)
11147 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);
11148 - 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, NULL);
11149 + 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, NULL, NULL);
11150 }
11151 if (res) {
11152 ast_log(LOG_NOTICE, "Call failed to go through, reason %d\n", reason);
11153 diff -urN asterisk-1.2.4.orig/pbx.c asterisk-1.2.4/pbx.c
11154 --- asterisk-1.2.4.orig/pbx.c 2006-01-22 03:05:41.000000000 +0100
11155 +++ asterisk-1.2.4/pbx.c 2006-01-31 09:41:43.000000000 +0100
11156 @@ -350,7 +350,8 @@
11157
11158 { "Hangup", pbx_builtin_hangup,
11159 "Hang up the calling channel",
11160 - " Hangup(): This application will hang up the calling channel.\n"
11161 + " Hangup(Cause): Unconditionally hangs up a given channel by returning -1 always.\n"
11162 + " If cause is given, it will set the hangup cause accordingly.\n"
11163 },
11164
11165 { "NoOp", pbx_builtin_noop,
11166 @@ -1871,7 +1872,7 @@
11167 return ast_extension_state2(e); /* Check all devices in the hint */
11168 }
11169
11170 -void ast_hint_state_changed(const char *device)
11171 +void ast_hint_state_changed(const char *device, const char *cid_num, const char *cid_name)
11172 {
11173 struct ast_hint *hint;
11174 struct ast_state_cb *cblist;
11175 @@ -1899,11 +1900,11 @@
11176
11177 /* For general callbacks */
11178 for (cblist = statecbs; cblist; cblist = cblist->next)
11179 - cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
11180 + cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
11181
11182 /* For extension callbacks */
11183 for (cblist = hint->callbacks; cblist; cblist = cblist->next)
11184 - cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
11185 + cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
11186
11187 hint->laststate = state;
11188 break;
11189 @@ -2144,7 +2145,7 @@
11190 /* Notify with -1 and remove all callbacks */
11191 cbprev = cblist;
11192 cblist = cblist->next;
11193 - cbprev->callback(list->exten->parent->name, list->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
11194 + cbprev->callback(list->exten->parent->name, list->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data, NULL, NULL);
11195 free(cbprev);
11196 }
11197 list->callbacks = NULL;
11198 @@ -3758,7 +3759,7 @@
11199 while (thiscb) {
11200 prevcb = thiscb;
11201 thiscb = thiscb->next;
11202 - prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data);
11203 + prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data, NULL, NULL);
11204 free(prevcb);
11205 }
11206 } else {
11207 @@ -4957,7 +4958,7 @@
11208 return 0; /* success */
11209 }
11210
11211 -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, struct ast_channel **channel)
11212 +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, struct ast_channel **channel, char *uniqueid)
11213 {
11214 struct ast_channel *chan;
11215 struct async_stat *as;
11216 @@ -4967,7 +4968,7 @@
11217
11218 if (sync) {
11219 LOAD_OH(oh);
11220 - chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
11221 + chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
11222 if (channel) {
11223 *channel = chan;
11224 if (chan)
11225 @@ -5063,7 +5064,7 @@
11226 goto outgoing_exten_cleanup;
11227 }
11228 memset(as, 0, sizeof(struct async_stat));
11229 - chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
11230 + chan = ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, uniqueid);
11231 if (channel) {
11232 *channel = chan;
11233 if (chan)
11234 @@ -5105,7 +5106,7 @@
11235 pthread_t t;
11236 };
11237
11238 -static void *ast_pbx_run_app(void *data)
11239 +void *ast_pbx_run_app(void *data)
11240 {
11241 struct app_tmp *tmp = data;
11242 struct ast_app *app;
11243 @@ -5121,7 +5122,7 @@
11244 return NULL;
11245 }
11246
11247 -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, struct ast_channel **locked_channel)
11248 +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, struct ast_channel **locked_channel, char *uniqueid)
11249 {
11250 struct ast_channel *chan;
11251 struct async_stat *as;
11252 @@ -5140,7 +5141,7 @@
11253 goto outgoing_app_cleanup;
11254 }
11255 if (sync) {
11256 - chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
11257 + chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
11258 if (chan) {
11259 if (chan->cdr) { /* check if the channel already has a cdr record, if not give it one */
11260 ast_log(LOG_WARNING, "%s already has a call record??\n", chan->name);
11261 @@ -5225,7 +5226,8 @@
11262 goto outgoing_app_cleanup;
11263 }
11264 memset(as, 0, sizeof(struct async_stat));
11265 - chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
11266 + chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
11267 +// chan = ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, uniqueid);
11268 if (!chan) {
11269 free(as);
11270 res = -1;
11271 @@ -5510,6 +5512,9 @@
11272 */
11273 static int pbx_builtin_hangup(struct ast_channel *chan, void *data)
11274 {
11275 + /* Copy the hangup cause as specified */
11276 + if (data)
11277 + chan->hangupcause = atoi(data);
11278 /* Just return non-zero and it will hang up */
11279 if (!chan->hangupcause)
11280 chan->hangupcause = AST_CAUSE_NORMAL_CLEARING;
11281 @@ -6151,6 +6156,9 @@
11282 return -1;
11283 }
11284 }
11285 + if (chan->_state != AST_STATE_UP) {
11286 + ast_answer(chan);
11287 + }
11288 return res = ast_say_number(chan, atoi((char *) tmp), "", chan->language, options);
11289 }
11290
11291 @@ -6158,8 +6166,12 @@
11292 {
11293 int res = 0;
11294
11295 - if (data)
11296 + if (data) {
11297 + if (chan->_state != AST_STATE_UP) {
11298 + ast_answer(chan);
11299 + }
11300 res = ast_say_digit_str(chan, (char *)data, "", chan->language);
11301 + }
11302 return res;
11303 }
11304
11305 @@ -6167,8 +6179,12 @@
11306 {
11307 int res = 0;
11308
11309 - if (data)
11310 + if (data) {
11311 + if (chan->_state != AST_STATE_UP) {
11312 + ast_answer(chan);
11313 + }
11314 res = ast_say_character_str(chan, (char *)data, "", chan->language);
11315 + }
11316 return res;
11317 }
11318
11319 @@ -6176,8 +6192,12 @@
11320 {
11321 int res = 0;
11322
11323 - if (data)
11324 + if (data) {
11325 + if (chan->_state != AST_STATE_UP) {
11326 + ast_answer(chan);
11327 + }
11328 res = ast_say_phonetic_str(chan, (char *)data, "", chan->language);
11329 + }
11330 return res;
11331 }
11332
11333 diff -urN asterisk-1.2.4.orig/res/Makefile asterisk-1.2.4/res/Makefile
11334 --- asterisk-1.2.4.orig/res/Makefile 2005-11-29 19:24:39.000000000 +0100
11335 +++ asterisk-1.2.4/res/Makefile 2006-01-31 09:41:43.000000000 +0100
11336 @@ -11,7 +11,7 @@
11337 # the GNU General Public License
11338 #
11339
11340 -MODS=res_indications.so res_monitor.so res_adsi.so res_agi.so res_features.so
11341 +MODS=res_indications.so res_monitor.so res_adsi.so res_agi.so res_features.so res_watchdog.so
11342
11343 ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/odbcinst.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/odbcinst.h),)
11344 ifneq (${OSARCH},FreeBSD)
11345 diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
11346 --- asterisk-1.2.4.orig/res/res_agi.c 2005-12-20 21:21:26.000000000 +0100
11347 +++ asterisk-1.2.4/res/res_agi.c 2006-01-31 09:41:43.000000000 +0100
11348 @@ -11,6 +11,9 @@
11349 * the project provides a web site, mailing lists and IRC
11350 * channels for your use.
11351 *
11352 + * Copyright (C) 2005 Junghanns.NET GmbH
11353 + * Klaus-Peter Junghanns <kpj@junghanns.net>
11354 + *
11355 * This program is free software, distributed under the terms of
11356 * the GNU General Public License Version 2. See the LICENSE file
11357 * at the top of the source tree.
11358 @@ -74,16 +77,19 @@
11359
11360 static char *app = "AGI";
11361
11362 +static char *xapp = "XAGI";
11363 +
11364 static char *eapp = "EAGI";
11365
11366 static char *deadapp = "DeadAGI";
11367
11368 static char *synopsis = "Executes an AGI compliant application";
11369 +static char *xsynopsis = "Executes an XAGI compliant application";
11370 static char *esynopsis = "Executes an EAGI compliant application";
11371 static char *deadsynopsis = "Executes AGI on a hungup channel";
11372
11373 static char *descrip =
11374 -" [E|Dead]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
11375 +" [E|Dead|X]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
11376 "program on a channel. AGI allows Asterisk to launch external programs\n"
11377 "written in any language to control a telephony channel, play audio,\n"
11378 "read DTMF digits, etc. by communicating with the AGI protocol on stdin\n"
11379 @@ -91,7 +97,9 @@
11380 "Returns -1 on hangup (except for DeadAGI) or if application requested\n"
11381 " hangup, or 0 on non-hangup exit. \n"
11382 "Using 'EAGI' provides enhanced AGI, with incoming audio available out of band"
11383 -"on file descriptor 3\n\n"
11384 +" on file descriptor 3\n"
11385 +"Using 'XAGI' provides enhanced AGI, with incoming audio available out of band"
11386 +" on file descriptor 3 and outgoing audio available out of band on file descriptor 4\n\n"
11387 "Use the CLI command 'show agi' to list available agi commands\n";
11388
11389 static int agidebug = 0;
11390 @@ -214,13 +222,14 @@
11391 return 0;
11392 }
11393
11394 -static int launch_script(char *script, char *argv[], int *fds, int *efd, int *opid)
11395 +static int launch_script(char *script, char *argv[], int *fds, int *efd, int *efd2, int *opid)
11396 {
11397 char tmp[256];
11398 int pid;
11399 int toast[2];
11400 int fromast[2];
11401 int audio[2];
11402 + int audio2[2];
11403 int x;
11404 int res;
11405 sigset_t signal_set;
11406 @@ -265,6 +274,33 @@
11407 return -1;
11408 }
11409 }
11410 + if (efd2) {
11411 + if (pipe(audio2)) {
11412 + ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
11413 + close(fromast[0]);
11414 + close(fromast[1]);
11415 + close(toast[0]);
11416 + close(toast[1]);
11417 + close(audio[0]);
11418 + close(audio[1]);
11419 + return -1;
11420 + }
11421 + res = fcntl(audio2[0], F_GETFL);
11422 + if (res > -1)
11423 + res = fcntl(audio2[0], F_SETFL, res | O_NONBLOCK);
11424 + if (res < 0) {
11425 + ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
11426 + close(fromast[0]);
11427 + close(fromast[1]);
11428 + close(toast[0]);
11429 + close(toast[1]);
11430 + close(audio[0]);
11431 + close(audio[1]);
11432 + close(audio2[0]);
11433 + close(audio2[1]);
11434 + return -1;
11435 + }
11436 + }
11437 pid = fork();
11438 if (pid < 0) {
11439 ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
11440 @@ -279,15 +315,19 @@
11441 } else {
11442 close(STDERR_FILENO + 1);
11443 }
11444 + if (efd2) {
11445 + dup2(audio2[1], STDERR_FILENO + 2);
11446 + } else {
11447 + close(STDERR_FILENO + 2);
11448 + }
11449
11450 /* unblock important signal handlers */
11451 if (sigfillset(&signal_set) || pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
11452 ast_log(LOG_WARNING, "unable to unblock signals for AGI script: %s\n", strerror(errno));
11453 exit(1);
11454 }
11455 -
11456 /* Close everything but stdin/out/error */
11457 - for (x=STDERR_FILENO + 2;x<1024;x++)
11458 + for (x=STDERR_FILENO + 3;x<1024;x++)
11459 close(x);
11460
11461 /* Don't run AGI scripts with realtime priority -- it causes audio stutter */
11462 @@ -306,6 +346,9 @@
11463 if (efd) {
11464 *efd = audio[1];
11465 }
11466 + if (efd2) {
11467 + *efd2 = audio2[0];
11468 + }
11469 /* close what we're not using in the parent */
11470 close(toast[1]);
11471 close(fromast[0]);
11472 @@ -314,6 +357,9 @@
11473 /* [PHM 12/18/03] */
11474 close(audio[0]);
11475 }
11476 + if (efd2) {
11477 + close(audio2[1]);
11478 + }
11479
11480 *opid = pid;
11481 return 0;
11482 @@ -344,7 +390,7 @@
11483 fdprintf(fd, "agi_context: %s\n", chan->context);
11484 fdprintf(fd, "agi_extension: %s\n", chan->exten);
11485 fdprintf(fd, "agi_priority: %d\n", chan->priority);
11486 - fdprintf(fd, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
11487 + fdprintf(fd, "agi_enhanced: %d%s\n", enhanced, ".0");
11488
11489 /* User information */
11490 fdprintf(fd, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
11491 @@ -376,7 +422,7 @@
11492 return RESULT_SHOWUSAGE;
11493 if (sscanf(argv[3], "%d", &to) != 1)
11494 return RESULT_SHOWUSAGE;
11495 - res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl);
11496 + res = ast_waitfordigit_full(chan, to, agi->audio_out, agi->ctrl);
11497 fdprintf(agi->fd, "200 result=%d\n", res);
11498 if (res >= 0)
11499 return RESULT_SUCCESS;
11500 @@ -552,7 +598,7 @@
11501 else
11502 return RESULT_FAILURE;
11503 }
11504 - res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
11505 + res = ast_waitstream_full(chan, argv[3], agi->audio_out, agi->ctrl);
11506 /* this is to check for if ast_waitstream closed the stream, we probably are at
11507 * the end of the stream, return that amount, else check for the amount */
11508 sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length;
11509 @@ -612,7 +658,7 @@
11510 else
11511 return RESULT_FAILURE;
11512 }
11513 - res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
11514 + res = ast_waitstream_full(chan, argv[3], agi->audio_out, agi->ctrl);
11515 /* this is to check for if ast_waitstream closed the stream, we probably are at
11516 * the end of the stream, return that amount, else check for the amount */
11517 sample_offset = (chan->stream)?ast_tellstream(fs):max_length;
11518 @@ -624,7 +670,7 @@
11519
11520 /* If the user didnt press a key, wait for digitTimeout*/
11521 if (res == 0 ) {
11522 - res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl);
11523 + res = ast_waitfordigit_full(chan, timeout, agi->audio_out, agi->ctrl);
11524 /* Make sure the new result is in the escape digits of the GET OPTION */
11525 if ( !strchr(edigits,res) )
11526 res=0;
11527 @@ -651,7 +697,7 @@
11528 return RESULT_SHOWUSAGE;
11529 if (sscanf(argv[2], "%d", &num) != 1)
11530 return RESULT_SHOWUSAGE;
11531 - res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio, agi->ctrl);
11532 + res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio_out, agi->ctrl);
11533 if (res == 1)
11534 return RESULT_SUCCESS;
11535 fdprintf(agi->fd, "200 result=%d\n", res);
11536 @@ -671,7 +717,7 @@
11537 if (sscanf(argv[2], "%d", &num) != 1)
11538 return RESULT_SHOWUSAGE;
11539
11540 - res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
11541 + res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio_out, agi->ctrl);
11542 if (res == 1) /* New command */
11543 return RESULT_SUCCESS;
11544 fdprintf(agi->fd, "200 result=%d\n", res);
11545 @@ -688,7 +734,7 @@
11546 if (argc != 4)
11547 return RESULT_SHOWUSAGE;
11548
11549 - res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
11550 + res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio_out, agi->ctrl);
11551 if (res == 1) /* New command */
11552 return RESULT_SUCCESS;
11553 fdprintf(agi->fd, "200 result=%d\n", res);
11554 @@ -778,7 +824,7 @@
11555 if (argc != 4)
11556 return RESULT_SHOWUSAGE;
11557
11558 - res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
11559 + res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio_out, agi->ctrl);
11560 if (res == 1) /* New command */
11561 return RESULT_SUCCESS;
11562 fdprintf(agi->fd, "200 result=%d\n", res);
11563 @@ -805,7 +851,7 @@
11564 max = atoi(argv[4]);
11565 else
11566 max = 1024;
11567 - res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl);
11568 + res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio_out, agi->ctrl);
11569 if (res == 2) /* New command */
11570 return RESULT_SUCCESS;
11571 else if (res == 1)
11572 @@ -1843,7 +1889,12 @@
11573 int ms;
11574 int returnstatus = 0;
11575 struct ast_frame *f;
11576 + struct ast_frame fr;
11577 char buf[2048];
11578 + char audiobuf[2048];
11579 + int audiobytes;
11580 + int fds[2];
11581 + int enhanced = 0;
11582 FILE *readf;
11583 /* how many times we'll retry if ast_waitfor_nandfs will return without either
11584 channel or file descriptor in case select is interrupted by a system call (EINTR) */
11585 @@ -1857,10 +1908,22 @@
11586 return -1;
11587 }
11588 setlinebuf(readf);
11589 - setup_env(chan, request, agi->fd, (agi->audio > -1));
11590 + if (agi->audio_out > -1) {
11591 + enhanced = 1;
11592 + }
11593 + if (agi->audio_in > -1) {
11594 + enhanced++;
11595 + }
11596 + setup_env(chan, request, agi->fd, enhanced);
11597 + fds[0] = agi->ctrl;
11598 + fds[1] = agi->audio_in;
11599 for (;;) {
11600 ms = -1;
11601 - c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
11602 + if (agi->audio_in > -1) {
11603 + c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, fds, 2, NULL, &outfd, &ms);
11604 + } else {
11605 + c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
11606 + }
11607 if (c) {
11608 retry = RETRY;
11609 /* Idle the channel until we get a command */
11610 @@ -1871,13 +1934,24 @@
11611 break;
11612 } else {
11613 /* If it's voice, write it to the audio pipe */
11614 - if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) {
11615 + if ((agi->audio_out > -1) && (f->frametype == AST_FRAME_VOICE)) {
11616 /* Write, ignoring errors */
11617 - write(agi->audio, f->data, f->datalen);
11618 + write(agi->audio_out, f->data, f->datalen);
11619 }
11620 ast_frfree(f);
11621 }
11622 } else if (outfd > -1) {
11623 + if ((agi->audio_in > -1) && (outfd == agi->audio_in)) {
11624 + audiobytes = read(agi->audio_in, audiobuf, sizeof(audiobuf));
11625 + if (audiobytes > 0) {
11626 + // ast_log(LOG_NOTICE, "read %d bytes of audio\n", audiobytes);
11627 + fr.frametype = AST_FRAME_VOICE;
11628 + fr.subclass = AST_FORMAT_SLINEAR;
11629 + fr.datalen = audiobytes;
11630 + fr.data = audiobuf;
11631 + ast_write(chan, &fr);
11632 + }
11633 + } else {
11634 retry = RETRY;
11635 if (!fgets(buf, sizeof(buf), readf)) {
11636 /* Program terminated */
11637 @@ -1899,6 +1973,7 @@
11638 if ((returnstatus < 0) || (returnstatus == AST_PBX_KEEPALIVE)) {
11639 break;
11640 }
11641 + }
11642 } else {
11643 if (--retry <= 0) {
11644 ast_log(LOG_WARNING, "No channel, no fd?\n");
11645 @@ -2005,6 +2080,7 @@
11646 int argc = 0;
11647 int fds[2];
11648 int efd = -1;
11649 + int efd2 = -1;
11650 int pid;
11651 char *stringp;
11652 AGI agi;
11653 @@ -2030,15 +2106,18 @@
11654 }
11655 }
11656 #endif
11657 - res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, &pid);
11658 + res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, (enhanced == 2) ? &efd2 : NULL, &pid);
11659 if (!res) {
11660 agi.fd = fds[1];
11661 agi.ctrl = fds[0];
11662 - agi.audio = efd;
11663 + agi.audio_out = efd;
11664 + agi.audio_in = efd2;
11665 res = run_agi(chan, argv[0], &agi, pid, dead);
11666 close(fds[1]);
11667 if (efd > -1)
11668 close(efd);
11669 + if (efd2 > -1)
11670 + close(efd2);
11671 }
11672 LOCAL_USER_REMOVE(u);
11673 return res;
11674 @@ -2072,6 +2151,35 @@
11675 return res;
11676 }
11677
11678 +static int xagi_exec(struct ast_channel *chan, void *data)
11679 +{
11680 + int readformat, writeformat;
11681 + int res;
11682 +
11683 + if (chan->_softhangup)
11684 + ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
11685 + readformat = chan->readformat;
11686 + if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
11687 + ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
11688 + return -1;
11689 + }
11690 + writeformat = chan->writeformat;
11691 + if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
11692 + ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
11693 + return -1;
11694 + }
11695 + res = agi_exec_full(chan, data, 2, 0);
11696 + if (!res) {
11697 + if (ast_set_read_format(chan, readformat)) {
11698 + ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat));
11699 + }
11700 + if (ast_set_write_format(chan, writeformat)) {
11701 + ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(writeformat));
11702 + }
11703 + }
11704 + return res;
11705 +}
11706 +
11707 static int deadagi_exec(struct ast_channel *chan, void *data)
11708 {
11709 return agi_exec_full(chan, data, 0, 1);
11710 @@ -2101,6 +2209,7 @@
11711 ast_cli_unregister(&dumpagihtml);
11712 ast_cli_unregister(&cli_debug);
11713 ast_cli_unregister(&cli_no_debug);
11714 + ast_unregister_application(xapp);
11715 ast_unregister_application(eapp);
11716 ast_unregister_application(deadapp);
11717 return ast_unregister_application(app);
11718 @@ -2114,6 +2223,7 @@
11719 ast_cli_register(&cli_no_debug);
11720 ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
11721 ast_register_application(eapp, eagi_exec, esynopsis, descrip);
11722 + ast_register_application(xapp, xagi_exec, xsynopsis, descrip);
11723 return ast_register_application(app, agi_exec, synopsis, descrip);
11724 }
11725
11726 diff -urN asterisk-1.2.4.orig/res/res_features.c asterisk-1.2.4/res/res_features.c
11727 --- asterisk-1.2.4.orig/res/res_features.c 2006-01-17 19:29:57.000000000 +0100
11728 +++ asterisk-1.2.4/res/res_features.c 2006-01-31 09:41:43.000000000 +0100
11729 @@ -11,6 +11,10 @@
11730 * the project provides a web site, mailing lists and IRC
11731 * channels for your use.
11732 *
11733 + * Copyright (C) 2004, Junghanns.NET GmbH
11734 + *
11735 + * Klaus-Peter Junghanns <kpj@junghanns.net>
11736 + *
11737 * This program is free software, distributed under the terms of
11738 * the GNU General Public License Version 2. See the LICENSE file
11739 * at the top of the source tree.
11740 @@ -56,6 +60,7 @@
11741 #include "asterisk/utils.h"
11742 #include "asterisk/adsi.h"
11743 #include "asterisk/monitor.h"
11744 +#include "asterisk/indications.h"
11745
11746 #ifdef __AST_DEBUG_MALLOC
11747 static void FREE(void *ptr)
11748 @@ -73,6 +78,7 @@
11749 #define AST_MAX_WATCHERS 256
11750
11751 static char *parkedcall = "ParkedCall";
11752 +static char *holdedcall = "HoldedCall";
11753
11754 /* No more than 45 seconds parked before you do something with them */
11755 static int parkingtime = DEFAULT_PARK_TIME;
11756 @@ -132,6 +138,20 @@
11757 "into the dialplan, although you should include the 'parkedcalls'\n"
11758 "context.\n";
11759
11760 +static char *autoanswerlogin = "AutoanswerLogin";
11761 +
11762 +static char *synopsis3 = "Log in for autoanswer";
11763 +
11764 +static char *descrip3 = "AutoanswerLogin(exten):"
11765 +"Used to login to the autoanswer application for an extension.\n";
11766 +
11767 +static char *autoanswer = "Autoanswer";
11768 +
11769 +static char *synopsis4 = "Autoanswer a call";
11770 +
11771 +static char *descrip4 = "Autoanswer(exten):"
11772 +"Used to autoanswer a call for an extension.\n";
11773 +
11774 static struct ast_app *monitor_app=NULL;
11775 static int monitor_ok=1;
11776
11777 @@ -150,12 +170,51 @@
11778 struct parkeduser *next;
11779 };
11780
11781 +struct holdeduser {
11782 + struct ast_channel *chan;
11783 + struct timeval start;
11784 + int parkingnum;
11785 + int cref;
11786 + int tei;
11787 + /* Where to go if our parking time expires */
11788 + char context[AST_MAX_EXTENSION];
11789 + char exten[AST_MAX_EXTENSION];
11790 + int priority;
11791 + int parkingtime;
11792 + char uniqueid[AST_MAX_UNIQUEID];
11793 + char uniqueidpeer[AST_MAX_UNIQUEID];
11794 + struct holdeduser *next;
11795 +};
11796 +
11797 +/* auto answer user */
11798 +struct aauser {
11799 + struct ast_channel *chan;
11800 + struct timeval start;
11801 + /* waiting on this extension/context */
11802 + char exten[AST_MAX_EXTENSION];
11803 + char context[AST_MAX_EXTENSION];
11804 + int priority;
11805 + int notquiteyet;
11806 + struct aauser *next;
11807 +};
11808 +
11809 +
11810 +static struct aauser *aalot;
11811 +AST_MUTEX_DEFINE_STATIC(autoanswer_lock);
11812 +static pthread_t autoanswer_thread;
11813 +
11814 static struct parkeduser *parkinglot;
11815
11816 +static struct holdeduser *holdlist;
11817 +
11818 AST_MUTEX_DEFINE_STATIC(parking_lock);
11819
11820 +AST_MUTEX_DEFINE_STATIC(holding_lock);
11821 +
11822 static pthread_t parking_thread;
11823
11824 +static pthread_t holding_thread;
11825 +
11826 STANDARD_LOCAL_USER;
11827
11828 LOCAL_USER_DECL;
11829 @@ -165,6 +224,12 @@
11830 return parking_ext;
11831 }
11832
11833 +char *ast_parking_con(void)
11834 +{
11835 + return parking_con;
11836 +}
11837 +
11838 +
11839 char *ast_pickup_ext(void)
11840 {
11841 return pickup_ext;
11842 @@ -362,10 +427,11 @@
11843 "Timeout: %ld\r\n"
11844 "CallerID: %s\r\n"
11845 "CallerIDName: %s\r\n"
11846 + "Unqiueid: %s\r\n\r\n"
11847 ,pu->parkingnum, pu->chan->name, peer->name
11848 ,(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL)
11849 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
11850 - ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
11851 + ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
11852 );
11853
11854 if (peer) {
11855 @@ -418,7 +484,8 @@
11856 ast_copy_string(chan->context, rchan->context, sizeof(chan->context));
11857 ast_copy_string(chan->exten, rchan->exten, sizeof(chan->exten));
11858 chan->priority = rchan->priority;
11859 -
11860 + /* might be dirty but we want trackable channels */
11861 + strncpy(chan->uniqueid, rchan->uniqueid, sizeof(chan->uniqueid) - 1);
11862 /* Make the masq execute */
11863 f = ast_read(chan);
11864 if (f)
11865 @@ -906,7 +973,7 @@
11866 }
11867
11868 /* find a feature by name */
11869 -static struct ast_call_feature *find_feature(char *name)
11870 +struct ast_call_feature *ast_find_feature(char *name)
11871 {
11872 struct ast_call_feature *tmp;
11873
11874 @@ -916,10 +983,21 @@
11875 break;
11876 }
11877 AST_LIST_UNLOCK(&feature_list);
11878 -
11879 return tmp;
11880 }
11881
11882 +struct ast_call_feature *ast_find_builtin_feature(char *name)
11883 +{
11884 + int x = 0;
11885 +
11886 + for (x = 0; x < FEATURES_COUNT; x++) {
11887 + if (!strcasecmp(name, builtin_features[x].sname)) {
11888 + return &builtin_features[x];
11889 + }
11890 + }
11891 + return NULL;
11892 +}
11893 +
11894 /* exec an app by feature */
11895 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
11896 {
11897 @@ -1014,7 +1092,7 @@
11898 return res;
11899
11900 while ((tok = strsep(&tmp, "#")) != NULL) {
11901 - feature = find_feature(tok);
11902 + feature = ast_find_feature(tok);
11903
11904 if (feature) {
11905 /* Feature is up for consideration */
11906 @@ -1064,7 +1142,7 @@
11907
11908 /* while we have a feature */
11909 while (NULL != (tok = strsep(&tmp, "#"))) {
11910 - if ((feature = find_feature(tok))) {
11911 + if ((feature = ast_find_feature(tok))) {
11912 if (ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
11913 if (ast_test_flag(feature, AST_FEATURE_FLAG_CALLER))
11914 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
11915 @@ -1089,7 +1167,7 @@
11916 struct ast_frame *f = NULL;
11917 int res = 0, ready = 0;
11918
11919 - if ((chan = ast_request(type, format, data, &cause))) {
11920 + if ((chan = ast_request(type, format, data, &cause, NULL))) {
11921 ast_set_callerid(chan, cid_num, cid_name, cid_num);
11922 ast_channel_inherit_variables(caller, chan);
11923 if (!ast_call(chan, data, timeout)) {
11924 @@ -1538,9 +1616,10 @@
11925 "Channel: %s\r\n"
11926 "CallerID: %s\r\n"
11927 "CallerIDName: %s\r\n"
11928 + "Uniqueid: %s\r\n\r\n"
11929 ,pu->parkingnum, pu->chan->name
11930 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
11931 - ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
11932 + ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
11933 );
11934
11935 if (option_verbose > 1)
11936 @@ -1583,9 +1662,10 @@
11937 "Channel: %s\r\n"
11938 "CallerID: %s\r\n"
11939 "CallerIDName: %s\r\n"
11940 + "Uniqueid: %s\r\n\r\n"
11941 ,pu->parkingnum, pu->chan->name
11942 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
11943 - ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
11944 + ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
11945 );
11946
11947 /* There's a problem, hang them up*/
11948 @@ -1672,6 +1752,280 @@
11949 return res;
11950 }
11951
11952 +int ast_hold_call(struct ast_channel *chan, struct ast_channel *peer)
11953 +{
11954 + /* We put the user in the parking list, then wake up the parking thread to be sure it looks
11955 + after these channels too */
11956 + struct holdeduser *pu;
11957 + pu = malloc(sizeof(struct holdeduser));
11958 + if (pu) {
11959 + memset(pu, 0, sizeof(pu));
11960 + ast_mutex_lock(&holding_lock);
11961 + chan->appl = "Holded Call";
11962 + chan->data = NULL;
11963 +
11964 + pu->chan = chan;
11965 + strncpy(pu->uniqueid, chan->uniqueid, sizeof(pu->uniqueid));
11966 + strncpy(pu->uniqueidpeer, peer->uniqueid, sizeof(pu->uniqueidpeer));
11967 + /* Start music on hold */
11968 + ast_moh_start(pu->chan, NULL);
11969 + gettimeofday(&pu->start, NULL);
11970 + pu->next = holdlist;
11971 + holdlist = pu;
11972 + ast_mutex_unlock(&holding_lock);
11973 + /* Wake up the (presumably select()ing) thread */
11974 + pthread_kill(holding_thread, SIGURG);
11975 +
11976 + manager_event(EVENT_FLAG_CALL, "HoldedCall",
11977 + "Channel1: %s\r\n"
11978 + "Channel2: %s\r\n"
11979 + "Uniqueid1: %s\r\n"
11980 + "Uniqueid2: %s\r\n"
11981 + ,pu->chan->name, peer->name, pu->chan->uniqueid, peer->uniqueid);
11982 +
11983 + } else {
11984 + ast_log(LOG_WARNING, "Out of memory\n");
11985 + return -1;
11986 + }
11987 + return 0;
11988 +}
11989 +
11990 +int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *peer)
11991 +{
11992 + struct ast_channel *chan;
11993 + struct ast_frame *f;
11994 + /* Make a new, fake channel that we'll use to masquerade in the real one */
11995 + chan = ast_channel_alloc(0);
11996 + if (chan) {
11997 + /* Let us keep track of the channel name */
11998 + snprintf(chan->name, sizeof (chan->name), "Onhold/%s",rchan->name);
11999 + /* Make formats okay */
12000 + chan->readformat = rchan->readformat;
12001 + chan->writeformat = rchan->writeformat;
12002 + ast_channel_masquerade(chan, rchan);
12003 + /* Setup the extensions and such */
12004 + strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
12005 + strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
12006 + chan->priority = rchan->priority;
12007 + /* this might be dirty, but we need to preserve the uniqueid */
12008 + strncpy(chan->uniqueid, rchan->uniqueid, sizeof(chan->uniqueid) - 1);
12009 + /* Make the masq execute */
12010 + f = ast_read(chan);
12011 + if (f)
12012 + ast_frfree(f);
12013 + ast_hold_call(chan, peer);
12014 + return -1;
12015 + } else {
12016 + ast_log(LOG_WARNING, "Unable to create holded channel\n");
12017 + return -1;
12018 + }
12019 + return 0;
12020 +}
12021 +
12022 +int ast_retrieve_call(struct ast_channel *chan, char *uniqueid)
12023 +{
12024 + int res=-1, dres=-1;
12025 + struct ast_channel *peer=NULL;
12026 + struct ast_bridge_config config;
12027 +
12028 + peer = ast_get_holded_call(uniqueid);
12029 +
12030 + /* JK02: it helps to answer the channel if not already up */
12031 + if (chan->_state != AST_STATE_UP) {
12032 + ast_answer(chan);
12033 + }
12034 +
12035 + if (peer) {
12036 + ast_mutex_unlock(&peer->lock);
12037 + ast_moh_stop(peer);
12038 + res = ast_channel_make_compatible(chan, peer);
12039 + if (res < 0) {
12040 + ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
12041 + ast_hangup(peer);
12042 + return -1;
12043 + }
12044 + /* This runs sorta backwards, since we give the incoming channel control, as if it
12045 + were the person called. */
12046 + if (option_verbose > 2)
12047 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to holded call %s\n", chan->name, peer->name);
12048 +
12049 + memset(&config,0,sizeof(struct ast_bridge_config));
12050 + ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
12051 + ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
12052 + config.timelimit = 0;
12053 + config.play_warning = 0;
12054 + config.warning_freq = 0;
12055 + config.warning_sound=NULL;
12056 + res = ast_bridge_call(chan,peer,&config);
12057 +
12058 + /* Simulate the PBX hanging up */
12059 + if (res != AST_PBX_NO_HANGUP_PEER)
12060 + ast_hangup(peer);
12061 + return res;
12062 + } else {
12063 + /* XXX Play a message XXX */
12064 + dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
12065 + if (!dres)
12066 + dres = ast_waitstream(chan, "");
12067 + else {
12068 + ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
12069 + dres = 0;
12070 + }
12071 + }
12072 + return res;
12073 +}
12074 +
12075 +int ast_retrieve_call_to_death(char *uniqueid)
12076 +{
12077 + int res=-1;
12078 + struct ast_channel *peer=NULL;
12079 +
12080 + peer = ast_get_holded_call(uniqueid);
12081 +
12082 + if (peer) {
12083 + res=0;
12084 + if (option_verbose > 2)
12085 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
12086 + ast_mutex_unlock(&peer->lock);
12087 + ast_hangup(peer);
12088 + } else {
12089 + ast_log(LOG_WARNING, "Could not find channel with uniqueid %s to retrieve.\n", uniqueid);
12090 + }
12091 + return res;
12092 +}
12093 +
12094 +struct ast_channel *ast_get_holded_call(char *uniqueid)
12095 +{
12096 + int res=-1;
12097 + struct ast_channel *peer=NULL;
12098 + struct holdeduser *pu, *pl=NULL;
12099 +
12100 + ast_mutex_lock(&holding_lock);
12101 + pu = holdlist;
12102 + while(pu) {
12103 + if (!strncmp(uniqueid,pu->uniqueid,sizeof(pu->uniqueid))) {
12104 + if (pl)
12105 + pl->next = pu->next;
12106 + else
12107 + holdlist = pu->next;
12108 + break;
12109 + }
12110 + pl = pu;
12111 + pu = pu->next;
12112 + }
12113 + ast_mutex_unlock(&holding_lock);
12114 + if (pu) {
12115 + peer = ast_get_channel_by_uniqueid_locked(pu->uniqueid);
12116 + free(pu);
12117 + if (peer) {
12118 + res=0;
12119 + if (option_verbose > 2)
12120 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
12121 + ast_moh_stop(peer);
12122 + return peer;
12123 + } else {
12124 + if (option_verbose > 2)
12125 + ast_verbose(VERBOSE_PREFIX_3 "Could not find channel with uniqueid %s.\n", uniqueid);
12126 + return NULL;
12127 + }
12128 + } else {
12129 + ast_log(LOG_WARNING, "Could not find held channel with uniqueid %s to retrieve.\n", uniqueid);
12130 + }
12131 + return NULL;
12132 +}
12133 +
12134 +/* this is our autmagically service thread that keeps channels onhold happy */
12135 +static void *do_holding_thread(void *ignore)
12136 +{
12137 + int ms, tms, max;
12138 + struct holdeduser *pu, *pl, *pt = NULL;
12139 + struct timeval tv;
12140 + struct ast_frame *f;
12141 + int x;
12142 + fd_set rfds, efds;
12143 + fd_set nrfds, nefds;
12144 + FD_ZERO(&rfds);
12145 + FD_ZERO(&efds);
12146 + for (;;) {
12147 + ms = -1;
12148 + max = -1;
12149 + ast_mutex_lock(&holding_lock);
12150 + pl = NULL;
12151 + pu = holdlist;
12152 + gettimeofday(&tv, NULL);
12153 + FD_ZERO(&nrfds);
12154 + FD_ZERO(&nefds);
12155 + while(pu) {
12156 + tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
12157 + for (x=0;x<AST_MAX_FDS;x++) {
12158 + if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
12159 + /* if (FD_ISSET(pu->chan->fds[x], &efds))
12160 + pu->chan->exception = 1; */
12161 + pu->chan->fdno = x;
12162 + /* See if they need servicing */
12163 + f = ast_read(pu->chan);
12164 + if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
12165 + /* There's a problem, hang them up*/
12166 + if (option_verbose > 1)
12167 + ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being onhold\n", pu->chan->name);
12168 + ast_hangup(pu->chan);
12169 + /* find the corresponding channel and hang them up too! */
12170 + /* but only if it is not bridged yet! */
12171 + /* And take them out of the parking lot */
12172 + if (pl)
12173 + pl->next = pu->next;
12174 + else
12175 + holdlist = pu->next;
12176 + pt = pu;
12177 + pu = pu->next;
12178 + free(pt);
12179 + break;
12180 + } else {
12181 + /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
12182 + ast_frfree(f);
12183 + goto std; /* XXX Ick: jumping into an else statement??? XXX */
12184 + }
12185 + }
12186 + }
12187 + if (x >= AST_MAX_FDS) {
12188 +std: for (x=0;x<AST_MAX_FDS;x++) {
12189 + /* Keep this one for next one */
12190 + if (pu->chan->fds[x] > -1) {
12191 + FD_SET(pu->chan->fds[x], &nrfds);
12192 + FD_SET(pu->chan->fds[x], &nefds);
12193 + if (pu->chan->fds[x] > max)
12194 + max = pu->chan->fds[x];
12195 + }
12196 + }
12197 + /* Keep track of our longest wait */
12198 + if ((tms < ms) || (ms < 0))
12199 + ms = tms;
12200 + pl = pu;
12201 + pu = pu->next;
12202 + }
12203 + }
12204 + ast_mutex_unlock(&holding_lock);
12205 + rfds = nrfds;
12206 + efds = nefds;
12207 + tv.tv_sec = ms / 1000;
12208 + tv.tv_usec = (ms % 1000) * 1000;
12209 + /* Wait for something to happen */
12210 + ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
12211 + pthread_testcancel();
12212 + }
12213 + return NULL; /* Never reached */
12214 +}
12215 +
12216 +static int retrieve_call_exec(struct ast_channel *chan, void *data) {
12217 + int res=0;
12218 + struct localuser *u;
12219 + char *uniqueid = (char *)data;
12220 + LOCAL_USER_ADD(u);
12221 + res = ast_retrieve_call(chan, uniqueid);
12222 + LOCAL_USER_REMOVE(u);
12223 + return res;
12224 +}
12225 +
12226 static int park_exec(struct ast_channel *chan, void *data)
12227 {
12228 int res=0;
12229 @@ -1720,9 +2074,10 @@
12230 "From: %s\r\n"
12231 "CallerID: %s\r\n"
12232 "CallerIDName: %s\r\n"
12233 + "Uniqueid: %s\r\n\r\n"
12234 ,pu->parkingnum, pu->chan->name, chan->name
12235 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
12236 - ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
12237 + ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
12238 );
12239
12240 free(pu);
12241 @@ -1890,12 +2245,13 @@
12242 "Timeout: %ld\r\n"
12243 "CallerID: %s\r\n"
12244 "CallerIDName: %s\r\n"
12245 + "Uniqueid: %s\r\n"
12246 "%s"
12247 "\r\n"
12248 ,cur->parkingnum, cur->chan->name
12249 ,(long)cur->start.tv_sec + (long)(cur->parkingtime/1000) - (long)time(NULL)
12250 ,(cur->chan->cid.cid_num ? cur->chan->cid.cid_num : "")
12251 - ,(cur->chan->cid.cid_name ? cur->chan->cid.cid_name : "")
12252 + ,(cur->chan->cid.cid_name ? cur->chan->cid.cid_name : ""), cur->chan->uniqueid
12253 ,idText);
12254
12255 cur = cur->next;
12256 @@ -1911,6 +2267,386 @@
12257 return RESULT_SUCCESS;
12258 }
12259
12260 +static int handle_autoanswer(int fd, int argc, char *argv[])
12261 +{
12262 + struct aauser *cur;
12263 +
12264 + ast_cli(fd, "%25s %10s %15s \n", "Channel"
12265 + , "Extension", "Context");
12266 +
12267 + ast_mutex_lock(&autoanswer_lock);
12268 +
12269 + cur=aalot;
12270 + while(cur) {
12271 + ast_cli(fd, "%25s %10s %15s\n",cur->chan->name, cur->exten, cur->context);
12272 +
12273 + cur = cur->next;
12274 + }
12275 +
12276 + ast_mutex_unlock(&autoanswer_lock);
12277 +
12278 + return RESULT_SUCCESS;
12279 +}
12280 +static char showautoanswer_help[] =
12281 +"Usage: show autoanswer\n"
12282 +" Lists currently logged in autoanswr channels.\n";
12283 +
12284 +static struct ast_cli_entry showautoanswer =
12285 +{ { "show", "autoanswer", NULL }, handle_autoanswer, "Lists autoanswer channels", showautoanswer_help };
12286 +
12287 +int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data)
12288 +{
12289 + struct ast_channel *chan;
12290 + struct ast_frame *f;
12291 + /* Make a new, fake channel that we'll use to masquerade in the real one */
12292 + chan = ast_channel_alloc(0);
12293 + if (chan) {
12294 + /* Let us keep track of the channel name */
12295 + snprintf(chan->name, sizeof (chan->name), "Autoanswer/%s",rchan->name);
12296 + /* Make formats okay */
12297 + chan->readformat = rchan->readformat;
12298 + chan->writeformat = rchan->writeformat;
12299 + ast_channel_masquerade(chan, rchan);
12300 + /* Setup the extensions and such */
12301 + strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
12302 + strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
12303 + chan->priority = rchan->priority;
12304 + /* Make the masq execute */
12305 + f = ast_read(chan);
12306 + if (f)
12307 + ast_frfree(f);
12308 + ast_autoanswer_login(chan, data);
12309 + } else {
12310 + ast_log(LOG_WARNING, "Unable to create aa channel\n");
12311 + return -1;
12312 + }
12313 + return 0;
12314 +}
12315 +
12316 +static int autoanswer_login_exec(struct ast_channel *chan, void *data)
12317 +{
12318 + int res=0;
12319 + struct localuser *u;
12320 + LOCAL_USER_ADD(u);
12321 + if (!data) {
12322 + ast_log(LOG_WARNING, "AutoanswerLogin requires an argument (extension number)\n");
12323 + return -1;
12324 + }
12325 + res = ast_masq_autoanswer_login(chan, data);
12326 + LOCAL_USER_REMOVE(u);
12327 + return res;
12328 +}
12329 +
12330 +int ast_autoanswer_login(struct ast_channel *chan, void *data)
12331 +{
12332 + /* We put the user in the parking list, then wake up the parking thread to be sure it looks
12333 + after these channels too */
12334 + struct ast_context *con;
12335 + char exten[AST_MAX_EXTENSION];
12336 + struct aauser *pu,*pl = NULL;
12337 + char *s, *stringp, *aacontext, *aaexten = NULL;
12338 +
12339 + s = ast_strdupa((void *) data);
12340 + stringp=s;
12341 + aacontext = strsep(&stringp, "|");
12342 + aaexten = strsep(&stringp, "|");
12343 + if (!aaexten) {
12344 + aaexten = aacontext;
12345 + aacontext = NULL;
12346 + }
12347 + if (!aaexten) {
12348 + ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
12349 + return -1;
12350 + } else {
12351 + if (!aacontext) {
12352 + aacontext = "default";
12353 + }
12354 + }
12355 +
12356 + ast_mutex_lock(&autoanswer_lock);
12357 + pu = aalot;
12358 + while(pu) {
12359 + if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
12360 + if (pl)
12361 + pl->next = pu->next;
12362 + else
12363 + aalot = pu->next;
12364 + break;
12365 + }
12366 + pl = pu;
12367 + pu = pu->next;
12368 + }
12369 + ast_mutex_unlock(&autoanswer_lock);
12370 + if (pu) {
12371 + ast_log(LOG_NOTICE, "Logout old Channel %s for %s@%s.\n",pu->chan->name, pu->exten, pu->context);
12372 + manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
12373 + "Channel: %s\r\n"
12374 + "Uniqueid: %s\r\n"
12375 + "Context: %s\r\n"
12376 + "Exten: %s\r\n"
12377 + ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
12378 + ast_hangup(pu->chan);
12379 + free(pu);
12380 + }
12381 + pu = malloc(sizeof(struct aauser));
12382 + if (pu) {
12383 + memset(pu, 0, sizeof(pu));
12384 + ast_mutex_lock(&autoanswer_lock);
12385 + chan->appl = "Autoanswer";
12386 + chan->data = NULL;
12387 +
12388 + pu->chan = chan;
12389 + if (chan->_state != AST_STATE_UP) {
12390 + ast_answer(chan);
12391 + }
12392 +
12393 + /* Start music on hold */
12394 + ast_moh_start(pu->chan, NULL);
12395 + gettimeofday(&pu->start, NULL);
12396 + strncpy(pu->exten, aaexten, sizeof(pu->exten)-1);
12397 + strncpy(pu->context, aacontext, sizeof(pu->exten)-1);
12398 + pu->next = aalot;
12399 + aalot = pu;
12400 + con = ast_context_find(aacontext);
12401 + if (!con) {
12402 + con = ast_context_create(NULL,aacontext, registrar);
12403 + if (!con) {
12404 + ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", aacontext);
12405 + }
12406 + }
12407 + if (con) {
12408 + snprintf(exten, sizeof(exten), "%s", aaexten);
12409 + ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)data), free, registrar);
12410 + }
12411 +
12412 + ast_mutex_unlock(&autoanswer_lock);
12413 + /* Wake up the (presumably select()ing) thread */
12414 + pthread_kill(autoanswer_thread, SIGURG);
12415 + if (option_verbose > 1)
12416 + ast_verbose(VERBOSE_PREFIX_2 "Autoanswer login from %s for %s@%s.\n", pu->chan->name, pu->exten, pu->context);
12417 + manager_event(EVENT_FLAG_CALL, "AutoanswerLogin",
12418 + "Channel: %s\r\n"
12419 + "Uniqueid: %s\r\n"
12420 + "Context: %s\r\n"
12421 + "Exten: %s\r\n"
12422 + ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
12423 +
12424 + return 0;
12425 + } else {
12426 + ast_log(LOG_WARNING, "Out of memory\n");
12427 + return -1;
12428 + }
12429 + return 0;
12430 +}
12431 +
12432 +static void *do_autoanswer_thread(void *ignore)
12433 +{
12434 + int ms, tms, max;
12435 + struct ast_context *con;
12436 + char exten[AST_MAX_EXTENSION];
12437 + struct aauser *pu, *pl, *pt = NULL;
12438 + struct timeval tv;
12439 + struct ast_frame *f;
12440 + int x;
12441 + fd_set rfds, efds;
12442 + fd_set nrfds, nefds;
12443 + FD_ZERO(&rfds);
12444 + FD_ZERO(&efds);
12445 + for (;;) {
12446 + ms = -1;
12447 + max = -1;
12448 + ast_mutex_lock(&autoanswer_lock);
12449 + pl = NULL;
12450 + pu = aalot;
12451 + gettimeofday(&tv, NULL);
12452 + FD_ZERO(&nrfds);
12453 + FD_ZERO(&nefds);
12454 + while(pu) {
12455 + tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
12456 + for (x=0;x<AST_MAX_FDS;x++) {
12457 + if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
12458 +/* if (FD_ISSET(pu->chan->fds[x], &efds))
12459 + pu->chan->exception = 1; */
12460 + pu->chan->fdno = x;
12461 + /* See if they need servicing */
12462 + f = ast_read(pu->chan);
12463 + if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
12464 + /* There's a problem, hang them up*/
12465 + if (option_verbose > 1)
12466 + ast_verbose(VERBOSE_PREFIX_2 "%s logged out of autoanswer app\n", pu->chan->name);
12467 + manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
12468 + "Channel: %s\r\n"
12469 + "Uniqueid: %s\r\n"
12470 + "Context: %s\r\n"
12471 + "Exten: %s\r\n"
12472 + ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
12473 + ast_hangup(pu->chan);
12474 + con = ast_context_find(pu->context);
12475 + if (con) {
12476 + snprintf(exten, sizeof(exten), "%s", pu->exten);
12477 + if (ast_context_remove_extension2(con, exten, 1, registrar))
12478 + ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
12479 + } else {
12480 + ast_log(LOG_WARNING, "Whoa, no %s context?\n", pu->exten);
12481 + }
12482 + /* And take them out of the parking lot */
12483 + if (pl)
12484 + pl->next = pu->next;
12485 + else
12486 + aalot = pu->next;
12487 + pt = pu;
12488 + pu = pu->next;
12489 + free(pt);
12490 + break;
12491 + } else {
12492 + /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
12493 + ast_frfree(f);
12494 + goto std; /* XXX Ick: jumping into an else statement??? XXX */
12495 + }
12496 + }
12497 + }
12498 + if (x >= AST_MAX_FDS) {
12499 +std: for (x=0;x<AST_MAX_FDS;x++) {
12500 + /* Keep this one for next one */
12501 + if (pu->chan->fds[x] > -1) {
12502 + FD_SET(pu->chan->fds[x], &nrfds);
12503 + FD_SET(pu->chan->fds[x], &nefds);
12504 + if (pu->chan->fds[x] > max)
12505 + max = pu->chan->fds[x];
12506 + }
12507 + }
12508 + /* Keep track of our longest wait */
12509 + if ((tms < ms) || (ms < 0))
12510 + ms = tms;
12511 + pl = pu;
12512 + pu = pu->next;
12513 + }
12514 + }
12515 + ast_mutex_unlock(&autoanswer_lock);
12516 + rfds = nrfds;
12517 + efds = nefds;
12518 + tv.tv_sec = ms / 1000;
12519 + tv.tv_usec = (ms % 1000) * 1000;
12520 + /* Wait for something to happen */
12521 + ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
12522 + pthread_testcancel();
12523 + }
12524 + return NULL; /* Never reached */
12525 +}
12526 +
12527 +static int autoanswer_exec(struct ast_channel *chan, void *data)
12528 +{
12529 + int res=0;
12530 + struct localuser *u;
12531 + struct ast_channel *peer=NULL;
12532 + struct aauser *pu, *pl=NULL;
12533 + struct ast_bridge_config config;
12534 + char *s, *stringp, *aacontext, *aaexten = NULL;
12535 + char datastring[80];
12536 +
12537 + if (!data) {
12538 + ast_log(LOG_WARNING, "Autoanswer requires an argument (extension number)\n");
12539 + return -1;
12540 + }
12541 + s = ast_strdupa((void *) data);
12542 + stringp=s;
12543 + aacontext = strsep(&stringp, "|");
12544 + aaexten = strsep(&stringp, "|");
12545 + if (!aaexten) {
12546 + aaexten = aacontext;
12547 + aacontext = NULL;
12548 + }
12549 + if (!aaexten) {
12550 + ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
12551 + return -1;
12552 + } else {
12553 + if (!aacontext) {
12554 + aacontext = "default";
12555 + }
12556 + }
12557 +
12558 + LOCAL_USER_ADD(u);
12559 + ast_mutex_lock(&autoanswer_lock);
12560 + pu = aalot;
12561 + while(pu) {
12562 + if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
12563 + if (pl)
12564 + pl->next = pu->next;
12565 + else
12566 + aalot = pu->next;
12567 + break;
12568 + }
12569 + pl = pu;
12570 + pu = pu->next;
12571 + }
12572 + ast_mutex_unlock(&autoanswer_lock);
12573 + if (pu) {
12574 + peer = pu->chan;
12575 + free(pu);
12576 + pu = NULL;
12577 + }
12578 + /* JK02: it helps to answer the channel if not already up */
12579 + if (chan->_state != AST_STATE_UP) {
12580 + ast_answer(chan);
12581 + }
12582 +
12583 + if (peer) {
12584 + ast_moh_stop(peer);
12585 + /* Play a courtesy beep in the callED channel to prefix the bridge connecting */
12586 + if (!ast_strlen_zero(courtesytone)) {
12587 + if (!ast_streamfile(peer, courtesytone, peer->language)) {
12588 + if (ast_waitstream(peer, "") < 0) {
12589 + ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
12590 + ast_hangup(peer);
12591 + return -1;
12592 + }
12593 + }
12594 + }
12595 +
12596 + res = ast_channel_make_compatible(chan, peer);
12597 + if (res < 0) {
12598 + ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
12599 + ast_hangup(peer);
12600 + return -1;
12601 + }
12602 + /* This runs sorta backwards, since we give the incoming channel control, as if it
12603 + were the person called. */
12604 + if (option_verbose > 2)
12605 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s autoanswered %s\n", peer->name, chan->name);
12606 + manager_event(EVENT_FLAG_CALL, "Autoanswer",
12607 + "Channel: %s\r\n"
12608 + "Uniqueid: %s\r\n"
12609 + "Channel2: %s\r\n"
12610 + "Uniqueid2: %s\r\n"
12611 + "Context: %s\r\n"
12612 + "Exten: %s\r\n"
12613 + ,chan->name, chan->uniqueid, peer->name, peer->uniqueid, aacontext, aaexten);
12614 +
12615 +
12616 + memset(&config,0,sizeof(struct ast_bridge_config));
12617 + ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
12618 + ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
12619 + config.timelimit = 0;
12620 + config.play_warning = 0;
12621 + config.warning_freq = 0;
12622 + config.warning_sound=NULL;
12623 + res = ast_bridge_call(chan,peer,&config);
12624 +
12625 + if (option_verbose > 2)
12626 + ast_verbose(VERBOSE_PREFIX_3 "returning from bridge %s\n", peer->name);
12627 + /* relogin */
12628 + snprintf(datastring, sizeof(datastring) - 1, "%s|%s", aacontext, aaexten);
12629 + ast_autoanswer_login(peer, datastring);
12630 + return res;
12631 + } else {
12632 + if (option_verbose > 2)
12633 + ast_verbose(VERBOSE_PREFIX_3 "Nobody logged in for autoanswer %s@%s\n", aaexten, aacontext);
12634 + res = -1;
12635 + }
12636 + LOCAL_USER_REMOVE(u);
12637 + return res;
12638 +}
12639 +
12640
12641 int ast_pickup_call(struct ast_channel *chan)
12642 {
12643 @@ -2064,7 +2800,7 @@
12644 }
12645
12646 {
12647 - struct ast_call_feature *feature=find_feature(var->name);
12648 + struct ast_call_feature *feature = ast_find_feature(var->name);
12649 int mallocd=0;
12650
12651 if (!feature) {
12652 @@ -2140,14 +2876,22 @@
12653 if ((res = load_config()))
12654 return res;
12655 ast_cli_register(&showparked);
12656 + ast_cli_register(&showautoanswer);
12657 ast_cli_register(&showfeatures);
12658 ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
12659 + ast_pthread_create(&holding_thread, NULL, do_holding_thread, NULL);
12660 res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
12661 if (!res)
12662 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
12663 if (!res) {
12664 ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" );
12665 }
12666 + res = ast_register_application(holdedcall, retrieve_call_exec, synopsis, descrip);
12667 + ast_pthread_create(&autoanswer_thread, NULL, do_autoanswer_thread, NULL);
12668 + if (!res)
12669 + res = ast_register_application(autoanswerlogin, autoanswer_login_exec, synopsis3, descrip3);
12670 + if (!res)
12671 + res = ast_register_application(autoanswer, autoanswer_exec, synopsis4, descrip4);
12672 return res;
12673 }
12674
12675 @@ -2158,7 +2902,11 @@
12676
12677 ast_manager_unregister("ParkedCalls");
12678 ast_cli_unregister(&showfeatures);
12679 + ast_cli_unregister(&showautoanswer);
12680 ast_cli_unregister(&showparked);
12681 + ast_unregister_application(autoanswer);
12682 + ast_unregister_application(autoanswerlogin);
12683 + ast_unregister_application(holdedcall);
12684 ast_unregister_application(parkcall);
12685 return ast_unregister_application(parkedcall);
12686 }
12687 diff -urN asterisk-1.2.4.orig/res/res_watchdog.c asterisk-1.2.4/res/res_watchdog.c
12688 --- asterisk-1.2.4.orig/res/res_watchdog.c 1970-01-01 01:00:00.000000000 +0100
12689 +++ asterisk-1.2.4/res/res_watchdog.c 2006-01-31 09:41:43.000000000 +0100
12690 @@ -0,0 +1,148 @@
12691 +/*
12692 + * Asterisk -- A telephony toolkit for Linux.
12693 + *
12694 + * Resource to make watchdogs happy
12695 + *
12696 + * Copyright (C) 2005, Junghanns.NET GmbH
12697 + *
12698 + * Klaus-Peter Junghanns <kpj@junghanns.net>
12699 + *
12700 + * This program is free software, distributed under the terms of
12701 + * the GNU General Public License
12702 + */
12703 +
12704 +#include <stdlib.h>
12705 +#include <errno.h>
12706 +#include <unistd.h>
12707 +#include <string.h>
12708 +#include <stdlib.h>
12709 +#include <stdio.h>
12710 +#include <sys/time.h>
12711 +#include <sys/signal.h>
12712 +#include <netinet/in.h>
12713 +#include <asterisk/lock.h>
12714 +#include <asterisk/file.h>
12715 +#include <asterisk/logger.h>
12716 +#include <asterisk/channel.h>
12717 +#include <asterisk/pbx.h>
12718 +#include <asterisk/options.h>
12719 +#include <asterisk/module.h>
12720 +#include <asterisk/translate.h>
12721 +#include <asterisk/say.h>
12722 +#include <asterisk/features.h>
12723 +#include <asterisk/musiconhold.h>
12724 +#include <asterisk/config.h>
12725 +#include <asterisk/cli.h>
12726 +#include <asterisk/manager.h>
12727 +#include <asterisk/utils.h>
12728 +#include <asterisk/adsi.h>
12729 +
12730 +static struct watchdog_pvt *watchdogs = NULL;
12731 +
12732 +STANDARD_LOCAL_USER;
12733 +
12734 +LOCAL_USER_DECL;
12735 +
12736 +typedef struct watchdog_pvt {
12737 + char device[80];
12738 + int fd;
12739 + int type;
12740 + int interval;
12741 + pthread_t watchdog_thread;
12742 + struct watchdog_pvt *next;
12743 +} watchdog_pvt;
12744 +
12745 +static void *do_watchdog_thread(void *data) {
12746 + struct watchdog_pvt *woof = (struct watchdog_pvt *)data;
12747 + for (;;) {
12748 + if (woof->fd) {
12749 + write(woof->fd, "PING\n", 1);
12750 + }
12751 + usleep(woof->interval * 1000);
12752 + }
12753 + return NULL;
12754 +}
12755 +
12756 +
12757 +int load_module(void)
12758 +{
12759 + int res = 0;
12760 + char *cat, *utype, *udevice, *uinterval;
12761 + struct ast_config *cfg;
12762 + struct watchdog_pvt *woof = NULL;
12763 +
12764 + cfg = ast_config_load("watchdog.conf");
12765 + if (cfg) {
12766 + cat = ast_category_browse(cfg, NULL);
12767 + while(cat) {
12768 + cat = ast_category_browse(cfg, cat);
12769 + utype = ast_variable_retrieve(cfg, cat, "type");
12770 + if (utype) {
12771 + ast_log(LOG_NOTICE, "type = %s\n", utype);
12772 + }
12773 + udevice = ast_variable_retrieve(cfg, cat, "device");
12774 + if (udevice) {
12775 + ast_log(LOG_NOTICE, "device = %s\n", udevice);
12776 + }
12777 + uinterval = ast_variable_retrieve(cfg, cat, "interval");
12778 + if (uinterval) {
12779 + ast_log(LOG_NOTICE, "interval = %s\n", uinterval);
12780 + }
12781 + if (uinterval && udevice && utype) {
12782 + woof = malloc(sizeof(struct watchdog_pvt));
12783 + if (!woof) {
12784 + ast_log(LOG_ERROR, "unable to malloc!\n");
12785 + return -1;
12786 + }
12787 + memset(woof, 0x0, sizeof(struct watchdog_pvt));
12788 + strncpy(woof->device, udevice, sizeof(woof->device) - 1);
12789 +
12790 + woof->interval = atoi(uinterval);;
12791 + woof->next = watchdogs;
12792 + watchdogs = woof;
12793 + woof->fd = open(woof->device, O_WRONLY | O_SYNC);
12794 + if (woof->fd) {
12795 + if (!strncmp(utype, "isdnguard", sizeof(utype))) {
12796 + woof->type = 1;
12797 + write(woof->fd, "START\n", 6);
12798 + }
12799 + ast_pthread_create(&woof->watchdog_thread, NULL, do_watchdog_thread, woof);
12800 + } else {
12801 + ast_log(LOG_WARNING, "error opening watchdog device %s !\n", woof->device);
12802 + }
12803 + }
12804 + }
12805 + ast_config_destroy(cfg);
12806 + }
12807 + return res;
12808 +}
12809 +
12810 +
12811 +int unload_module(void)
12812 +{
12813 + struct watchdog_pvt *dogs, *woof;
12814 + STANDARD_HANGUP_LOCALUSERS;
12815 + dogs = watchdogs;
12816 + while (dogs) {
12817 + pthread_cancel(dogs->watchdog_thread);
12818 + woof = dogs->next;
12819 + free(dogs);
12820 + dogs = woof;
12821 + }
12822 + return 0;
12823 +}
12824 +
12825 +char *description(void)
12826 +{
12827 + return "Watchdog Resource";
12828 +}
12829 +
12830 +int usecount(void)
12831 +{
12832 + return 1;
12833 +}
12834 +
12835 +char *key()
12836 +{
12837 + return ASTERISK_GPL_KEY;
12838 +}
12839 diff -urN asterisk-1.2.4.orig/rtp.c asterisk-1.2.4/rtp.c
12840 --- asterisk-1.2.4.orig/rtp.c 2005-11-30 15:27:59.000000000 +0100
12841 +++ asterisk-1.2.4/rtp.c 2006-01-31 09:41:43.000000000 +0100
12842 @@ -442,6 +442,11 @@
12843 struct rtpPayloadType rtpPT;
12844
12845 len = sizeof(sin);
12846 +
12847 + /* XXX SYMPTON CURE, DIRTY FIX, CHECK, BEGIN */
12848 + if (!rtp)
12849 + return &null_frame;
12850 + /* XXX SYMPTON CURE, DIRTY FIX, CHECK, END */
12851
12852 /* Cache where the header will go */
12853 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,