2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2004 - 2006, Christian Richter
6 * Christian Richter <crich@beronet.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
23 * \brief the chan_misdn channel driver for Asterisk
24 * \author Christian Richter <crich@beronet.com>
26 * \ingroup channel_drivers
30 <depend>isdnnet</depend>
31 <depend>misdn</depend>
32 <depend>suppserv</depend>
36 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
41 #include <sys/socket.h>
46 #include <arpa/inet.h>
48 #include <sys/ioctl.h>
51 #include <semaphore.h>
53 #include "asterisk/channel.h"
54 #include "asterisk/config.h"
55 #include "asterisk/logger.h"
56 #include "asterisk/module.h"
57 #include "asterisk/pbx.h"
58 #include "asterisk/options.h"
59 #include "asterisk/io.h"
60 #include "asterisk/frame.h"
61 #include "asterisk/translate.h"
62 #include "asterisk/cli.h"
63 #include "asterisk/musiconhold.h"
64 #include "asterisk/dsp.h"
65 #include "asterisk/translate.h"
66 #include "asterisk/config.h"
67 #include "asterisk/file.h"
68 #include "asterisk/callerid.h"
69 #include "asterisk/indications.h"
70 #include "asterisk/app.h"
71 #include "asterisk/features.h"
72 #include "asterisk/term.h"
73 #include "asterisk/sched.h"
74 #include "asterisk/stringfields.h"
76 #include "chan_misdn_config.h"
79 char global_tracefile
[BUFFERSIZE
+1];
81 static int g_config_initialized
=0;
97 /* allocates the jb-structure and initialize the elements*/
98 struct misdn_jb
*misdn_jb_init(int size
, int upper_threshold
);
100 /* frees the data and destroys the given jitterbuffer struct */
101 void misdn_jb_destroy(struct misdn_jb
*jb
);
103 /* fills the jitterbuffer with len data returns < 0 if there was an
104 error (buffer overrun). */
105 int misdn_jb_fill(struct misdn_jb
*jb
, const char *data
, int len
);
107 /* gets len bytes out of the jitterbuffer if available, else only the
108 available data is returned and the return value indicates the number
110 int misdn_jb_empty(struct misdn_jb
*jb
, char *data
, int len
);
113 /* BEGIN: chan_misdn.h */
115 ast_mutex_t release_lock
;
117 enum misdn_chan_state
{
118 MISDN_NOTHING
=0, /*!< at beginning */
119 MISDN_WAITING4DIGS
, /*!< when waiting for infos */
120 MISDN_EXTCANTMATCH
, /*!< when asterisk couldn't match our ext */
121 MISDN_INCOMING_SETUP
, /*!< for incoming setups*/
122 MISDN_DIALING
, /*!< when pbx_start */
123 MISDN_PROGRESS
, /*!< we got a progress */
124 MISDN_PROCEEDING
, /*!< we got a progress */
125 MISDN_CALLING
, /*!< when misdn_call is called */
126 MISDN_CALLING_ACKNOWLEDGE
, /*!< when we get SETUP_ACK */
127 MISDN_ALERTING
, /*!< when Alerting */
128 MISDN_BUSY
, /*!< when BUSY */
129 MISDN_CONNECTED
, /*!< when connected */
130 MISDN_PRECONNECTED
, /*!< when connected */
131 MISDN_DISCONNECTED
, /*!< when connected */
132 MISDN_RELEASED
, /*!< when connected */
133 MISDN_BRIDGED
, /*!< when bridged */
134 MISDN_CLEANING
, /*!< when hangup from * but we were connected before */
135 MISDN_HUNGUP_FROM_MISDN
, /*!< when DISCONNECT/RELEASE/REL_COMP cam from misdn */
136 MISDN_HUNGUP_FROM_AST
, /*!< when DISCONNECT/RELEASE/REL_COMP came out of */
138 MISDN_HOLDED
, /*!< if this chan is holded */
139 MISDN_HOLD_DISCONNECT
, /*!< if this chan is holded */
153 char allowed_bearers
[BUFFERSIZE
+1];
155 enum misdn_chan_state state
;
156 int need_queue_hangup
;
160 int noautorespond_on_setup
;
169 int incoming_early_audio
;
174 char ast_rd_buf
[4096];
175 struct ast_frame frame
;
177 int faxdetect
; /* 0:no 1:yes 2:yes+nojump */
178 int faxdetect_timeout
;
179 struct timeval faxdetect_tv
;
185 int jb_upper_threshold
;
189 struct ast_trans_pvt
*trans
;
191 struct ast_channel
* ast
;
195 struct misdn_bchannel
*bc
;
197 struct hold_info hold_info
;
202 char context
[BUFFERSIZE
];
205 int dropped_frame_cnt
;
212 struct chan_list
*other_ch
;
214 const struct ind_tone_zone_sound
*ts
;
217 int overlap_dial_task
;
218 ast_mutex_t overlap_tv_lock
;
219 struct timeval overlap_tv
;
221 struct chan_list
*peer
;
222 struct chan_list
*next
;
223 struct chan_list
*prev
;
224 struct chan_list
*first
;
229 void export_ch(struct ast_channel
*chan
, struct misdn_bchannel
*bc
, struct chan_list
*ch
);
230 void import_ch(struct ast_channel
*chan
, struct misdn_bchannel
*bc
, struct chan_list
*ch
);
236 struct robin_list
*next
;
237 struct robin_list
*prev
;
239 static struct robin_list
*robin
= NULL
;
243 static struct ast_frame
*process_ast_dsp(struct chan_list
*tmp
, struct ast_frame
*frame
);
247 static inline void free_robin_list_r (struct robin_list
*r
)
250 if (r
->next
) free_robin_list_r(r
->next
);
251 if (r
->group
) free(r
->group
);
256 static void free_robin_list ( void )
258 free_robin_list_r(robin
);
262 static struct robin_list
* get_robin_position (char *group
)
264 struct robin_list
*new;
265 struct robin_list
*iter
= robin
;
266 for (; iter
; iter
= iter
->next
) {
267 if (!strcasecmp(iter
->group
, group
))
270 new = (struct robin_list
*)calloc(1, sizeof(struct robin_list
));
271 new->group
= strndup(group
, strlen(group
));
283 /* the main schedule context for stuff like l1 watcher, overlap dial, ... */
284 static struct sched_context
*misdn_tasks
= NULL
;
285 static pthread_t misdn_tasks_thread
;
287 static int *misdn_ports
;
289 static void chan_misdn_log(int level
, int port
, char *tmpl
, ...);
291 static struct ast_channel
*misdn_new(struct chan_list
*cl
, int state
, char *exten
, char *callerid
, int format
, int port
, int c
);
292 static void send_digit_to_chan(struct chan_list
*cl
, char digit
);
294 static void hangup_chan(struct chan_list
*ch
);
295 static int pbx_start_chan(struct chan_list
*ch
);
297 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
298 #define MISDN_ASTERISK_PVT(ast) 1
300 #include <asterisk/strings.h>
302 /* #define MISDN_DEBUG 1 */
304 static const char misdn_type
[] = "mISDN";
306 static int tracing
= 0 ;
308 /* Only alaw and mulaw is allowed for now */
309 static int prefformat
= AST_FORMAT_ALAW
; /* AST_FORMAT_SLINEAR ; AST_FORMAT_ULAW | */
311 static int *misdn_debug
;
312 static int *misdn_debug_only
;
313 static int max_ports
;
315 static int *misdn_in_calls
;
316 static int *misdn_out_calls
;
319 struct chan_list dummy_cl
;
321 struct chan_list
*cl_te
=NULL
;
322 ast_mutex_t cl_te_lock
;
324 static enum event_response_e
325 cb_events(enum event_e event
, struct misdn_bchannel
*bc
, void *user_data
);
327 static void send_cause2ast(struct ast_channel
*ast
, struct misdn_bchannel
*bc
, struct chan_list
*ch
);
329 static void cl_queue_chan(struct chan_list
**list
, struct chan_list
*chan
);
330 static void cl_dequeue_chan(struct chan_list
**list
, struct chan_list
*chan
);
331 static struct chan_list
*find_chan_by_bc(struct chan_list
*list
, struct misdn_bchannel
*bc
);
332 static struct chan_list
*find_chan_by_pid(struct chan_list
*list
, int pid
);
336 static int dialtone_indicate(struct chan_list
*cl
);
337 static int hanguptone_indicate(struct chan_list
*cl
);
338 static int stop_indicate(struct chan_list
*cl
);
340 static int start_bc_tones(struct chan_list
*cl
);
341 static int stop_bc_tones(struct chan_list
*cl
);
342 static void release_chan(struct misdn_bchannel
*bc
);
344 static int misdn_check_l2l1(struct ast_channel
*chan
, void *data
);
345 static int misdn_set_opt_exec(struct ast_channel
*chan
, void *data
);
346 static int misdn_facility_exec(struct ast_channel
*chan
, void *data
);
348 int chan_misdn_jb_empty(struct misdn_bchannel
*bc
, char *buf
, int len
);
351 void debug_numplan(int port
, int numplan
, char *type
);
354 int add_out_calls(int port
);
355 int add_in_calls(int port
);
359 static int update_pipeline_config(struct misdn_bchannel
*bc
);
361 static int update_ec_config(struct misdn_bchannel
*bc
);
366 /*************** Helpers *****************/
368 static struct chan_list
* get_chan_by_ast(struct ast_channel
*ast
)
370 struct chan_list
*tmp
;
372 for (tmp
=cl_te
; tmp
; tmp
= tmp
->next
) {
373 if ( tmp
->ast
== ast
) return tmp
;
379 static struct chan_list
* get_chan_by_ast_name(char *name
)
381 struct chan_list
*tmp
;
383 for (tmp
=cl_te
; tmp
; tmp
= tmp
->next
) {
384 if ( tmp
->ast
&& strcmp(tmp
->ast
->name
,name
) == 0) return tmp
;
392 struct allowed_bearers
{
399 static struct allowed_bearers allowed_bearers_array
[]= {
400 {INFO_CAPABILITY_SPEECH
,1,"speech"},
401 {INFO_CAPABILITY_AUDIO_3_1K
,2,"3_1khz"},
402 {INFO_CAPABILITY_DIGITAL_UNRESTRICTED
,4,"digital_unrestricted"},
403 {INFO_CAPABILITY_DIGITAL_RESTRICTED
,8,"digital_restricted"},
404 {INFO_CAPABILITY_DIGITAL_RESTRICTED
,8,"digital_restriced", 1}, /* Allow misspelling for backwards compatibility */
405 {INFO_CAPABILITY_VIDEO
,16,"video"}
408 static char *bearer2str(int cap
) {
409 static char *bearers
[]={
419 case INFO_CAPABILITY_SPEECH
:
422 case INFO_CAPABILITY_AUDIO_3_1K
:
425 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED
:
428 case INFO_CAPABILITY_DIGITAL_RESTRICTED
:
431 case INFO_CAPABILITY_VIDEO
:
441 static void print_facility(struct FacParm
*fac
, struct misdn_bchannel
*bc
)
443 switch (fac
->Function
) {
445 chan_misdn_log(1,bc
->port
," --> calldeflect to: %s, screened: %s\n", fac
->u
.CDeflection
.DeflectedToNumber
,
446 fac
->u
.CDeflection
.PresentationAllowed
? "yes" : "no");
448 case Fac_AOCDCurrency
:
449 if (fac
->u
.AOCDcur
.chargeNotAvailable
)
450 chan_misdn_log(1,bc
->port
," --> AOCD currency: charge not available\n");
451 else if (fac
->u
.AOCDcur
.freeOfCharge
)
452 chan_misdn_log(1,bc
->port
," --> AOCD currency: free of charge\n");
453 else if (fac
->u
.AOCDchu
.billingId
>= 0)
454 chan_misdn_log(1,bc
->port
," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d billingId:%d\n",
455 fac
->u
.AOCDcur
.currency
, fac
->u
.AOCDcur
.currencyAmount
, fac
->u
.AOCDcur
.multiplier
,
456 (fac
->u
.AOCDcur
.typeOfChargingInfo
== 0) ? "subTotal" : "total", fac
->u
.AOCDcur
.billingId
);
458 chan_misdn_log(1,bc
->port
," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d\n",
459 fac
->u
.AOCDcur
.currency
, fac
->u
.AOCDcur
.currencyAmount
, fac
->u
.AOCDcur
.multiplier
,
460 (fac
->u
.AOCDcur
.typeOfChargingInfo
== 0) ? "subTotal" : "total");
462 case Fac_AOCDChargingUnit
:
463 if (fac
->u
.AOCDchu
.chargeNotAvailable
)
464 chan_misdn_log(1,bc
->port
," --> AOCD charging unit: charge not available\n");
465 else if (fac
->u
.AOCDchu
.freeOfCharge
)
466 chan_misdn_log(1,bc
->port
," --> AOCD charging unit: free of charge\n");
467 else if (fac
->u
.AOCDchu
.billingId
>= 0)
468 chan_misdn_log(1,bc
->port
," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
469 fac
->u
.AOCDchu
.recordedUnits
, (fac
->u
.AOCDchu
.typeOfChargingInfo
== 0) ? "subTotal" : "total", fac
->u
.AOCDchu
.billingId
);
471 chan_misdn_log(1,bc
->port
," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
472 fac
->u
.AOCDchu
.recordedUnits
, (fac
->u
.AOCDchu
.typeOfChargingInfo
== 0) ? "subTotal" : "total");
475 chan_misdn_log(1,bc
->port
," --> unknown\n");
479 static void print_bearer(struct misdn_bchannel
*bc
)
482 chan_misdn_log(2, bc
->port
, " --> Bearer: %s\n",bearer2str(bc
->capability
));
485 case INFO_CODEC_ALAW
:
486 chan_misdn_log(2, bc
->port
, " --> Codec: Alaw\n");
488 case INFO_CODEC_ULAW
:
489 chan_misdn_log(2, bc
->port
, " --> Codec: Ulaw\n");
494 static void export_aoc_vars(int originator
, struct ast_channel
*ast
, struct misdn_bchannel
*bc
)
501 if (originator
== ORG_AST
) {
502 ast
= ast_bridged_channel(ast
);
507 switch (bc
->AOCDtype
) {
508 case Fac_AOCDCurrency
:
509 pbx_builtin_setvar_helper(ast
, "AOCD_Type", "currency");
510 if (bc
->AOCD
.currency
.chargeNotAvailable
)
511 pbx_builtin_setvar_helper(ast
, "AOCD_ChargeAvailable", "no");
513 pbx_builtin_setvar_helper(ast
, "AOCD_ChargeAvailable", "yes");
514 if (bc
->AOCD
.currency
.freeOfCharge
)
515 pbx_builtin_setvar_helper(ast
, "AOCD_FreeOfCharge", "yes");
517 pbx_builtin_setvar_helper(ast
, "AOCD_FreeOfCharge", "no");
518 if (snprintf(buf
, sizeof(buf
), "%d %s", bc
->AOCD
.currency
.currencyAmount
* bc
->AOCD
.currency
.multiplier
, bc
->AOCD
.currency
.currency
) < sizeof(buf
)) {
519 pbx_builtin_setvar_helper(ast
, "AOCD_Amount", buf
);
520 if (bc
->AOCD
.currency
.billingId
>= 0 && snprintf(buf
, sizeof(buf
), "%d", bc
->AOCD
.currency
.billingId
) < sizeof(buf
))
521 pbx_builtin_setvar_helper(ast
, "AOCD_BillingId", buf
);
526 case Fac_AOCDChargingUnit
:
527 pbx_builtin_setvar_helper(ast
, "AOCD_Type", "charging_unit");
528 if (bc
->AOCD
.chargingUnit
.chargeNotAvailable
)
529 pbx_builtin_setvar_helper(ast
, "AOCD_ChargeAvailable", "no");
531 pbx_builtin_setvar_helper(ast
, "AOCD_ChargeAvailable", "yes");
532 if (bc
->AOCD
.chargingUnit
.freeOfCharge
)
533 pbx_builtin_setvar_helper(ast
, "AOCD_FreeOfCharge", "yes");
535 pbx_builtin_setvar_helper(ast
, "AOCD_FreeOfCharge", "no");
536 if (snprintf(buf
, sizeof(buf
), "%d", bc
->AOCD
.chargingUnit
.recordedUnits
) < sizeof(buf
)) {
537 pbx_builtin_setvar_helper(ast
, "AOCD_RecordedUnits", buf
);
538 if (bc
->AOCD
.chargingUnit
.billingId
>= 0 && snprintf(buf
, sizeof(buf
), "%d", bc
->AOCD
.chargingUnit
.billingId
) < sizeof(buf
))
539 pbx_builtin_setvar_helper(ast
, "AOCD_BillingId", buf
);
549 /*************** Helpers END *************/
551 static void sighandler(int sig
)
554 static void* misdn_tasks_thread_func (void *data
)
559 sa
.sa_handler
= sighandler
;
560 sa
.sa_flags
= SA_NODEFER
;
561 sigemptyset(&sa
.sa_mask
);
562 sigaddset(&sa
.sa_mask
, SIGUSR1
);
563 sigaction(SIGUSR1
, &sa
, NULL
);
565 sem_post((sem_t
*)data
);
568 wait
= ast_sched_wait(misdn_tasks
);
571 if (poll(NULL
, 0, wait
) < 0)
572 chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
573 ast_sched_runq(misdn_tasks
);
578 static void misdn_tasks_init (void)
583 if (sem_init(&blocker
, 0, 0)) {
584 perror("chan_misdn: Failed to initialize semaphore!");
588 chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
590 misdn_tasks
= sched_context_create();
591 pthread_create(&misdn_tasks_thread
, NULL
, misdn_tasks_thread_func
, &blocker
);
593 while (sem_wait(&blocker
) && --i
);
594 sem_destroy(&blocker
);
597 static void misdn_tasks_destroy (void)
600 chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
601 if ( pthread_cancel(misdn_tasks_thread
) == 0 ) {
602 cb_log(4, 0, "Joining misdn_tasks thread\n");
603 pthread_join(misdn_tasks_thread
, NULL
);
605 sched_context_destroy(misdn_tasks
);
609 static inline void misdn_tasks_wakeup (void)
611 pthread_kill(misdn_tasks_thread
, SIGUSR1
);
614 static inline int _misdn_tasks_add_variable (int timeout
, ast_sched_cb callback
, const void *data
, int variable
)
621 task_id
= ast_sched_add_variable(misdn_tasks
, timeout
, callback
, data
, variable
);
622 misdn_tasks_wakeup();
627 static int misdn_tasks_add (int timeout
, ast_sched_cb callback
, const void *data
)
629 return _misdn_tasks_add_variable(timeout
, callback
, data
, 0);
632 static int misdn_tasks_add_variable (int timeout
, ast_sched_cb callback
, const void *data
)
634 return _misdn_tasks_add_variable(timeout
, callback
, data
, 1);
637 static void misdn_tasks_remove (int task_id
)
639 AST_SCHED_DEL(misdn_tasks
, task_id
);
642 static int misdn_l1_task (const void *data
)
644 misdn_lib_isdn_l1watcher(*(int *)data
);
645 chan_misdn_log(5, *(int *)data
, "L1watcher timeout\n");
649 static int misdn_overlap_dial_task (const void *data
)
651 struct timeval tv_end
, tv_now
;
653 struct chan_list
*ch
= (struct chan_list
*)data
;
655 chan_misdn_log(4, ch
->bc
->port
, "overlap dial task, chan_state: %d\n", ch
->state
);
657 if (ch
->state
!= MISDN_WAITING4DIGS
) {
658 ch
->overlap_dial_task
= -1;
662 ast_mutex_lock(&ch
->overlap_tv_lock
);
663 tv_end
= ch
->overlap_tv
;
664 ast_mutex_unlock(&ch
->overlap_tv_lock
);
666 tv_end
.tv_sec
+= ch
->overlap_dial
;
667 tv_now
= ast_tvnow();
669 diff
= ast_tvdiff_ms(tv_end
, tv_now
);
672 char *dad
=ch
->bc
->dad
, sexten
[]="s";
673 /* if we are 100ms near the timeout, we are satisfied.. */
676 if (ast_strlen_zero(ch
->bc
->dad
)) {
678 strcpy(ch
->ast
->exten
, sexten
);
681 if (ast_exists_extension(ch
->ast
, ch
->context
, dad
, 1, ch
->bc
->oad
)) {
682 ch
->state
=MISDN_DIALING
;
683 if (pbx_start_chan(ch
) < 0) {
684 chan_misdn_log(-1, ch
->bc
->port
, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
685 goto misdn_overlap_dial_task_disconnect
;
688 misdn_overlap_dial_task_disconnect
:
689 hanguptone_indicate(ch
);
691 ch
->state
=MISDN_CLEANING
;
692 misdn_lib_send_event(ch
->bc
, EVENT_DISCONNECT
);
694 ch
->overlap_dial_task
= -1;
700 static void send_digit_to_chan(struct chan_list
*cl
, char digit
)
702 static const char* dtmf_tones
[] = {
703 "!941+1336/100,!0/100", /* 0 */
704 "!697+1209/100,!0/100", /* 1 */
705 "!697+1336/100,!0/100", /* 2 */
706 "!697+1477/100,!0/100", /* 3 */
707 "!770+1209/100,!0/100", /* 4 */
708 "!770+1336/100,!0/100", /* 5 */
709 "!770+1477/100,!0/100", /* 6 */
710 "!852+1209/100,!0/100", /* 7 */
711 "!852+1336/100,!0/100", /* 8 */
712 "!852+1477/100,!0/100", /* 9 */
713 "!697+1633/100,!0/100", /* A */
714 "!770+1633/100,!0/100", /* B */
715 "!852+1633/100,!0/100", /* C */
716 "!941+1633/100,!0/100", /* D */
717 "!941+1209/100,!0/100", /* * */
718 "!941+1477/100,!0/100" }; /* # */
719 struct ast_channel
*chan
=cl
->ast
;
721 if (digit
>= '0' && digit
<='9')
722 ast_playtones_start(chan
,0,dtmf_tones
[digit
-'0'], 0);
723 else if (digit
>= 'A' && digit
<= 'D')
724 ast_playtones_start(chan
,0,dtmf_tones
[digit
-'A'+10], 0);
725 else if (digit
== '*')
726 ast_playtones_start(chan
,0,dtmf_tones
[14], 0);
727 else if (digit
== '#')
728 ast_playtones_start(chan
,0,dtmf_tones
[15], 0);
731 ast_log(LOG_DEBUG
, "Unable to handle DTMF tone '%c' for '%s'\n", digit
, chan
->name
);
736 /*** CLI HANDLING ***/
737 static int misdn_set_debug(int fd
, int argc
, char *argv
[])
741 if (argc
!= 4 && argc
!= 5 && argc
!= 6 && argc
!= 7)
742 return RESULT_SHOWUSAGE
;
744 level
= atoi(argv
[3]);
752 if (strncasecmp(argv
[4], "only", strlen(argv
[4])))
753 return RESULT_SHOWUSAGE
;
757 for (i
=0; i
<=max_ports
; i
++) {
758 misdn_debug
[i
] = level
;
759 misdn_debug_only
[i
] = only
;
761 ast_cli(fd
, "changing debug level for all ports to %d%s\n",misdn_debug
[0], only
?" (only)":"");
767 if (strncasecmp(argv
[4], "port", strlen(argv
[4])))
768 return RESULT_SHOWUSAGE
;
769 port
= atoi(argv
[5]);
770 if (port
<= 0 || port
> max_ports
) {
773 ast_cli(fd
, "port number not valid! no ports available so you won't get lucky with any number here...\n");
776 ast_cli(fd
, "port number not valid! only port 1 is available.\n");
779 ast_cli(fd
, "port number not valid! only ports 1 to %d are available.\n", max_ports
);
784 if (strncasecmp(argv
[6], "only", strlen(argv
[6])))
785 return RESULT_SHOWUSAGE
;
787 misdn_debug_only
[port
] = 1;
789 misdn_debug_only
[port
] = 0;
790 misdn_debug
[port
] = level
;
791 ast_cli(fd
, "changing debug level to %d%s for port %d\n", misdn_debug
[port
], misdn_debug_only
[port
]?" (only)":"", port
);
797 static int misdn_set_crypt_debug(int fd
, int argc
, char *argv
[])
799 if (argc
!= 5) return RESULT_SHOWUSAGE
;
804 static int misdn_port_block(int fd
, int argc
, char *argv
[])
809 return RESULT_SHOWUSAGE
;
811 port
= atoi(argv
[3]);
813 misdn_lib_port_block(port
);
818 static int misdn_port_unblock(int fd
, int argc
, char *argv
[])
823 return RESULT_SHOWUSAGE
;
825 port
= atoi(argv
[3]);
827 misdn_lib_port_unblock(port
);
833 static int misdn_restart_port (int fd
, int argc
, char *argv
[])
838 return RESULT_SHOWUSAGE
;
840 port
= atoi(argv
[3]);
842 misdn_lib_port_restart(port
);
847 static int misdn_restart_pid (int fd
, int argc
, char *argv
[])
852 return RESULT_SHOWUSAGE
;
856 misdn_lib_pid_restart(pid
);
861 static int misdn_port_up (int fd
, int argc
, char *argv
[])
866 return RESULT_SHOWUSAGE
;
868 port
= atoi(argv
[3]);
870 misdn_lib_get_port_up(port
);
875 static int misdn_port_down (int fd
, int argc
, char *argv
[])
880 return RESULT_SHOWUSAGE
;
882 port
= atoi(argv
[3]);
884 misdn_lib_get_port_down(port
);
889 static inline void show_config_description (int fd
, enum misdn_cfg_elements elem
)
891 char section
[BUFFERSIZE
];
892 char name
[BUFFERSIZE
];
893 char desc
[BUFFERSIZE
];
894 char def
[BUFFERSIZE
];
895 char tmp
[BUFFERSIZE
];
897 misdn_cfg_get_name(elem
, tmp
, sizeof(tmp
));
898 term_color(name
, tmp
, COLOR_BRWHITE
, 0, sizeof(tmp
));
899 misdn_cfg_get_desc(elem
, desc
, sizeof(desc
), def
, sizeof(def
));
901 if (elem
< MISDN_CFG_LAST
)
902 term_color(section
, "PORTS SECTION", COLOR_YELLOW
, 0, sizeof(section
));
904 term_color(section
, "GENERAL SECTION", COLOR_YELLOW
, 0, sizeof(section
));
907 ast_cli(fd
, "[%s] %s (Default: %s)\n\t%s\n", section
, name
, def
, desc
);
909 ast_cli(fd
, "[%s] %s\n\t%s\n", section
, name
, desc
);
912 static int misdn_show_config (int fd
, int argc
, char *argv
[])
914 char buffer
[BUFFERSIZE
];
915 enum misdn_cfg_elements elem
;
921 if (!strcmp(argv
[3], "description")) {
923 enum misdn_cfg_elements elem
= misdn_cfg_get_elem (argv
[4]);
924 if (elem
== MISDN_CFG_FIRST
)
925 ast_cli(fd
, "Unknown element: %s\n", argv
[4]);
927 show_config_description(fd
, elem
);
930 return RESULT_SHOWUSAGE
;
932 if (!strcmp(argv
[3], "descriptions")) {
933 if ((argc
== 4) || ((argc
== 5) && !strcmp(argv
[4], "general"))) {
934 for (elem
= MISDN_GEN_FIRST
+ 1; elem
< MISDN_GEN_LAST
; ++elem
) {
935 show_config_description(fd
, elem
);
940 if ((argc
== 4) || ((argc
== 5) && !strcmp(argv
[4], "ports"))) {
941 for (elem
= MISDN_CFG_FIRST
+ 1; elem
< MISDN_CFG_LAST
- 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem
) {
942 show_config_description(fd
, elem
);
947 return ok
? 0 : RESULT_SHOWUSAGE
;
949 if (!sscanf(argv
[3], "%d", &onlyport
) || onlyport
< 0) {
950 ast_cli(fd
, "Unknown option: %s\n", argv
[3]);
951 return RESULT_SHOWUSAGE
;
955 if (argc
== 3 || onlyport
== 0) {
956 ast_cli(fd
,"Misdn General-Config: \n");
957 for (elem
= MISDN_GEN_FIRST
+ 1, linebreak
= 1; elem
< MISDN_GEN_LAST
; elem
++, linebreak
++) {
958 misdn_cfg_get_config_string( 0, elem
, buffer
, BUFFERSIZE
);
959 ast_cli(fd
, "%-36s%s", buffer
, !(linebreak
% 2) ? "\n" : "");
965 int port
= misdn_cfg_get_next_port(0);
966 for (; port
> 0; port
= misdn_cfg_get_next_port(port
)) {
967 ast_cli(fd
, "\n[PORT %d]\n", port
);
968 for (elem
= MISDN_CFG_FIRST
+ 1, linebreak
= 1; elem
< MISDN_CFG_LAST
; elem
++, linebreak
++) {
969 misdn_cfg_get_config_string( port
, elem
, buffer
, BUFFERSIZE
);
970 ast_cli(fd
, "%-36s%s", buffer
, !(linebreak
% 2) ? "\n" : "");
977 if (misdn_cfg_is_port_valid(onlyport
)) {
978 ast_cli(fd
, "[PORT %d]\n", onlyport
);
979 for (elem
= MISDN_CFG_FIRST
+ 1, linebreak
= 1; elem
< MISDN_CFG_LAST
; elem
++, linebreak
++) {
980 misdn_cfg_get_config_string(onlyport
, elem
, buffer
, BUFFERSIZE
);
981 ast_cli(fd
, "%-36s%s", buffer
, !(linebreak
% 2) ? "\n" : "");
985 ast_cli(fd
, "Port %d is not active!\n", onlyport
);
991 struct state_struct
{
992 enum misdn_chan_state state
;
996 static struct state_struct state_array
[] = {
997 {MISDN_NOTHING
,"NOTHING"}, /* at beginning */
998 {MISDN_WAITING4DIGS
,"WAITING4DIGS"}, /* when waiting for infos */
999 {MISDN_EXTCANTMATCH
,"EXTCANTMATCH"}, /* when asterisk couldn't match our ext */
1000 {MISDN_INCOMING_SETUP
,"INCOMING SETUP"}, /* when pbx_start */
1001 {MISDN_DIALING
,"DIALING"}, /* when pbx_start */
1002 {MISDN_PROGRESS
,"PROGRESS"}, /* when pbx_start */
1003 {MISDN_PROCEEDING
,"PROCEEDING"}, /* when pbx_start */
1004 {MISDN_CALLING
,"CALLING"}, /* when misdn_call is called */
1005 {MISDN_CALLING_ACKNOWLEDGE
,"CALLING_ACKNOWLEDGE"}, /* when misdn_call is called */
1006 {MISDN_ALERTING
,"ALERTING"}, /* when Alerting */
1007 {MISDN_BUSY
,"BUSY"}, /* when BUSY */
1008 {MISDN_CONNECTED
,"CONNECTED"}, /* when connected */
1009 {MISDN_PRECONNECTED
,"PRECONNECTED"}, /* when connected */
1010 {MISDN_DISCONNECTED
,"DISCONNECTED"}, /* when connected */
1011 {MISDN_RELEASED
,"RELEASED"}, /* when connected */
1012 {MISDN_BRIDGED
,"BRIDGED"}, /* when bridged */
1013 {MISDN_CLEANING
,"CLEANING"}, /* when hangup from * but we were connected before */
1014 {MISDN_HUNGUP_FROM_MISDN
,"HUNGUP_FROM_MISDN"}, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
1015 {MISDN_HOLDED
,"HOLDED"}, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
1016 {MISDN_HOLD_DISCONNECT
,"HOLD_DISCONNECT"}, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
1017 {MISDN_HUNGUP_FROM_AST
,"HUNGUP_FROM_AST"} /* when DISCONNECT/RELEASE/REL_COMP came out of misdn_hangup */
1020 static char *misdn_get_ch_state(struct chan_list
*p
)
1023 static char state
[8];
1025 if( !p
) return NULL
;
1027 for (i
=0; i
< sizeof(state_array
)/sizeof(struct state_struct
); i
++) {
1028 if ( state_array
[i
].state
== p
->state
) return state_array
[i
].txt
;
1031 sprintf(state
,"%d",p
->state
) ;
1038 static void reload_config(void)
1042 if (!g_config_initialized
) {
1043 ast_log(LOG_WARNING
, "chan_misdn is not initialized properly, still reloading ?\n");
1049 misdn_cfg_update_ptp();
1050 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE
, global_tracefile
, BUFFERSIZE
);
1051 misdn_cfg_get( 0, MISDN_GEN_DEBUG
, &cfg_debug
, sizeof(int));
1053 for (i
= 0; i
<= max_ports
; i
++) {
1054 misdn_debug
[i
] = cfg_debug
;
1055 misdn_debug_only
[i
] = 0;
1059 static int misdn_reload (int fd
, int argc
, char *argv
[])
1061 ast_cli(fd
, "Reloading mISDN Config\n");
1066 static void print_bc_info (int fd
, struct chan_list
* help
, struct misdn_bchannel
* bc
)
1068 struct ast_channel
*ast
=help
->ast
;
1070 "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
1072 bc
->pid
, bc
->port
, bc
->channel
,
1074 help
->originator
== ORG_AST
?"*":"I",
1075 ast
?ast
->exten
:NULL
,
1076 ast
?ast
->cid
.cid_num
:NULL
,
1078 ast
?ast
->context
:NULL
,
1079 misdn_get_ch_state(help
)
1081 if (misdn_debug
[bc
->port
] > 0)
1083 " --> astname: %s\n"
1084 " --> ch_l3id: %x\n"
1085 " --> ch_addr: %x\n"
1086 " --> bc_addr: %x\n"
1087 " --> bc_l3id: %x\n"
1088 " --> display: %s\n"
1089 " --> activated: %d\n"
1091 " --> capability: %s\n"
1093 " --> pipeline: %s\n"
1095 " --> echo_cancel: %d\n"
1097 " --> notone : rx %d tx:%d\n"
1098 " --> bc_hold: %d\n",
1107 bc_state2str(bc
->bc_state
),
1108 bearer2str(bc
->capability
),
1115 help
->norxtone
,help
->notxtone
,
1121 static int misdn_show_cls (int fd
, int argc
, char *argv
[])
1123 struct chan_list
*help
=cl_te
;
1125 ast_cli(fd
,"Chan List: %p\n",cl_te
);
1127 for (;help
; help
=help
->next
) {
1128 struct misdn_bchannel
*bc
=help
->bc
;
1129 struct ast_channel
*ast
=help
->ast
;
1132 ast_cli(fd
, "chan_list obj. with l3id:%x has no bc and no ast Leg\n", help
->l3id
);
1135 ast_cli(fd
, "bc with pid:%d has no Ast Leg\n", bc
->pid
);
1138 if (misdn_debug
[0] > 2) ast_cli(fd
, "Bc:%p Ast:%p\n", bc
, ast
);
1140 print_bc_info(fd
, help
, bc
);
1142 if (help
->state
== MISDN_HOLDED
) {
1143 ast_cli(fd
, "ITS A HOLDED BC:\n");
1144 ast_cli(fd
, " --> l3_id: %x\n"
1145 " --> dad:%s oad:%s\n"
1146 " --> hold_port: %d\n"
1147 " --> hold_channel: %d\n"
1152 ,help
->hold_info
.port
1153 ,help
->hold_info
.channel
1156 ast_cli(fd
,"* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast
->exten
, ast
->cid
.cid_num
);
1161 misdn_dump_chanlist();
1165 static int misdn_show_cl (int fd
, int argc
, char *argv
[])
1167 struct chan_list
*help
=cl_te
;
1170 return RESULT_SHOWUSAGE
;
1172 for (;help
; help
=help
->next
) {
1173 struct misdn_bchannel
*bc
=help
->bc
;
1174 struct ast_channel
*ast
=help
->ast
;
1177 if (!strcasecmp(ast
->name
,argv
[3])) {
1178 print_bc_info(fd
, help
, bc
);
1191 static int misdn_set_tics (int fd
, int argc
, char *argv
[])
1194 return RESULT_SHOWUSAGE
;
1196 MAXTICS
=atoi(argv
[3]);
1201 static int misdn_show_stacks (int fd
, int argc
, char *argv
[])
1205 ast_cli(fd
, "BEGIN STACK_LIST:\n");
1207 for (port
=misdn_cfg_get_next_port(0); port
> 0;
1208 port
=misdn_cfg_get_next_port(port
)) {
1210 get_show_stack_details(port
,buf
);
1211 ast_cli(fd
," %s Debug:%d%s\n", buf
, misdn_debug
[port
], misdn_debug_only
[port
]?"(only)":"");
1218 static int misdn_show_ports_stats (int fd
, int argc
, char *argv
[])
1222 ast_cli(fd
, "Port\tin_calls\tout_calls\n");
1224 for (port
=misdn_cfg_get_next_port(0); port
> 0;
1225 port
=misdn_cfg_get_next_port(port
)) {
1226 ast_cli(fd
,"%d\t%d\t\t%d\n",port
,misdn_in_calls
[port
],misdn_out_calls
[port
]);
1235 static int misdn_show_port (int fd
, int argc
, char *argv
[])
1241 return RESULT_SHOWUSAGE
;
1243 port
= atoi(argv
[3]);
1245 ast_cli(fd
, "BEGIN STACK_LIST:\n");
1247 get_show_stack_details(port
,buf
);
1248 ast_cli(fd
," %s Debug:%d%s\n",buf
, misdn_debug
[port
], misdn_debug_only
[port
]?"(only)":"");
1254 static int misdn_send_cd (int fd
, int argc
, char *argv
[])
1260 return RESULT_SHOWUSAGE
;
1265 ast_cli(fd
, "Sending Calldeflection (%s) to %s\n",nr
, channame
);
1268 struct chan_list
*tmp
=get_chan_by_ast_name(channame
);
1271 ast_cli(fd
, "Sending CD with nr %s to %s failed: Channel does not exist.\n",nr
, channame
);
1274 if (strlen(nr
) >= 15) {
1275 ast_cli(fd
, "Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n",nr
, channame
);
1278 tmp
->bc
->fac_out
.Function
= Fac_CD
;
1279 strncpy((char *)tmp
->bc
->fac_out
.u
.CDeflection
.DeflectedToNumber
, nr
, sizeof(tmp
->bc
->fac_out
.u
.CDeflection
.DeflectedToNumber
));
1280 misdn_lib_send_event(tmp
->bc
, EVENT_FACILITY
);
1287 static int misdn_send_restart(int fd
, int argc
, char *argv
[])
1292 if ( (argc
< 4) || (argc
> 5) )
1293 return RESULT_SHOWUSAGE
;
1295 port
= atoi(argv
[3]);
1298 channel
= atoi(argv
[4]);
1299 misdn_lib_send_restart(port
, channel
);
1301 misdn_lib_send_restart(port
, -1 );
1306 static int misdn_send_digit (int fd
, int argc
, char *argv
[])
1312 return RESULT_SHOWUSAGE
;
1317 ast_cli(fd
, "Sending %s to %s\n",msg
, channame
);
1320 struct chan_list
*tmp
=get_chan_by_ast_name(channame
);
1323 ast_cli(fd
, "Sending %s to %s failed Channel does not exist\n",msg
, channame
);
1328 int msglen
= strlen(msg
);
1329 for (i
=0; i
<msglen
; i
++) {
1330 ast_cli(fd
, "Sending: %c\n",msg
[i
]);
1331 send_digit_to_chan(tmp
, msg
[i
]);
1332 /* res = ast_safe_sleep(tmp->ast, 250); */
1334 /* res = ast_waitfor(tmp->ast,100); */
1338 res
= ast_dtmf_stream(tmp
->ast
,NULL
,msg
,250);
1346 static int misdn_toggle_echocancel (int fd
, int argc
, char *argv
[])
1351 return RESULT_SHOWUSAGE
;
1355 ast_cli(fd
, "Toggling EchoCancel on %s\n", channame
);
1358 struct chan_list
*tmp
=get_chan_by_ast_name(channame
);
1361 ast_cli(fd
, "Toggling EchoCancel %s failed Channel does not exist\n", channame
);
1365 tmp
->toggle_ec
=tmp
->toggle_ec
?0:1;
1367 if (tmp
->toggle_ec
) {
1369 update_pipeline_config(tmp
->bc
);
1371 update_ec_config(tmp
->bc
);
1373 manager_ec_enable(tmp
->bc
);
1375 manager_ec_disable(tmp
->bc
);
1383 static int misdn_send_display (int fd
, int argc
, char *argv
[])
1389 return RESULT_SHOWUSAGE
;
1394 ast_cli(fd
, "Sending %s to %s\n",msg
, channame
);
1396 struct chan_list
*tmp
;
1397 tmp
=get_chan_by_ast_name(channame
);
1399 if (tmp
&& tmp
->bc
) {
1400 ast_copy_string(tmp
->bc
->display
, msg
, sizeof(tmp
->bc
->display
));
1401 misdn_lib_send_event(tmp
->bc
, EVENT_INFORMATION
);
1403 ast_cli(fd
,"No such channel %s\n",channame
);
1404 return RESULT_FAILURE
;
1408 return RESULT_SUCCESS
;
1411 static char *complete_ch_helper(const char *line
, const char *word
, int pos
, int state
, int rpos
)
1413 struct ast_channel
*c
;
1418 c
= ast_channel_walk_locked(NULL
);
1420 if (!strncasecmp(word
, c
->name
, strlen(word
))) {
1421 if (++which
> state
)
1424 ast_mutex_unlock(&c
->lock
);
1425 c
= ast_channel_walk_locked(c
);
1428 ret
= strdup(c
->name
);
1429 ast_mutex_unlock(&c
->lock
);
1435 static char *complete_ch(const char *line
, const char *word
, int pos
, int state
)
1437 return complete_ch_helper(line
, word
, pos
, state
, 3);
1440 static char *complete_debug_port (const char *line
, const char *word
, int pos
, int state
)
1446 case 4: if (*word
== 'p')
1447 return strdup("port");
1448 else if (*word
== 'o')
1449 return strdup("only");
1451 case 6: if (*word
== 'o')
1452 return strdup("only");
1458 static char *complete_show_config (const char *line
, const char *word
, int pos
, int state
)
1460 char buffer
[BUFFERSIZE
];
1461 enum misdn_cfg_elements elem
;
1462 int wordlen
= strlen(word
);
1467 case 3: if ((!strncmp(word
, "description", wordlen
)) && (++which
> state
))
1468 return strdup("description");
1469 if ((!strncmp(word
, "descriptions", wordlen
)) && (++which
> state
))
1470 return strdup("descriptions");
1471 if ((!strncmp(word
, "0", wordlen
)) && (++which
> state
))
1473 while ((port
= misdn_cfg_get_next_port(port
)) != -1) {
1474 snprintf(buffer
, sizeof(buffer
), "%d", port
);
1475 if ((!strncmp(word
, buffer
, wordlen
)) && (++which
> state
)) {
1476 return strdup(buffer
);
1481 if (strstr(line
, "description ")) {
1482 for (elem
= MISDN_CFG_FIRST
+ 1; elem
< MISDN_GEN_LAST
; ++elem
) {
1483 if ((elem
== MISDN_CFG_LAST
) || (elem
== MISDN_GEN_FIRST
))
1485 misdn_cfg_get_name(elem
, buffer
, BUFFERSIZE
);
1486 if (!wordlen
|| !strncmp(word
, buffer
, wordlen
)) {
1487 if (++which
> state
)
1488 return strdup(buffer
);
1491 } else if (strstr(line
, "descriptions ")) {
1492 if ((!wordlen
|| !strncmp(word
, "general", wordlen
)) && (++which
> state
))
1493 return strdup("general");
1494 if ((!wordlen
|| !strncmp(word
, "ports", wordlen
)) && (++which
> state
))
1495 return strdup("ports");
1502 static struct ast_cli_entry chan_misdn_clis
[] = {
1503 { {"misdn","send","calldeflect", NULL
}, misdn_send_cd
, "Sends CallDeflection to mISDN Channel",
1504 "Usage: misdn send calldeflect <channel> \"<nr>\" \n", complete_ch
},
1505 { {"misdn","send","digit", NULL
}, misdn_send_digit
, "Sends DTMF Digit to mISDN Channel",
1506 "Usage: misdn send digit <channel> \"<msg>\" \n"
1507 " Send <digit> to <channel> as DTMF Tone\n"
1508 " when channel is a mISDN channel\n", complete_ch
},
1509 { {"misdn","toggle","echocancel", NULL
}, misdn_toggle_echocancel
, "Toggles EchoCancel on mISDN Channel",
1510 "Usage: misdn toggle echocancel <channel>\n", complete_ch
},
1511 { {"misdn","send","display", NULL
}, misdn_send_display
, "Sends Text to mISDN Channel",
1512 "Usage: misdn send display <channel> \"<msg>\" \n"
1513 " Send <msg> to <channel> as Display Message\n"
1514 " when channel is a mISDN channel\n", complete_ch
},
1515 { {"misdn","show","config", NULL
}, misdn_show_config
, "Shows internal mISDN config, read from cfg-file",
1516 "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
1517 " Use 0 for <port> to only print the general config.\n", complete_show_config
},
1518 { {"misdn","reload", NULL
}, misdn_reload
, "Reloads internal mISDN config, read from cfg-file",
1519 "Usage: misdn reload\n" },
1520 { {"misdn","set","tics", NULL
}, misdn_set_tics
, "",
1522 { {"misdn","show","channels", NULL
}, misdn_show_cls
, "Shows internal mISDN chan_list",
1523 "Usage: misdn show channels\n" },
1524 { {"misdn","show","channel", NULL
}, misdn_show_cl
, "Shows internal mISDN chan_list",
1525 "Usage: misdn show channels\n", complete_ch
},
1526 { {"misdn","port","block", NULL
}, misdn_port_block
, "Blocks the given port",
1527 "Usage: misdn port block\n" },
1528 { {"misdn","port","unblock", NULL
}, misdn_port_unblock
, "Unblocks the given port",
1529 "Usage: misdn port unblock\n" },
1530 { {"misdn","restart","port", NULL
}, misdn_restart_port
, "Restarts the given port",
1531 "Usage: misdn restart port\n" },
1532 { {"misdn","restart","pid", NULL
}, misdn_restart_pid
, "Restarts the given pid",
1533 "Usage: misdn restart pid\n" },
1534 { {"misdn","send","restart", NULL
}, misdn_send_restart
,
1535 "Sends a restart for every bchannel on the given port",
1536 "Usage: misdn send restart <port>\n"},
1537 { {"misdn","port","up", NULL
}, misdn_port_up
, "Tries to establish L1 on the given port",
1538 "Usage: misdn port up <port>\n" },
1539 { {"misdn","port","down", NULL
}, misdn_port_down
, "Tries to deactivate the L1 on the given port",
1540 "Usage: misdn port down <port>\n" },
1541 { {"misdn","show","stacks", NULL
}, misdn_show_stacks
, "Shows internal mISDN stack_list",
1542 "Usage: misdn show stacks\n" },
1543 { {"misdn","show","ports","stats", NULL
}, misdn_show_ports_stats
, "Shows chan_misdns call statistics per port",
1544 "Usage: misdn show port stats\n" },
1545 { {"misdn","show","port", NULL
}, misdn_show_port
, "Shows detailed information for given port",
1546 "Usage: misdn show port <port>\n" },
1547 { {"misdn","set","debug", NULL
}, misdn_set_debug
, "Sets Debuglevel of chan_misdn",
1548 "Usage: misdn set debug <level> [only] | [port <port> [only]]\n", complete_debug_port
},
1549 { {"misdn","set","crypt","debug", NULL
}, misdn_set_crypt_debug
, "Sets CryptDebuglevel of chan_misdn, at the moment, level={1,2}",
1550 "Usage: misdn set crypt debug <level>\n" }
1553 static int update_config (struct chan_list
*ch
, int orig
)
1555 struct ast_channel
*ast
=ch
->ast
;
1556 struct misdn_bchannel
*bc
=ch
->bc
;
1562 ast_log(LOG_WARNING
, "Cannot configure without chanlist\n");
1568 if (! ast
|| ! bc
) {
1569 ast_log(LOG_WARNING
, "Cannot configure without ast || bc\n");
1575 chan_misdn_log(7,port
,"update_config: Getting Config\n");
1577 misdn_cfg_get( port
, MISDN_CFG_HDLC
, &hdlc
, sizeof(int));
1580 switch (bc
->capability
) {
1581 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED
:
1582 case INFO_CAPABILITY_DIGITAL_RESTRICTED
:
1583 chan_misdn_log(1,bc
->port
," --> CONF HDLC\n");
1590 misdn_cfg_get( port
, MISDN_CFG_PRES
, &pres
, sizeof(int));
1591 misdn_cfg_get( port
, MISDN_CFG_SCREEN
, &screen
, sizeof(int));
1592 chan_misdn_log(2,port
," --> pres: %d screen: %d\n",pres
, screen
);
1594 if ( (pres
+ screen
) < 0 ) {
1596 chan_misdn_log(2,port
," --> pres: %x\n", ast
->cid
.cid_pres
);
1598 switch (ast
->cid
.cid_pres
& 0x60){
1600 case AST_PRES_RESTRICTED
:
1602 chan_misdn_log(2, port
, " --> PRES: Restricted (0x1)\n");
1606 case AST_PRES_UNAVAILABLE
:
1608 chan_misdn_log(2, port
, " --> PRES: Unavailable (0x2)\n");
1613 chan_misdn_log(2, port
, " --> PRES: Allowed (0x0)\n");
1616 switch (ast
->cid
.cid_pres
& 0x3){
1618 case AST_PRES_USER_NUMBER_UNSCREENED
:
1620 chan_misdn_log(2, port
, " --> SCREEN: Unscreened (0x0)\n");
1623 case AST_PRES_USER_NUMBER_PASSED_SCREEN
:
1625 chan_misdn_log(2, port
, " --> SCREEN: Passed Screen (0x1)\n");
1627 case AST_PRES_USER_NUMBER_FAILED_SCREEN
:
1629 chan_misdn_log(2, port
, " --> SCREEN: Failed Screen (0x2)\n");
1632 case AST_PRES_NETWORK_NUMBER
:
1634 chan_misdn_log(2, port
, " --> SCREEN: Network Nr. (0x3)\n");
1639 chan_misdn_log(2, port
, " --> SCREEN: Unscreened (0x0)\n");
1655 static void config_jitterbuffer(struct chan_list
*ch
)
1657 struct misdn_bchannel
*bc
=ch
->bc
;
1658 int len
=ch
->jb_len
, threshold
=ch
->jb_upper_threshold
;
1660 chan_misdn_log(5,bc
->port
, "config_jb: Called\n");
1663 chan_misdn_log(1,bc
->port
, "config_jb: Deactivating Jitterbuffer\n");
1667 if (len
<=100 || len
> 8000) {
1668 chan_misdn_log(0,bc
->port
,"config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
1672 if ( threshold
> len
) {
1673 chan_misdn_log(0,bc
->port
,"config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
1677 cb_log(0,bc
->port
,"config_jb: We've got a Jitterbuffer Already on this port.\n");
1678 misdn_jb_destroy(ch
->jb
);
1682 ch
->jb
=misdn_jb_init(len
, threshold
);
1690 void debug_numplan(int port
, int numplan
, char *type
)
1693 case NUMPLAN_INTERNATIONAL
:
1694 chan_misdn_log(2, port
, " --> %s: International\n",type
);
1696 case NUMPLAN_NATIONAL
:
1697 chan_misdn_log(2, port
, " --> %s: National\n",type
);
1699 case NUMPLAN_SUBSCRIBER
:
1700 chan_misdn_log(2, port
, " --> %s: Subscriber\n",type
);
1702 case NUMPLAN_UNKNOWN
:
1703 chan_misdn_log(2, port
, " --> %s: Unknown\n",type
);
1705 /* Maybe we should cut off the prefix if present ? */
1707 chan_misdn_log(0, port
, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
1716 static int update_pipeline_config(struct misdn_bchannel
*bc
)
1720 misdn_cfg_get(bc
->port
, MISDN_CFG_PIPELINE
, bc
->pipeline
, sizeof(bc
->pipeline
));
1725 misdn_cfg_get(bc
->port
, MISDN_CFG_ECHOCANCEL
, &ec
, sizeof(int));
1727 snprintf(bc
->pipeline
, sizeof(bc
->pipeline
) - 1, "mg2ec");
1729 snprintf(bc
->pipeline
, sizeof(bc
->pipeline
) - 1, "mg2ec(deftaps=%d)", ec
);
1734 static int update_ec_config(struct misdn_bchannel
*bc
)
1739 misdn_cfg_get( port
, MISDN_CFG_ECHOCANCEL
, &ec
, sizeof(int));
1743 } else if ( ec
> 1 ) {
1753 static int read_config(struct chan_list
*ch
, int orig
)
1755 struct ast_channel
*ast
;
1756 struct misdn_bchannel
*bc
;
1758 char lang
[BUFFERSIZE
+1];
1759 char localmusicclass
[BUFFERSIZE
+1];
1760 char faxdetect
[BUFFERSIZE
+1];
1764 ast_log(LOG_WARNING
, "Cannot configure without chanlist\n");
1770 if (! ast
|| ! bc
) {
1771 ast_log(LOG_WARNING
, "Cannot configure without ast || bc\n");
1778 chan_misdn_log(1,port
,"read_config: Getting Config\n");
1780 misdn_cfg_get( port
, MISDN_CFG_LANGUAGE
, lang
, BUFFERSIZE
);
1781 ast_string_field_set(ast
, language
, lang
);
1783 misdn_cfg_get( port
, MISDN_CFG_MUSICCLASS
, localmusicclass
, BUFFERSIZE
);
1784 ast_string_field_set(ast
, musicclass
, localmusicclass
);
1787 misdn_cfg_get( port
, MISDN_CFG_TXGAIN
, &bc
->txgain
, sizeof(int));
1788 misdn_cfg_get( port
, MISDN_CFG_RXGAIN
, &bc
->rxgain
, sizeof(int));
1790 misdn_cfg_get( port
, MISDN_CFG_INCOMING_EARLY_AUDIO
, &ch
->incoming_early_audio
, sizeof(int));
1792 misdn_cfg_get( port
, MISDN_CFG_SENDDTMF
, &bc
->send_dtmf
, sizeof(int));
1794 misdn_cfg_get( port
, MISDN_CFG_ASTDTMF
, &ch
->ast_dsp
, sizeof(int));
1800 misdn_cfg_get( port
, MISDN_CFG_NEED_MORE_INFOS
, &bc
->need_more_infos
, sizeof(int));
1801 misdn_cfg_get( port
, MISDN_CFG_NTTIMEOUT
, &ch
->nttimeout
, sizeof(int));
1803 misdn_cfg_get( port
, MISDN_CFG_NOAUTORESPOND_ON_SETUP
, &ch
->noautorespond_on_setup
, sizeof(int));
1805 misdn_cfg_get( port
, MISDN_CFG_FAR_ALERTING
, &ch
->far_alerting
, sizeof(int));
1807 misdn_cfg_get( port
, MISDN_CFG_ALLOWED_BEARERS
, &ch
->allowed_bearers
, BUFFERSIZE
);
1809 misdn_cfg_get( port
, MISDN_CFG_FAXDETECT
, faxdetect
, BUFFERSIZE
);
1811 misdn_cfg_get( port
, MISDN_CFG_HDLC
, &hdlc
, sizeof(int));
1814 switch (bc
->capability
) {
1815 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED
:
1816 case INFO_CAPABILITY_DIGITAL_RESTRICTED
:
1817 chan_misdn_log(1,bc
->port
," --> CONF HDLC\n");
1823 /*Initialize new Jitterbuffer*/
1825 misdn_cfg_get( port
, MISDN_CFG_JITTERBUFFER
, &ch
->jb_len
, sizeof(int));
1826 misdn_cfg_get( port
, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD
, &ch
->jb_upper_threshold
, sizeof(int));
1828 config_jitterbuffer(ch
);
1831 misdn_cfg_get( bc
->port
, MISDN_CFG_CONTEXT
, ch
->context
, sizeof(ch
->context
));
1833 ast_copy_string (ast
->context
,ch
->context
,sizeof(ast
->context
));
1836 update_pipeline_config(bc
);
1838 update_ec_config(bc
);
1844 misdn_cfg_get( bc
->port
, MISDN_CFG_EARLY_BCONNECT
, &eb3
, sizeof(int));
1845 bc
->early_bconnect
=eb3
;
1854 misdn_cfg_get(port
, MISDN_CFG_PICKUPGROUP
, &pg
, sizeof(pg
));
1855 misdn_cfg_get(port
, MISDN_CFG_CALLGROUP
, &cg
, sizeof(cg
));
1857 chan_misdn_log(5, port
, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf
,sizeof(buf
),cg
),ast_print_group(buf
,sizeof(buf
),pg
));
1858 ast
->pickupgroup
=pg
;
1862 if ( orig
== ORG_AST
) {
1863 misdn_cfg_get( port
, MISDN_CFG_TE_CHOOSE_CHANNEL
, &(bc
->te_choose_channel
), sizeof(int));
1865 if (strstr(faxdetect
, "outgoing") || strstr(faxdetect
, "both")) {
1866 if (strstr(faxdetect
, "nojump"))
1873 char callerid
[BUFFERSIZE
+1];
1874 misdn_cfg_get( port
, MISDN_CFG_CALLERID
, callerid
, BUFFERSIZE
);
1875 if ( ! ast_strlen_zero(callerid
) ) {
1876 chan_misdn_log(1, port
, " --> * Setting Cid to %s\n", callerid
);
1878 int l
= sizeof(bc
->oad
);
1879 strncpy(bc
->oad
,callerid
, l
);
1886 misdn_cfg_get( port
, MISDN_CFG_DIALPLAN
, &bc
->dnumplan
, sizeof(int));
1887 misdn_cfg_get( port
, MISDN_CFG_LOCALDIALPLAN
, &bc
->onumplan
, sizeof(int));
1888 misdn_cfg_get( port
, MISDN_CFG_CPNDIALPLAN
, &bc
->cpnnumplan
, sizeof(int));
1889 debug_numplan(port
, bc
->dnumplan
,"TON");
1890 debug_numplan(port
, bc
->onumplan
,"LTON");
1891 debug_numplan(port
, bc
->cpnnumplan
,"CTON");
1894 ch
->overlap_dial
= 0;
1895 } else { /** ORIGINATOR MISDN **/
1896 char prefix
[BUFFERSIZE
+1]="";
1897 if (strstr(faxdetect
, "incoming") || strstr(faxdetect
, "both")) {
1898 if (strstr(faxdetect
, "nojump"))
1904 misdn_cfg_get( port
, MISDN_CFG_CPNDIALPLAN
, &bc
->cpnnumplan
, sizeof(int));
1905 debug_numplan(port
, bc
->cpnnumplan
,"CTON");
1907 switch( bc
->onumplan
) {
1908 case NUMPLAN_INTERNATIONAL
:
1909 misdn_cfg_get( bc
->port
, MISDN_CFG_INTERNATPREFIX
, prefix
, BUFFERSIZE
);
1912 case NUMPLAN_NATIONAL
:
1913 misdn_cfg_get( bc
->port
, MISDN_CFG_NATPREFIX
, prefix
, BUFFERSIZE
);
1920 int l
= strlen(prefix
) + strlen(bc
->oad
);
1921 char *tmp
= alloca(l
+1);
1923 strcat(tmp
,bc
->oad
);
1924 strcpy(bc
->oad
,tmp
);
1927 if (!ast_strlen_zero(bc
->dad
)) {
1928 ast_copy_string(bc
->orig_dad
,bc
->dad
, sizeof(bc
->orig_dad
));
1931 if ( ast_strlen_zero(bc
->dad
) && !ast_strlen_zero(bc
->keypad
)) {
1932 ast_copy_string(bc
->dad
,bc
->keypad
, sizeof(bc
->dad
));
1937 switch( bc
->dnumplan
) {
1938 case NUMPLAN_INTERNATIONAL
:
1939 misdn_cfg_get( bc
->port
, MISDN_CFG_INTERNATPREFIX
, prefix
, BUFFERSIZE
);
1941 case NUMPLAN_NATIONAL
:
1942 misdn_cfg_get( bc
->port
, MISDN_CFG_NATPREFIX
, prefix
, BUFFERSIZE
);
1949 int l
= strlen(prefix
) + strlen(bc
->dad
);
1950 char *tmp
= alloca(l
+1);
1952 strcat(tmp
,bc
->dad
);
1953 strcpy(bc
->dad
,tmp
);
1956 if ( strcmp(bc
->dad
,ast
->exten
)) {
1957 ast_copy_string(ast
->exten
, bc
->dad
, sizeof(ast
->exten
));
1960 ast_set_callerid(ast
, bc
->oad
, NULL
, bc
->oad
);
1962 if ( !ast_strlen_zero(bc
->rad
) ) {
1963 if (ast
->cid
.cid_rdnis
)
1964 free(ast
->cid
.cid_rdnis
);
1965 ast
->cid
.cid_rdnis
= strdup(bc
->rad
);
1968 misdn_cfg_get(bc
->port
, MISDN_CFG_OVERLAP_DIAL
, &ch
->overlap_dial
, sizeof(ch
->overlap_dial
));
1969 ast_mutex_init(&ch
->overlap_tv_lock
);
1970 } /* ORIG MISDN END */
1972 ch
->overlap_dial_task
= -1;
1974 if (ch
->faxdetect
|| ch
->ast_dsp
) {
1975 misdn_cfg_get( port
, MISDN_CFG_FAXDETECT_TIMEOUT
, &ch
->faxdetect_timeout
, sizeof(ch
->faxdetect_timeout
));
1977 ch
->dsp
= ast_dsp_new();
1980 ast_dsp_set_features(ch
->dsp
, DSP_FEATURE_DTMF_DETECT
| DSP_FEATURE_FAX_DETECT
);
1982 ast_dsp_set_features(ch
->dsp
, DSP_FEATURE_DTMF_DETECT
);
1985 ch
->trans
=ast_translator_build_path(AST_FORMAT_SLINEAR
, AST_FORMAT_ALAW
);
1988 /* AOCD initialization */
1989 bc
->AOCDtype
= Fac_None
;
1995 /*****************************/
1996 /*** AST Indications Start ***/
1997 /*****************************/
1999 static int misdn_call(struct ast_channel
*ast
, char *dest
, int timeout
)
2004 struct chan_list
*ch
=MISDN_ASTERISK_TECH_PVT(ast
);
2005 struct misdn_bchannel
*newbc
;
2006 char *opts
=NULL
, *ext
;
2009 ext
= ast_strdupa(dest
);
2015 ast_log(LOG_WARNING
, "Malformed dialstring\n");
2021 ast_log(LOG_WARNING
, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
2025 if (((ast
->_state
!= AST_STATE_DOWN
) && (ast
->_state
!= AST_STATE_RESERVED
)) || !dest
) {
2026 ast_log(LOG_WARNING
, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast
->name
);
2027 ast
->hangupcause
=41;
2028 ast_setstate(ast
, AST_STATE_DOWN
);
2033 ast_log(LOG_WARNING
, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast
->name
);
2034 ast
->hangupcause
=41;
2035 ast_setstate(ast
, AST_STATE_DOWN
);
2042 ast_log(LOG_WARNING
, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast
->name
);
2043 ast
->hangupcause
=41;
2044 ast_setstate(ast
, AST_STATE_DOWN
);
2050 if ((exceed
=add_out_calls(port
))) {
2052 sprintf(tmp
,"%d",exceed
);
2053 pbx_builtin_setvar_helper(ast
,"MAX_OVERFLOW",tmp
);
2057 chan_misdn_log(1, port
, "* CALL: %s\n",dest
);
2059 chan_misdn_log(2, port
, " --> * dad:%s tech:%s ctx:%s\n",ast
->exten
,ast
->name
, ast
->context
);
2061 chan_misdn_log(3, port
, " --> * adding2newbc ext %s\n",ast
->exten
);
2063 int l
= sizeof(newbc
->dad
);
2064 strncpy(ast
->exten
,ext
,sizeof(ast
->exten
));
2066 strncpy(newbc
->dad
,ext
,l
);
2068 newbc
->dad
[l
-1] = 0;
2071 if (ast
->cid
.cid_rdnis
)
2072 strcpy(newbc
->rad
, ast
->cid
.cid_rdnis
);
2076 chan_misdn_log(3, port
, " --> * adding2newbc callerid %s\n",ast
->cid
.cid_num
);
2077 if (ast_strlen_zero(newbc
->oad
) && ast
->cid
.cid_num
) {
2079 if (ast
->cid
.cid_num
) {
2080 int l
= sizeof(newbc
->oad
);
2081 strncpy(newbc
->oad
,ast
->cid
.cid_num
, l
);
2082 newbc
->oad
[l
-1] = 0;
2088 struct chan_list
*ch
=MISDN_ASTERISK_TECH_PVT(ast
);
2089 if (!ch
) { ast_verbose("No chan_list in misdn_call\n"); return -1;}
2091 newbc
->capability
=ast
->transfercapability
;
2092 pbx_builtin_setvar_helper(ast
,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc
->capability
));
2093 if ( ast
->transfercapability
== INFO_CAPABILITY_DIGITAL_UNRESTRICTED
) {
2094 chan_misdn_log(2, port
, " --> * Call with flag Digital\n");
2098 /* update screening and presentation */
2099 update_config(ch
,ORG_AST
);
2101 /* fill in some ies from channel vary*/
2102 import_ch(ast
, newbc
, ch
);
2104 /* Finally The Options Override Everything */
2106 misdn_set_opt_exec(ast
,opts
);
2108 chan_misdn_log(2,port
,"NO OPTS GIVEN\n");
2110 /*check for bridging*/
2111 misdn_cfg_get( 0, MISDN_GEN_BRIDGING
, &bridging
, sizeof(int));
2112 if (bridging
&& ch
->other_ch
) {
2114 chan_misdn_log(1, port
, "Disabling EC (aka Pipeline) on both Sides\n");
2115 *ch
->bc
->pipeline
=0;
2116 *ch
->other_ch
->bc
->pipeline
=0;
2118 chan_misdn_log(1, port
, "Disabling EC on both Sides\n");
2119 ch
->bc
->ec_enable
=0;
2120 ch
->other_ch
->bc
->ec_enable
=0;
2124 r
=misdn_lib_send_event( newbc
, EVENT_SETUP
);
2126 /** we should have l3id after sending setup **/
2127 ch
->l3id
=newbc
->l3_id
;
2130 if ( r
== -ENOCHAN
) {
2131 chan_misdn_log(0, port
, " --> * Theres no Channel at the moment .. !\n");
2132 chan_misdn_log(1, port
, " --> * SEND: State Down pid:%d\n",newbc
?newbc
->pid
:-1);
2133 ast
->hangupcause
=34;
2134 ast_setstate(ast
, AST_STATE_DOWN
);
2138 chan_misdn_log(2, port
, " --> * SEND: State Dialing pid:%d\n",newbc
?newbc
->pid
:1);
2140 ast_setstate(ast
, AST_STATE_DIALING
);
2141 ast
->hangupcause
=16;
2143 if (newbc
->nt
) stop_bc_tones(ch
);
2145 ch
->state
=MISDN_CALLING
;
2151 static int misdn_answer(struct ast_channel
*ast
)
2153 struct chan_list
*p
;
2156 if (!ast
|| ! (p
=MISDN_ASTERISK_TECH_PVT(ast
)) ) return -1;
2158 chan_misdn_log(1, p
? (p
->bc
? p
->bc
->port
: 0) : 0, "* ANSWER:\n");
2161 ast_log(LOG_WARNING
, " --> Channel not connected ??\n");
2162 ast_queue_hangup(ast
);
2166 chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n");
2168 ast_queue_hangup(ast
);
2172 const char *tmp_key
= pbx_builtin_getvar_helper(p
->ast
, "CRYPT_KEY");
2175 chan_misdn_log(1, p
->bc
->port
, " --> Connection will be BF crypted\n");
2177 int l
= sizeof(p
->bc
->crypt_key
);
2178 strncpy(p
->bc
->crypt_key
,tmp_key
, l
);
2179 p
->bc
->crypt_key
[l
-1] = 0;
2182 chan_misdn_log(3, p
->bc
->port
, " --> Connection is without BF encryption\n");
2188 const char *nodsp
=pbx_builtin_getvar_helper(ast
, "MISDN_DIGITAL_TRANS");
2190 chan_misdn_log(1, p
->bc
->port
, " --> Connection is transparent digital\n");
2197 p
->state
= MISDN_CONNECTED
;
2200 if ( ast_strlen_zero(p
->bc
->cad
) ) {
2201 chan_misdn_log(2,p
->bc
->port
," --> empty cad using dad\n");
2202 ast_copy_string(p
->bc
->cad
,p
->bc
->dad
,sizeof(p
->bc
->cad
));
2205 misdn_lib_send_event( p
->bc
, EVENT_CONNECT
);
2211 static int misdn_digit_begin(struct ast_channel
*chan
, char digit
)
2213 /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
2217 static int misdn_digit_end(struct ast_channel
*ast
, char digit
, unsigned int duration
)
2219 struct chan_list
*p
;
2220 struct misdn_bchannel
*bc
;
2222 if (!ast
|| ! (p
=MISDN_ASTERISK_TECH_PVT(ast
))) return -1;
2225 chan_misdn_log(1, bc
?bc
->port
:0, "* IND : Digit %c\n",digit
);
2228 ast_log(LOG_WARNING
, " --> !! Got Digit Event without having bchannel Object\n");
2232 switch (p
->state
) {
2240 l
= sizeof(bc
->infos_pending
);
2241 strncat(bc
->infos_pending
, buf
, l
- strlen(bc
->infos_pending
) - 1);
2244 case MISDN_CALLING_ACKNOWLEDGE
:
2246 bc
->info_dad
[0]=digit
;
2250 int l
= sizeof(bc
->dad
);
2251 strncat(bc
->dad
, bc
->info_dad
, l
- strlen(bc
->dad
) - 1);
2254 int l
= sizeof(p
->ast
->exten
);
2255 strncpy(p
->ast
->exten
, bc
->dad
, l
);
2256 p
->ast
->exten
[l
-1] = 0;
2259 misdn_lib_send_event( bc
, EVENT_INFORMATION
);
2264 /* Do not send Digits in CONNECTED State, when
2265 * the other side is too mISDN. */
2269 if ( bc
->send_dtmf
)
2270 send_digit_to_chan(p
,digit
);
2278 static int misdn_fixup(struct ast_channel
*oldast
, struct ast_channel
*ast
)
2280 struct chan_list
*p
;
2282 if (!ast
|| ! (p
=MISDN_ASTERISK_TECH_PVT(ast
) )) return -1;
2284 chan_misdn_log(1, p
->bc
?p
->bc
->port
:0, "* IND: Got Fixup State:%s L3id:%x\n", misdn_get_ch_state(p
), p
->l3id
);
2293 static int misdn_indication(struct ast_channel
*ast
, int cond
, const void *data
, size_t datalen
)
2295 struct chan_list
*p
;
2298 if (!ast
|| ! (p
=MISDN_ASTERISK_TECH_PVT(ast
))) {
2299 ast_log(LOG_WARNING
, "Returned -1 in misdn_indication\n");
2304 chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast
->exten
);
2305 ast_log(LOG_WARNING
, "Private Pointer but no bc ?\n");
2309 chan_misdn_log(5, p
->bc
->port
, "* IND : Indication [%d] from %s\n",cond
, ast
->exten
);
2312 case AST_CONTROL_BUSY
:
2313 chan_misdn_log(1, p
->bc
->port
, "* IND :\tbusy pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2314 ast_setstate(ast
,AST_STATE_BUSY
);
2316 p
->bc
->out_cause
=17;
2317 if (p
->state
!= MISDN_CONNECTED
) {
2319 misdn_lib_send_event( p
->bc
, EVENT_DISCONNECT
);
2321 chan_misdn_log(-1, p
->bc
->port
, " --> !! Got Busy in Connected State !?! ast:%s\n", ast
->name
);
2325 case AST_CONTROL_RING
:
2326 chan_misdn_log(1, p
->bc
->port
, "* IND :\tring pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2330 case AST_CONTROL_RINGING
:
2331 chan_misdn_log(1, p
->bc
->port
, "* IND :\tringing pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2333 case MISDN_ALERTING
:
2334 chan_misdn_log(2, p
->bc
->port
, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoring it\n",p
->bc
?p
->bc
->pid
:-1);
2336 case MISDN_CONNECTED
:
2337 chan_misdn_log(2, p
->bc
->port
, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n",p
->bc
?p
->bc
->pid
:-1);
2341 p
->state
=MISDN_ALERTING
;
2342 chan_misdn_log(2, p
->bc
->port
, " --> * IND :\tringing pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2343 misdn_lib_send_event( p
->bc
, EVENT_ALERTING
);
2345 if (p
->other_ch
&& p
->other_ch
->bc
) {
2346 if (misdn_inband_avail(p
->other_ch
->bc
)) {
2347 chan_misdn_log(2,p
->bc
->port
, " --> other End is mISDN and has inband info available\n");
2351 if (!p
->other_ch
->bc
->nt
) {
2352 chan_misdn_log(2,p
->bc
->port
, " --> other End is mISDN TE so it has inband info for sure (?)\n");
2357 chan_misdn_log(3, p
->bc
->port
, " --> * SEND: State Ring pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2358 ast_setstate(ast
,AST_STATE_RINGING
);
2360 if ( !p
->bc
->nt
&& (p
->originator
==ORG_MISDN
) && !p
->incoming_early_audio
)
2361 chan_misdn_log(2,p
->bc
->port
, " --> incoming_early_audio off\n");
2366 case AST_CONTROL_ANSWER
:
2367 chan_misdn_log(1, p
->bc
->port
, " --> * IND :\tanswer pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2370 case AST_CONTROL_TAKEOFFHOOK
:
2371 chan_misdn_log(1, p
->bc
->port
, " --> *\ttakeoffhook pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2374 case AST_CONTROL_OFFHOOK
:
2375 chan_misdn_log(1, p
->bc
->port
, " --> *\toffhook pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2378 case AST_CONTROL_FLASH
:
2379 chan_misdn_log(1, p
->bc
->port
, " --> *\tflash pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2381 case AST_CONTROL_PROGRESS
:
2382 chan_misdn_log(1, p
->bc
->port
, " --> * IND :\tprogress pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2383 misdn_lib_send_event( p
->bc
, EVENT_PROGRESS
);
2385 case AST_CONTROL_PROCEEDING
:
2386 chan_misdn_log(1, p
->bc
->port
, " --> * IND :\tproceeding pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2387 misdn_lib_send_event( p
->bc
, EVENT_PROCEEDING
);
2389 case AST_CONTROL_CONGESTION
:
2390 chan_misdn_log(1, p
->bc
->port
, " --> * IND :\tcongestion pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2392 p
->bc
->out_cause
=42;
2394 misdn_lib_send_event( p
->bc
, EVENT_DISCONNECT
);
2397 hanguptone_indicate(p
);
2401 chan_misdn_log(1, p
->bc
->port
, " --> * IND :\t-1! (stop indication) pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2405 if (p
->state
== MISDN_CONNECTED
)
2410 case AST_CONTROL_HOLD
:
2411 ast_moh_start(ast
,data
,ast
->musicclass
);
2412 chan_misdn_log(1, p
->bc
->port
, " --> *\tHOLD pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2414 case AST_CONTROL_UNHOLD
:
2416 chan_misdn_log(1, p
->bc
->port
, " --> *\tUNHOLD pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2419 chan_misdn_log(1, p
->bc
->port
, " --> * Unknown Indication:%d pid:%d\n",cond
,p
->bc
?p
->bc
->pid
:-1);
2425 static int misdn_hangup(struct ast_channel
*ast
)
2427 struct chan_list
*p
;
2428 struct misdn_bchannel
*bc
=NULL
;
2430 ast_log(LOG_DEBUG
, "misdn_hangup(%s)\n", ast
->name
);
2432 if (!ast
|| ! (p
=MISDN_ASTERISK_TECH_PVT(ast
) ) ) return -1;
2435 chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
2442 const char *tmp
=pbx_builtin_getvar_helper(ast
,"MISDN_USERUSER");
2444 ast_log(LOG_NOTICE
, "MISDN_USERUSER: %s\n", tmp
);
2445 strcpy(bc
->uu
, tmp
);
2446 bc
->uulen
=strlen(bc
->uu
);
2450 MISDN_ASTERISK_TECH_PVT(ast
)=NULL
;
2453 if (ast
->_state
== AST_STATE_RESERVED
||
2454 p
->state
== MISDN_NOTHING
||
2455 p
->state
== MISDN_HOLDED
||
2456 p
->state
== MISDN_HOLD_DISCONNECT
) {
2459 /* between request and call */
2460 ast_log(LOG_DEBUG
, "State Reserved (or nothing) => chanIsAvail\n");
2461 MISDN_ASTERISK_TECH_PVT(ast
)=NULL
;
2463 ast_mutex_lock(&release_lock
);
2464 cl_dequeue_chan(&cl_te
, p
);
2468 ast_mutex_unlock(&release_lock
);
2471 misdn_lib_release(bc
);
2477 ast_log(LOG_WARNING
,"Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p
), p
->l3id
);
2483 p
->need_queue_hangup
=0;
2492 const char *varcause
=NULL
;
2493 bc
->out_cause
=ast
->hangupcause
?ast
->hangupcause
:16;
2495 if ( (varcause
=pbx_builtin_getvar_helper(ast
, "HANGUPCAUSE")) ||
2496 (varcause
=pbx_builtin_getvar_helper(ast
, "PRI_CAUSE"))) {
2497 int tmpcause
=atoi(varcause
);
2498 bc
->out_cause
=tmpcause
?tmpcause
:16;
2501 chan_misdn_log(1, bc
->port
, "* IND : HANGUP\tpid:%d ctx:%s dad:%s oad:%s State:%s\n",p
->bc
?p
->bc
->pid
:-1, ast
->context
, ast
->exten
, ast
->cid
.cid_num
, misdn_get_ch_state(p
));
2502 chan_misdn_log(3, bc
->port
, " --> l3id:%x\n",p
->l3id
);
2503 chan_misdn_log(3, bc
->port
, " --> cause:%d\n",bc
->cause
);
2504 chan_misdn_log(2, bc
->port
, " --> out_cause:%d\n",bc
->out_cause
);
2505 chan_misdn_log(2, bc
->port
, " --> state:%s\n", misdn_get_ch_state(p
));
2509 case MISDN_INCOMING_SETUP
:
2510 /* This is the only place in misdn_hangup, where we
2511 * can call release_chan, else it might create lot's of trouble
2513 ast_log(LOG_NOTICE
, "release channel, in CALLING/INCOMING_SETUP state.. no other events happened\n");
2516 p
->state
=MISDN_CLEANING
;
2517 if (bc
->need_release_complete
)
2518 misdn_lib_send_event( bc
, EVENT_RELEASE_COMPLETE
);
2523 hanguptone_indicate(p
);
2525 if (bc
->need_disconnect
)
2526 misdn_lib_send_event( bc
, EVENT_DISCONNECT
);
2529 case MISDN_CALLING_ACKNOWLEDGE
:
2531 hanguptone_indicate(p
);
2533 if (bc
->need_disconnect
)
2534 misdn_lib_send_event( bc
, EVENT_DISCONNECT
);
2537 case MISDN_ALERTING
:
2538 case MISDN_PROGRESS
:
2539 case MISDN_PROCEEDING
:
2540 if (p
->originator
!= ORG_AST
)
2541 hanguptone_indicate(p
);
2543 /*p->state=MISDN_CLEANING;*/
2544 if (bc
->need_disconnect
)
2545 misdn_lib_send_event( bc
, EVENT_DISCONNECT
);
2547 case MISDN_CONNECTED
:
2548 case MISDN_PRECONNECTED
:
2549 /* Alerting or Disconnect */
2552 hanguptone_indicate(p
);
2553 p
->bc
->progress_indicator
=8;
2555 if (bc
->need_disconnect
)
2556 misdn_lib_send_event( bc
, EVENT_DISCONNECT
);
2558 /*p->state=MISDN_CLEANING;*/
2560 case MISDN_DISCONNECTED
:
2561 if (bc
->need_release
)
2562 misdn_lib_send_event( bc
, EVENT_RELEASE
);
2563 p
->state
=MISDN_CLEANING
; /* MISDN_HUNGUP_FROM_AST; */
2566 case MISDN_RELEASED
:
2567 case MISDN_CLEANING
:
2568 p
->state
=MISDN_CLEANING
;
2574 case MISDN_HOLD_DISCONNECT
:
2575 /* need to send release here */
2576 chan_misdn_log(1, bc
->port
, " --> cause %d\n",bc
->cause
);
2577 chan_misdn_log(1, bc
->port
, " --> out_cause %d\n",bc
->out_cause
);
2580 if (bc
->need_release
)
2581 misdn_lib_send_event(bc
,EVENT_RELEASE
);
2582 p
->state
=MISDN_CLEANING
;
2587 if (bc
->need_release
)
2588 misdn_lib_send_event(bc
, EVENT_RELEASE
);
2589 p
->state
=MISDN_CLEANING
;
2591 if (bc
->need_disconnect
)
2592 misdn_lib_send_event(bc
, EVENT_DISCONNECT
);
2596 p
->state
=MISDN_CLEANING
;
2601 chan_misdn_log(3, bc
->port
, " --> Channel: %s hanguped new state:%s\n",ast
->name
,misdn_get_ch_state(p
));
2607 static struct ast_frame
*process_ast_dsp(struct chan_list
*tmp
, struct ast_frame
*frame
)
2609 struct ast_frame
*f
,*f2
;
2612 f2
= ast_translate(tmp
->trans
, frame
, 0);
2613 f
= ast_dsp_process(tmp
->ast
, tmp
->dsp
, f2
);
2615 chan_misdn_log(0, tmp
->bc
->port
, "No T-Path found\n");
2620 if (!f
|| (f
->frametype
!= AST_FRAME_DTMF
))
2623 ast_log(LOG_DEBUG
, "Detected inband DTMF digit: %c\n", f
->subclass
);
2625 if (tmp
->faxdetect
&& (f
->subclass
== 'f')) {
2626 /* Fax tone -- Handle and return NULL */
2627 if (!tmp
->faxhandled
) {
2628 struct ast_channel
*ast
= tmp
->ast
;
2630 chan_misdn_log(0, tmp
->bc
->port
, "Fax detected, preparing %s for fax transfer.\n", ast
->name
);
2631 tmp
->bc
->rxgain
= 0;
2632 isdn_lib_update_rxgain(tmp
->bc
);
2633 tmp
->bc
->txgain
= 0;
2634 isdn_lib_update_txgain(tmp
->bc
);
2636 *tmp
->bc
->pipeline
= 0;
2638 tmp
->bc
->ec_enable
= 0;
2640 isdn_lib_update_ec(tmp
->bc
);
2641 isdn_lib_stop_dtmf(tmp
->bc
);
2642 switch (tmp
->faxdetect
) {
2644 if (strcmp(ast
->exten
, "fax")) {
2646 char context_tmp
[BUFFERSIZE
];
2647 misdn_cfg_get(tmp
->bc
->port
, MISDN_CFG_FAXDETECT_CONTEXT
, &context_tmp
, sizeof(context_tmp
));
2648 context
= ast_strlen_zero(context_tmp
) ? (ast_strlen_zero(ast
->macrocontext
) ? ast
->context
: ast
->macrocontext
) : context_tmp
;
2649 if (ast_exists_extension(ast
, context
, "fax", 1, ast
->cid
.cid_num
)) {
2650 if (option_verbose
> 2)
2651 ast_verbose(VERBOSE_PREFIX_3
"Redirecting %s to fax extension (context:%s)\n", ast
->name
, context
);
2652 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
2653 pbx_builtin_setvar_helper(ast
,"FAXEXTEN",ast
->exten
);
2654 if (ast_async_goto(ast
, context
, "fax", 1))
2655 ast_log(LOG_WARNING
, "Failed to async goto '%s' into fax of '%s'\n", ast
->name
, context
);
2657 ast_log(LOG_NOTICE
, "Fax detected, but no fax extension ctx:%s exten:%s\n", context
, ast
->exten
);
2659 ast_log(LOG_DEBUG
, "Already in a fax extension, not redirecting\n");
2662 ast_verbose(VERBOSE_PREFIX_3
"Not redirecting %s to fax extension, nojump is set.\n", ast
->name
);
2666 ast_log(LOG_DEBUG
, "Fax already handled\n");
2669 if (tmp
->ast_dsp
&& (f
->subclass
!= 'f')) {
2670 chan_misdn_log(2, tmp
->bc
->port
, " --> * SEND: DTMF (AST_DSP) :%c\n", f
->subclass
);
2677 static struct ast_frame
*misdn_read(struct ast_channel
*ast
)
2679 struct chan_list
*tmp
;
2685 chan_misdn_log(1,0,"misdn_read called without ast\n");
2688 if (!(tmp
=MISDN_ASTERISK_TECH_PVT(ast
))) {
2689 chan_misdn_log(1,0,"misdn_read called without ast->pvt\n");
2693 if (!tmp
->bc
&& !(tmp
->state
==MISDN_HOLDED
)) {
2694 chan_misdn_log(1,0,"misdn_read called without bc\n");
2702 FD_SET(tmp
->pipe
[0],&rrfs
);
2704 t
=select(FD_SETSIZE
,&rrfs
,NULL
, NULL
,&tv
);
2707 chan_misdn_log(3, tmp
->bc
->port
, "read Select Timed out\n");
2712 chan_misdn_log(-1, tmp
->bc
->port
, "Select Error (err=%s)\n",strerror(errno
));
2716 if (FD_ISSET(tmp
->pipe
[0],&rrfs
)) {
2717 len
=read(tmp
->pipe
[0],tmp
->ast_rd_buf
,sizeof(tmp
->ast_rd_buf
));
2720 /* we hangup here, since our pipe is closed */
2721 chan_misdn_log(2,tmp
->bc
->port
,"misdn_read: Pipe closed, hanging up\n");
2729 tmp
->frame
.frametype
= AST_FRAME_VOICE
;
2730 tmp
->frame
.subclass
= AST_FORMAT_ALAW
;
2731 tmp
->frame
.datalen
= len
;
2732 tmp
->frame
.samples
= len
;
2733 tmp
->frame
.mallocd
= 0;
2734 tmp
->frame
.offset
= 0;
2735 tmp
->frame
.delivery
= ast_tv(0,0) ;
2736 tmp
->frame
.src
= NULL
;
2737 tmp
->frame
.data
= tmp
->ast_rd_buf
;
2739 if (tmp
->faxdetect
&& !tmp
->faxhandled
) {
2740 if (tmp
->faxdetect_timeout
) {
2741 if (ast_tvzero(tmp
->faxdetect_tv
)) {
2742 tmp
->faxdetect_tv
= ast_tvnow();
2743 chan_misdn_log(2,tmp
->bc
->port
,"faxdetect: starting detection with timeout: %ds ...\n", tmp
->faxdetect_timeout
);
2744 return process_ast_dsp(tmp
, &tmp
->frame
);
2746 struct timeval tv_now
= ast_tvnow();
2747 int diff
= ast_tvdiff_ms(tv_now
, tmp
->faxdetect_tv
);
2748 if (diff
<= (tmp
->faxdetect_timeout
* 1000)) {
2749 chan_misdn_log(5,tmp
->bc
->port
,"faxdetect: detecting ...\n");
2750 return process_ast_dsp(tmp
, &tmp
->frame
);
2752 chan_misdn_log(2,tmp
->bc
->port
,"faxdetect: stopping detection (time ran out) ...\n");
2758 chan_misdn_log(5,tmp
->bc
->port
,"faxdetect: detecting ... (no timeout)\n");
2759 return process_ast_dsp(tmp
, &tmp
->frame
);
2763 return process_ast_dsp(tmp
, &tmp
->frame
);
2770 static int misdn_write(struct ast_channel
*ast
, struct ast_frame
*frame
)
2772 struct chan_list
*ch
;
2775 if (!ast
|| ! (ch
=MISDN_ASTERISK_TECH_PVT(ast
)) ) return -1;
2777 if (ch
->state
== MISDN_HOLDED
) {
2778 chan_misdn_log(7, 0, "misdn_write: Returning because holded\n");
2783 ast_log(LOG_WARNING
, "private but no bc\n");
2788 chan_misdn_log(7, ch
->bc
->port
, "misdn_write: Returning because notxtone\n");
2793 if ( !frame
->subclass
) {
2794 chan_misdn_log(4, ch
->bc
->port
, "misdn_write: * prods us\n");
2798 if ( !(frame
->subclass
& prefformat
)) {
2800 chan_misdn_log(-1, ch
->bc
->port
, "Got Unsupported Frame with Format:%d\n", frame
->subclass
);
2805 if ( !frame
->samples
) {
2806 chan_misdn_log(4, ch
->bc
->port
, "misdn_write: zero write\n");
2808 if (!strcmp(frame
->src
,"ast_prod")) {
2809 chan_misdn_log(1, ch
->bc
->port
, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch
));
2812 chan_misdn_log(4,ch
->bc
->port
,"Starting Playtones\n");
2813 misdn_lib_tone_generator_start(ch
->bc
);
2821 if ( ! ch
->bc
->addr
) {
2822 chan_misdn_log(8, ch
->bc
->port
, "misdn_write: no addr for bc dropping:%d\n", frame
->samples
);
2828 int i
, max
=5>frame
->samples
?frame
->samples
:5;
2830 printf("write2mISDN %p %d bytes: ", p
, frame
->samples
);
2832 for (i
=0; i
< max
; i
++) printf("%2.2x ",((char*) frame
->data
)[i
]);
2838 switch (ch
->bc
->bc_state
) {
2839 case BCHAN_ACTIVATED
:
2843 if (!ch
->dropped_frame_cnt
)
2844 chan_misdn_log(5, ch
->bc
->port
, "BC not active (nor bridged) dropping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n",frame
->samples
,ch
->bc
->addr
, ast
->exten
, ast
->cid
.cid_num
,misdn_get_ch_state( ch
), ch
->bc
->bc_state
, ch
->bc
->l3_id
);
2846 ch
->dropped_frame_cnt
++;
2847 if (ch
->dropped_frame_cnt
> 100) {
2848 ch
->dropped_frame_cnt
=0;
2849 chan_misdn_log(5, ch
->bc
->port
, "BC not active (nor bridged) dropping: %d frames addr:%x dropped > 100 frames!\n",frame
->samples
,ch
->bc
->addr
);
2856 chan_misdn_log(9, ch
->bc
->port
, "Sending :%d bytes 2 MISDN\n",frame
->samples
);
2857 if ( !ch
->bc
->nojitter
&& misdn_cap_is_speech(ch
->bc
->capability
) ) {
2858 /* Buffered Transmit (triggered by read from isdn side)*/
2859 if (misdn_jb_fill(ch
->jb
,frame
->data
,frame
->samples
) < 0) {
2861 cb_log(0,ch
->bc
->port
,"Misdn Jitterbuffer Overflow.\n");
2865 /*transmit without jitterbuffer*/
2866 i
=misdn_lib_tx2misdn_frm(ch
->bc
, frame
->data
, frame
->samples
);
2877 static enum ast_bridge_result
misdn_bridge (struct ast_channel
*c0
,
2878 struct ast_channel
*c1
, int flags
,
2879 struct ast_frame
**fo
,
2880 struct ast_channel
**rc
,
2884 struct chan_list
*ch1
,*ch2
;
2885 struct ast_channel
*carr
[2], *who
;
2887 struct ast_frame
*f
;
2891 ch1
=get_chan_by_ast(c0
);
2892 ch2
=get_chan_by_ast(c1
);
2901 misdn_cfg_get(ch1
->bc
->port
, MISDN_CFG_BRIDGING
, &p1_b
, sizeof(int));
2902 misdn_cfg_get(ch2
->bc
->port
, MISDN_CFG_BRIDGING
, &p2_b
, sizeof(int));
2904 if ( ! p1_b
|| ! p2_b
) {
2905 ast_log(LOG_NOTICE
, "Falling back to Asterisk bridging\n");
2906 return AST_BRIDGE_FAILED
;
2909 misdn_cfg_get( 0, MISDN_GEN_BRIDGING
, &bridging
, sizeof(int));
2911 /* trying to make a mISDN_dsp conference */
2912 chan_misdn_log(1, ch1
->bc
->port
, "I SEND: Making conference with Number:%d\n", ch1
->bc
->pid
+1);
2913 misdn_lib_bridge(ch1
->bc
,ch2
->bc
);
2916 if (option_verbose
> 2)
2917 ast_verbose(VERBOSE_PREFIX_3
"Native bridging %s and %s\n", c0
->name
, c1
->name
);
2919 chan_misdn_log(1, ch1
->bc
->port
, "* Making Native Bridge between %s and %s\n", ch1
->bc
->oad
, ch2
->bc
->oad
);
2921 if (! (flags
&AST_BRIDGE_DTMF_CHANNEL_0
) )
2924 if (! (flags
&AST_BRIDGE_DTMF_CHANNEL_1
) )
2929 who
= ast_waitfor_n(carr
, 2, &to
);
2932 ast_log(LOG_NOTICE
,"misdn_bridge: empty read, breaking out\n");
2937 if (!f
|| f
->frametype
== AST_FRAME_CONTROL
) {
2941 chan_misdn_log(4,ch1
->bc
->port
,"Read Null Frame\n");
2943 chan_misdn_log(4,ch1
->bc
->port
,"Read Frame Control class:%d\n",f
->subclass
);
2951 if ( f
->frametype
== AST_FRAME_DTMF
) {
2952 chan_misdn_log(1,0,"Read DTMF %d from %s\n",f
->subclass
, who
->exten
);
2960 if (f
->frametype
== AST_FRAME_VOICE
) {
2961 chan_misdn_log(1, ch1
->bc
->port
, "I SEND: Splitting conference with Number:%d\n", ch1
->bc
->pid
+1);
2976 chan_misdn_log(1, ch1
->bc
->port
, "I SEND: Splitting conference with Number:%d\n", ch1
->bc
->pid
+1);
2978 misdn_lib_split_bridge(ch1
->bc
,ch2
->bc
);
2981 return AST_BRIDGE_COMPLETE
;
2984 /** AST INDICATIONS END **/
2986 static int dialtone_indicate(struct chan_list
*cl
)
2988 const struct ind_tone_zone_sound
*ts
= NULL
;
2989 struct ast_channel
*ast
=cl
->ast
;
2993 chan_misdn_log(0,cl
->bc
->port
,"No Ast in dialtone_indicate\n");
2997 misdn_cfg_get( cl
->bc
->port
, MISDN_CFG_NODIALTONE
, &nd
, sizeof(nd
));
3000 chan_misdn_log(1,cl
->bc
->port
,"Not sending Dialtone, because config wants it\n");
3004 chan_misdn_log(3,cl
->bc
->port
," --> Dial\n");
3005 ts
=ast_get_indication_tone(ast
->zone
,"dial");
3011 /* This prods us in misdn_write */
3012 ast_playtones_start(ast
,0, ts
->data
, 0);
3018 static int hanguptone_indicate(struct chan_list
*cl
)
3020 misdn_lib_send_tone(cl
->bc
,TONE_HANGUP
);
3024 static int stop_indicate(struct chan_list
*cl
)
3026 struct ast_channel
*ast
=cl
->ast
;
3029 chan_misdn_log(0,cl
->bc
->port
,"No Ast in stop_indicate\n");
3033 chan_misdn_log(3,cl
->bc
->port
," --> None\n");
3034 misdn_lib_tone_generator_stop(cl
->bc
);
3035 ast_playtones_stop(ast
);
3038 /*ast_deactivate_generator(ast);*/
3044 static int start_bc_tones(struct chan_list
* cl
)
3046 misdn_lib_tone_generator_stop(cl
->bc
);
3052 static int stop_bc_tones(struct chan_list
*cl
)
3063 static struct chan_list
*init_chan_list(int orig
)
3065 struct chan_list
*cl
=malloc(sizeof(struct chan_list
));
3068 chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
3072 memset(cl
,0,sizeof(struct chan_list
));
3074 cl
->originator
=orig
;
3075 cl
->need_queue_hangup
=1;
3078 cl
->overlap_dial_task
=-1;
3084 static struct ast_channel
*misdn_request(const char *type
, int format
, void *data
, int *cause
)
3087 struct ast_channel
*tmp
= NULL
;
3088 char group
[BUFFERSIZE
+1]="";
3090 char buf2
[128], *ext
=NULL
, *port_str
;
3091 char *tokb
=NULL
, *p
=NULL
;
3092 int channel
=0, port
=0;
3093 struct misdn_bchannel
*newbc
= NULL
;
3096 struct chan_list
*cl
=init_chan_list(ORG_AST
);
3098 sprintf(buf
,"%s/%s",misdn_type
,(char*)data
);
3099 ast_copy_string(buf2
,data
, 128);
3101 port_str
=strtok_r(buf2
,"/", &tokb
);
3103 ext
=strtok_r(NULL
,"/", &tokb
);
3106 if (port_str
[0]=='g' && port_str
[1]==':' ) {
3107 /* We make a group call lets checkout which ports are in my group */
3109 strncpy(group
, port_str
, BUFFERSIZE
);
3111 chan_misdn_log(2, 0, " --> Group Call group: %s\n",group
);
3113 else if ((p
= strchr(port_str
, ':'))) {
3114 /* we have a preselected channel */
3116 channel
= atoi(++p
);
3117 port
= atoi(port_str
);
3118 chan_misdn_log(2, port
, " --> Call on preselected Channel (%d).\n", channel
);
3121 port
= atoi(port_str
);
3124 ast_log(LOG_WARNING
, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extension.conf\n",ext
);
3128 if (misdn_cfg_is_group_method(group
, METHOD_STANDARD_DEC
)) {
3129 chan_misdn_log(4, port
, " --> STARTING STANDARDDEC...\n");
3133 if (!ast_strlen_zero(group
)) {
3135 char cfg_group
[BUFFERSIZE
+1];
3136 struct robin_list
*rr
= NULL
;
3138 if (misdn_cfg_is_group_method(group
, METHOD_ROUND_ROBIN
)) {
3139 chan_misdn_log(4, port
, " --> STARTING ROUND ROBIN...\n");
3140 rr
= get_robin_position(group
);
3145 int port_bak
= rr
->port
;
3146 int chan_bak
= rr
->channel
;
3149 rr
->port
= misdn_cfg_get_next_port_spin(rr
->port
);
3151 for (; rr
->port
> 0; rr
->port
= misdn_cfg_get_next_port_spin(rr
->port
)) {
3155 int last_chance
= 0;
3157 misdn_cfg_get(rr
->port
, MISDN_CFG_GROUPNAME
, cfg_group
, BUFFERSIZE
);
3158 if (strcasecmp(cfg_group
, group
))
3161 misdn_cfg_get(rr
->port
, MISDN_CFG_PMP_L1_CHECK
, &check
, sizeof(int));
3162 port_up
= misdn_lib_port_up(rr
->port
, check
);
3164 if (check
&& !port_up
)
3165 chan_misdn_log(1, rr
->port
, "L1 is not Up on this Port\n");
3167 if (check
&& port_up
< 0)
3168 ast_log(LOG_WARNING
,"This port (%d) is blocked\n", rr
->port
);
3170 if ((port_start
== rr
->port
) && (port_up
<= 0))
3174 port_start
= rr
->port
;
3179 max_chan
= misdn_lib_get_maxchans(rr
->port
);
3181 for (++rr
->channel
; !last_chance
&& rr
->channel
<= max_chan
; ++rr
->channel
) {
3182 if (rr
->port
== port_bak
&& rr
->channel
== chan_bak
)
3185 chan_misdn_log(1, 0, "trying port:%d channel:%d\n", rr
->port
, rr
->channel
);
3186 newbc
= misdn_lib_get_free_bc(rr
->port
, rr
->channel
, 0, 0);
3188 chan_misdn_log(4, rr
->port
, " Success! Found port:%d channel:%d\n", newbc
->port
, newbc
->channel
);
3190 chan_misdn_log(4, rr
->port
, "portup:%d\n", port_up
);
3196 if (newbc
|| last_chance
)
3202 rr
->port
= port_bak
;
3203 rr
->channel
= chan_bak
;
3206 for (port
=misdn_cfg_get_next_port(0); port
> 0;
3207 port
=misdn_cfg_get_next_port(port
)) {
3209 misdn_cfg_get( port
, MISDN_CFG_GROUPNAME
, cfg_group
, BUFFERSIZE
);
3211 chan_misdn_log(3,port
, "Group [%s] Port [%d]\n", group
, port
);
3212 if (!strcasecmp(cfg_group
, group
)) {
3215 misdn_cfg_get(port
, MISDN_CFG_PMP_L1_CHECK
, &check
, sizeof(int));
3216 port_up
= misdn_lib_port_up(port
, check
);
3218 chan_misdn_log(4, port
, "portup:%d\n", port_up
);
3221 newbc
= misdn_lib_get_free_bc(port
, 0, 0, dec
);
3229 /* Group dial failed ?*/
3231 ast_log(LOG_WARNING
,
3232 "Could not Dial out on group '%s'.\n"
3233 "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
3234 "\tOr there was no free channel on none of the ports\n\n"
3238 } else { /* 'Normal' Port dial * Port dial */
3240 chan_misdn_log(1, port
," --> preselected_channel: %d\n",channel
);
3241 newbc
= misdn_lib_get_free_bc(port
, channel
, 0, dec
);
3244 ast_log(LOG_WARNING
, "Could not create channel on port:%d with extensions:%s\n",port
,ext
);
3250 /* create ast_channel and link all the objects together */
3253 tmp
= misdn_new(cl
, AST_STATE_RESERVED
, ext
, NULL
, format
, port
, channel
);
3255 ast_log(LOG_ERROR
,"Could not create Asterisk object\n");
3261 /* register chan in local list */
3262 cl_queue_chan(&cl_te
, cl
) ;
3264 /* fill in the config into the objects */
3265 read_config(cl
, ORG_AST
);
3274 static int misdn_send_text (struct ast_channel
*chan
, const char *text
)
3276 struct chan_list
*tmp
=chan
->tech_pvt
;
3278 if (tmp
&& tmp
->bc
) {
3279 ast_copy_string(tmp
->bc
->display
,text
,sizeof(tmp
->bc
->display
));
3280 misdn_lib_send_event(tmp
->bc
, EVENT_INFORMATION
);
3282 ast_log(LOG_WARNING
, "No chan_list but send_text request?\n");
3289 static struct ast_channel_tech misdn_tech
= {
3291 .description
="Channel driver for mISDN Support (Bri/Pri)",
3292 .capabilities
= AST_FORMAT_ALAW
,
3293 .requester
=misdn_request
,
3294 .send_digit_begin
=misdn_digit_begin
,
3295 .send_digit_end
=misdn_digit_end
,
3297 .bridge
=misdn_bridge
,
3298 .hangup
=misdn_hangup
,
3299 .answer
=misdn_answer
,
3302 .indicate
=misdn_indication
,
3304 .send_text
=misdn_send_text
,
3308 static struct ast_channel_tech misdn_tech_wo_bridge
= {
3310 .description
="Channel driver for mISDN Support (Bri/Pri)",
3311 .capabilities
=AST_FORMAT_ALAW
,
3312 .requester
=misdn_request
,
3313 .send_digit_begin
=misdn_digit_begin
,
3314 .send_digit_end
=misdn_digit_end
,
3316 .hangup
=misdn_hangup
,
3317 .answer
=misdn_answer
,
3320 .indicate
=misdn_indication
,
3322 .send_text
=misdn_send_text
,
3327 static int glob_channel
=0;
3329 static void update_name(struct ast_channel
*tmp
, int port
, int c
)
3332 int tmp_port
= misdn_cfg_get_next_port(0);
3333 for (; tmp_port
> 0; tmp_port
=misdn_cfg_get_next_port(tmp_port
)) {
3334 if (tmp_port
== port
) break;
3335 chan_offset
+=misdn_lib_port_is_pri(tmp_port
)?30:2;
3339 ast_string_field_build(tmp
, name
, "%s/%d-u%d",
3340 misdn_type
, chan_offset
+c
, glob_channel
++);
3342 chan_misdn_log(3,port
," --> updating channel name to [%s]\n",tmp
->name
);
3346 static struct ast_channel
*misdn_new(struct chan_list
*chlist
, int state
, char *exten
, char *callerid
, int format
, int port
, int c
)
3348 struct ast_channel
*tmp
;
3349 char *cid_name
= 0, *cid_num
= 0;
3351 int tmp_port
= misdn_cfg_get_next_port(0);
3353 for (; tmp_port
> 0; tmp_port
=misdn_cfg_get_next_port(tmp_port
)) {
3354 if (tmp_port
== port
) break;
3355 chan_offset
+=misdn_lib_port_is_pri(tmp_port
)?30:2;
3361 ast_callerid_parse(callerid
, &cid_name
, &cid_num
);
3363 tmp
= ast_channel_alloc(1, state
, cid_num
, cid_name
, "", exten
, "", 0, "%s/%d-u%d", misdn_type
, chan_offset
+ c
, glob_channel
++);
3367 chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n",exten
,callerid
);
3369 tmp
->nativeformats
= prefformat
;
3371 tmp
->readformat
= format
;
3372 tmp
->rawreadformat
= format
;
3373 tmp
->writeformat
= format
;
3374 tmp
->rawwriteformat
= format
;
3376 tmp
->tech_pvt
= chlist
;
3378 misdn_cfg_get( 0, MISDN_GEN_BRIDGING
, &bridging
, sizeof(int));
3381 tmp
->tech
= &misdn_tech
;
3383 tmp
->tech
= &misdn_tech_wo_bridge
;
3385 tmp
->writeformat
= format
;
3386 tmp
->readformat
= format
;
3390 ast_copy_string(tmp
->exten
, exten
, sizeof(tmp
->exten
));
3392 chan_misdn_log(1,0,"misdn_new: no exten given.\n");
3395 /* Don't use ast_set_callerid() here because it will
3396 * generate a needless NewCallerID event */
3397 tmp
->cid
.cid_ani
= ast_strdup(cid_num
);
3400 if (pipe(chlist
->pipe
)<0)
3401 perror("Pipe failed\n");
3403 tmp
->fds
[0]=chlist
->pipe
[0];
3407 if (state
== AST_STATE_RING
)
3414 chan_misdn_log(-1,0,"Unable to allocate channel structure\n");
3420 static struct chan_list
*find_chan_by_bc(struct chan_list
*list
, struct misdn_bchannel
*bc
)
3422 struct chan_list
*help
=list
;
3423 for (;help
; help
=help
->next
) {
3424 if (help
->bc
== bc
) return help
;
3427 chan_misdn_log(6, bc
->port
, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc
->oad
,bc
->dad
);
3432 static struct chan_list
*find_chan_by_pid(struct chan_list
*list
, int pid
)
3434 struct chan_list
*help
=list
;
3435 for (;help
; help
=help
->next
) {
3436 if ( help
->bc
&& (help
->bc
->pid
== pid
) ) return help
;
3439 chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n",pid
);
3444 static struct chan_list
*find_holded(struct chan_list
*list
, struct misdn_bchannel
*bc
)
3446 struct chan_list
*help
=list
;
3448 if (bc
->pri
) return NULL
;
3450 chan_misdn_log(6, bc
->port
, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc
->channel
, bc
->oad
,bc
->dad
);
3451 for (;help
; help
=help
->next
) {
3452 chan_misdn_log(4, bc
->port
, "$$$ find_holded: --> holded:%d channel:%d\n",help
->state
==MISDN_HOLDED
, help
->hold_info
.channel
);
3453 if ( (help
->state
== MISDN_HOLDED
) &&
3454 (help
->hold_info
.port
== bc
->port
) )
3457 chan_misdn_log(6, bc
->port
, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc
->oad
,bc
->dad
);
3463 static struct chan_list
*find_holded_l3(struct chan_list
*list
, unsigned long l3_id
, int w
)
3466 struct chan_list
*help
=list
;
3468 for (;help
; help
=help
->next
) {
3469 if ( (help
->state
== MISDN_HOLDED
) &&
3470 (help
->l3id
== l3_id
)
3478 static void cl_queue_chan(struct chan_list
**list
, struct chan_list
*chan
)
3480 chan_misdn_log(4, chan
->bc
? chan
->bc
->port
: 0, "* Queuing chan %p\n",chan
);
3482 ast_mutex_lock(&cl_te_lock
);
3486 struct chan_list
*help
=*list
;
3487 for (;help
->next
; help
=help
->next
);
3491 ast_mutex_unlock(&cl_te_lock
);
3494 static void cl_dequeue_chan(struct chan_list
**list
, struct chan_list
*chan
)
3497 ast_dsp_free(chan
->dsp
);
3499 ast_translator_free_path(chan
->trans
);
3503 ast_mutex_lock(&cl_te_lock
);
3505 ast_mutex_unlock(&cl_te_lock
);
3509 if (*list
== chan
) {
3510 *list
=(*list
)->next
;
3511 ast_mutex_unlock(&cl_te_lock
);
3516 struct chan_list
*help
=*list
;
3517 for (;help
->next
; help
=help
->next
) {
3518 if (help
->next
== chan
) {
3519 help
->next
=help
->next
->next
;
3520 ast_mutex_unlock(&cl_te_lock
);
3526 ast_mutex_unlock(&cl_te_lock
);
3529 /** Channel Queue End **/
3532 static int pbx_start_chan(struct chan_list
*ch
)
3534 int ret
=ast_pbx_start(ch
->ast
);
3544 static void hangup_chan(struct chan_list
*ch
)
3546 int port
=ch
?ch
->bc
?ch
->bc
->port
:0:0;
3548 cb_log(1,0,"Cannot hangup chan, no ch\n");
3552 cb_log(5,port
,"hangup_chan called\n");
3554 if (ch
->need_hangup
)
3556 cb_log(2,port
," --> hangup\n");
3557 send_cause2ast(ch
->ast
,ch
->bc
,ch
);
3559 ch
->need_queue_hangup
=0;
3561 ast_hangup(ch
->ast
);
3565 if (!ch
->need_queue_hangup
) {
3566 cb_log(2,port
," --> No need to queue hangup\n");
3569 ch
->need_queue_hangup
=0;
3571 send_cause2ast(ch
->ast
,ch
->bc
,ch
);
3574 ast_queue_hangup(ch
->ast
);
3575 cb_log(2,port
," --> queue_hangup\n");
3577 cb_log(1,port
,"Cannot hangup chan, no ast\n");
3581 /** Isdn asks us to release channel, pendant to misdn_hangup **/
3582 static void release_chan(struct misdn_bchannel
*bc
) {
3583 struct ast_channel
*ast
=NULL
;
3585 ast_mutex_lock(&release_lock
);
3587 struct chan_list
*ch
=find_chan_by_bc(cl_te
, bc
);
3589 chan_misdn_log(1, bc
->port
, "release_chan: Ch not found!\n");
3590 ast_mutex_unlock(&release_lock
);
3598 chan_misdn_log(5, bc
->port
, "release_chan: bc with l3id: %x\n",bc
->l3_id
);
3600 /*releasing jitterbuffer*/
3602 misdn_jb_destroy(ch
->jb
);
3606 chan_misdn_log(5,bc
->port
,"Jitterbuffer already destroyed.\n");
3609 if (ch
->overlap_dial
) {
3610 if (ch
->overlap_dial_task
!= -1) {
3611 misdn_tasks_remove(ch
->overlap_dial_task
);
3612 ch
->overlap_dial_task
= -1;
3614 ast_mutex_destroy(&ch
->overlap_tv_lock
);
3617 if (ch
->originator
== ORG_AST
) {
3618 misdn_out_calls
[bc
->port
]--;
3620 misdn_in_calls
[bc
->port
]--;
3629 if (ast
&& MISDN_ASTERISK_TECH_PVT(ast
)) {
3630 chan_misdn_log(1, bc
->port
, "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s state: %s\n",bc
?bc
->pid
:-1, ast
->context
, ast
->exten
,ast
->cid
.cid_num
,misdn_get_ch_state(ch
));
3631 chan_misdn_log(3, bc
->port
, " --> * State Down\n");
3632 MISDN_ASTERISK_TECH_PVT(ast
)=NULL
;
3635 if (ast
->_state
!= AST_STATE_RESERVED
) {
3636 chan_misdn_log(3, bc
->port
, " --> Setting AST State to down\n");
3637 ast_setstate(ast
, AST_STATE_DOWN
);
3641 ch
->state
=MISDN_CLEANING
;
3642 cl_dequeue_chan(&cl_te
, ch
);
3646 /* chan is already cleaned, so exiting */
3650 ast_mutex_unlock(&release_lock
);
3652 /*** release end **/
3654 static void misdn_transfer_bc(struct chan_list
*tmp_ch
, struct chan_list
*holded_chan
)
3656 chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan
->ast
->name
, tmp_ch
->ast
->name
);
3658 tmp_ch
->state
=MISDN_HOLD_DISCONNECT
;
3660 ast_moh_stop(ast_bridged_channel(holded_chan
->ast
));
3662 holded_chan
->state
=MISDN_CONNECTED
;
3663 //misdn_lib_transfer(holded_chan->bc);
3664 ast_channel_masquerade(holded_chan
->ast
, ast_bridged_channel(tmp_ch
->ast
));
3668 static void do_immediate_setup(struct misdn_bchannel
*bc
,struct chan_list
*ch
, struct ast_channel
*ast
)
3670 char predial
[256]="";
3673 struct ast_frame fr
;
3675 strncpy(predial
, ast
->exten
, sizeof(predial
) -1 );
3677 ch
->state
=MISDN_DIALING
;
3679 if (!ch
->noautorespond_on_setup
) {
3682 ret
= misdn_lib_send_event(bc
, EVENT_SETUP_ACKNOWLEDGE
);
3685 if ( misdn_lib_is_ptp(bc
->port
)) {
3686 ret
= misdn_lib_send_event(bc
, EVENT_SETUP_ACKNOWLEDGE
);
3688 ret
= misdn_lib_send_event(bc
, EVENT_PROCEEDING
);
3692 ch
->state
= MISDN_INCOMING_SETUP
;
3695 chan_misdn_log(1, bc
->port
, "* Starting Ast ctx:%s dad:%s oad:%s with 's' extension\n", ast
->context
, ast
->exten
, ast
->cid
.cid_num
);
3697 strncpy(ast
->exten
,"s", 2);
3699 if (pbx_start_chan(ch
)<0) {
3702 hanguptone_indicate(ch
);
3705 misdn_lib_send_event(bc
, EVENT_RELEASE_COMPLETE
);
3707 misdn_lib_send_event(bc
, EVENT_DISCONNECT
);
3711 while (!ast_strlen_zero(p
) ) {
3712 fr
.frametype
= AST_FRAME_DTMF
;
3720 fr
.delivery
= ast_tv(0,0) ;
3722 if (ch
->ast
&& MISDN_ASTERISK_PVT(ch
->ast
) && MISDN_ASTERISK_TECH_PVT(ch
->ast
)) {
3723 ast_queue_frame(ch
->ast
, &fr
);
3731 static void send_cause2ast(struct ast_channel
*ast
, struct misdn_bchannel
*bc
, struct chan_list
*ch
) {
3733 chan_misdn_log(1,0,"send_cause2ast: No Ast\n");
3737 chan_misdn_log(1,0,"send_cause2ast: No BC\n");
3741 chan_misdn_log(1,0,"send_cause2ast: No Ch\n");
3745 ast
->hangupcause
=bc
->cause
;
3747 switch ( bc
->cause
) {
3749 case 1: /** Congestion Cases **/
3756 * Not Queueing the Congestion anymore, since we want to hear
3757 * the inband message
3759 chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Congestion pid:%d\n", bc?bc->pid:-1);
3760 ch->state=MISDN_BUSY;
3762 ast_queue_control(ast, AST_CONTROL_CONGESTION);
3767 case 17: /* user busy */
3769 ch
->state
=MISDN_BUSY
;
3771 if (!ch
->need_busy
) {
3772 chan_misdn_log(1,bc
?bc
->port
:0, "Queued busy already\n");
3776 chan_misdn_log(1, bc
?bc
->port
:0, " --> * SEND: Queue Busy pid:%d\n", bc
?bc
->pid
:-1);
3778 ast_queue_control(ast
, AST_CONTROL_BUSY
);
3789 void import_ch(struct ast_channel
*chan
, struct misdn_bchannel
*bc
, struct chan_list
*ch
)
3792 tmp
=pbx_builtin_getvar_helper(chan
,"MISDN_PID");
3794 ch
->other_pid
=atoi(tmp
);
3795 chan_misdn_log(3,bc
->port
," --> IMPORT_PID: importing pid:%s\n",tmp
);
3796 if (ch
->other_pid
>0) {
3797 ch
->other_ch
=find_chan_by_pid(cl_te
,ch
->other_pid
);
3798 if (ch
->other_ch
) ch
->other_ch
->other_ch
=ch
;
3802 tmp
=pbx_builtin_getvar_helper(chan
,"MISDN_ADDRESS_COMPLETE");
3803 if (tmp
&& (atoi(tmp
) == 1)) {
3804 bc
->sending_complete
=1;
3807 tmp
=pbx_builtin_getvar_helper(chan
,"MISDN_USERUSER");
3809 ast_log(LOG_NOTICE
, "MISDN_USERUSER: %s\n", tmp
);
3810 strcpy(bc
->uu
, tmp
);
3811 bc
->uulen
=strlen(bc
->uu
);
3814 tmp
=pbx_builtin_getvar_helper(chan
,"MISDN_KEYPAD");
3816 strncpy(bc
->keypad
,tmp
,sizeof(bc
->keypad
));
3817 bc
->keypad
[sizeof(bc
->keypad
)-1]=0;
3823 void export_ch(struct ast_channel
*chan
, struct misdn_bchannel
*bc
, struct chan_list
*ch
)
3826 chan_misdn_log(3,bc
->port
," --> EXPORT_PID: pid:%d\n",bc
->pid
);
3827 sprintf(tmp
,"%d",bc
->pid
);
3828 pbx_builtin_setvar_helper(chan
,"_MISDN_PID",tmp
);
3830 if (bc
->sending_complete
) {
3831 sprintf(tmp
,"%d",bc
->sending_complete
);
3832 pbx_builtin_setvar_helper(chan
,"MISDN_ADDRESS_COMPLETE",tmp
);
3836 sprintf(tmp
,"%d",bc
->urate
);
3837 pbx_builtin_setvar_helper(chan
,"MISDN_URATE",tmp
);
3840 if (bc
->uulen
&& (bc
->uulen
< sizeof(bc
->uu
))) {
3841 bc
->uu
[bc
->uulen
]=0;
3842 pbx_builtin_setvar_helper(chan
,"MISDN_USERUSER",bc
->uu
);
3846 pbx_builtin_setvar_helper(chan
,"MISDN_KEYPAD",bc
->keypad
);
3849 int add_in_calls(int port
)
3853 misdn_cfg_get( port
, MISDN_CFG_MAX_IN
, &max_in_calls
, sizeof(max_in_calls
));
3854 misdn_in_calls
[port
]++;
3856 if (max_in_calls
>=0 && max_in_calls
<misdn_in_calls
[port
]) {
3857 ast_log(LOG_NOTICE
,"Marking Incoming Call on port[%d]\n",port
);
3858 return misdn_in_calls
[port
]-max_in_calls
;
3864 int add_out_calls(int port
)
3868 misdn_cfg_get( port
, MISDN_CFG_MAX_OUT
, &max_out_calls
, sizeof(max_out_calls
));
3871 if (max_out_calls
>=0 && max_out_calls
<=misdn_out_calls
[port
]) {
3872 ast_log(LOG_NOTICE
,"Rejecting Outgoing Call on port[%d]\n",port
);
3873 return (misdn_out_calls
[port
]+1)-max_out_calls
;
3876 misdn_out_calls
[port
]++;
3881 static void start_pbx(struct chan_list
*ch
, struct misdn_bchannel
*bc
, struct ast_channel
*chan
) {
3882 if (pbx_start_chan(ch
)<0) {
3884 chan_misdn_log(-1, bc
->port
, "ast_pbx_start returned <0 in SETUP\n");
3886 hanguptone_indicate(ch
);
3887 misdn_lib_send_event(bc
, EVENT_RELEASE_COMPLETE
);
3889 misdn_lib_send_event(bc
, EVENT_RELEASE
);
3893 static void wait_for_digits(struct chan_list
*ch
, struct misdn_bchannel
*bc
, struct ast_channel
*chan
) {
3894 ch
->state
=MISDN_WAITING4DIGS
;
3895 misdn_lib_send_event(bc
, EVENT_SETUP_ACKNOWLEDGE
);
3896 if (bc
->nt
&& !bc
->dad
[0])
3897 dialtone_indicate(ch
);
3901 /************************************************************/
3902 /* Receive Events from isdn_lib here */
3903 /************************************************************/
3904 static enum event_response_e
3905 cb_events(enum event_e event
, struct misdn_bchannel
*bc
, void *user_data
)
3908 struct chan_list
*ch
=find_chan_by_bc(cl_te
, bc
);
3910 if (event
!= EVENT_BCHAN_DATA
&& event
!= EVENT_TONE_GENERATE
) { /* Debug Only Non-Bchan */
3912 if ( event
==EVENT_CLEANUP
&& !user_data
)
3915 chan_misdn_log(debuglevel
, bc
->port
, "I IND :%s oad:%s dad:%s pid:%d state:%s\n", manager_isdn_get_info(event
), bc
->oad
, bc
->dad
, bc
->pid
, ch
?misdn_get_ch_state(ch
):"none");
3916 if (debuglevel
==1) {
3917 misdn_lib_log_ies(bc
);
3918 chan_misdn_log(4,bc
->port
," --> bc_state:%s\n",bc_state2str(bc
->bc_state
));
3925 case EVENT_DISCONNECT
:
3926 case EVENT_PORT_ALARM
:
3927 case EVENT_RETRIEVE
:
3929 case EVENT_FACILITY
:
3931 case EVENT_RELEASE_COMPLETE
:
3932 chan_misdn_log(1, bc
->port
, " --> no Ch, so we've already released.\n");
3935 case EVENT_TONE_GENERATE
:
3936 case EVENT_BCHAN_DATA
:
3940 chan_misdn_log(1,bc
->port
, "Chan not existing at the moment bc->l3id:%x bc:%p event:%s port:%d channel:%d\n",bc
->l3_id
, bc
, manager_isdn_get_info( event
), bc
->port
,bc
->channel
);
3947 case EVENT_TONE_GENERATE
:
3949 case EVENT_DISCONNECT
:
3951 case EVENT_RELEASE_COMPLETE
:
3955 chan_misdn_log(3,bc
->port
,"ast_hangup already called, so we have no ast ptr anymore in event(%s)\n",manager_isdn_get_info(event
));
3958 if ( !ch
->ast
|| !MISDN_ASTERISK_PVT(ch
->ast
) || !MISDN_ASTERISK_TECH_PVT(ch
->ast
)) {
3959 if (event
!=EVENT_BCHAN_DATA
)
3960 ast_log(LOG_NOTICE
, "No Ast or No private Pointer in Event (%d:%s)\n", event
, manager_isdn_get_info(event
));
3968 case EVENT_PORT_ALARM
:
3971 misdn_cfg_get( bc
->port
, MISDN_CFG_ALARM_BLOCK
, &boa
, sizeof(int));
3973 cb_log(1,bc
->port
," --> blocking\n");
3974 misdn_lib_port_block(bc
->port
);
3978 case EVENT_BCHAN_ACTIVATED
:
3981 case EVENT_NEW_CHANNEL
:
3982 update_name(ch
->ast
,bc
->port
,bc
->channel
);
3985 case EVENT_NEW_L3ID
:
3992 ch
=find_holded(cl_te
,bc
);
3996 ast_log(LOG_WARNING
,"NEW_BC without chan_list?\n");
4001 ch
->bc
=(struct misdn_bchannel
*)user_data
;
4004 case EVENT_DTMF_TONE
:
4006 /* sending INFOS as DTMF-Frames :) */
4007 struct ast_frame fr
;
4008 memset(&fr
, 0 , sizeof(fr
));
4009 fr
.frametype
= AST_FRAME_DTMF
;
4010 fr
.subclass
= bc
->dtmf
;
4017 fr
.delivery
= ast_tv(0,0) ;
4019 if (!ch
->ignore_dtmf
) {
4020 chan_misdn_log(2, bc
->port
, " --> DTMF:%c\n", bc
->dtmf
);
4021 ast_queue_frame(ch
->ast
, &fr
);
4023 chan_misdn_log(2, bc
->port
, " --> Ignoring DTMF:%c due to bridge flags\n", bc
->dtmf
);
4030 case EVENT_INFORMATION
:
4034 if ( ch
->state
!= MISDN_CONNECTED
)
4037 if (!ch
->ast
) break;
4039 if (ch
->state
== MISDN_WAITING4DIGS
) {
4040 /* Ok, incomplete Setup, waiting till extension exists */
4041 if (ast_strlen_zero(bc
->info_dad
) && ! ast_strlen_zero(bc
->keypad
)) {
4042 chan_misdn_log(1, bc
->port
, " --> using keypad as info\n");
4043 strcpy(bc
->info_dad
,bc
->keypad
);
4046 l
= sizeof(bc
->dad
);
4047 strncat(bc
->dad
,bc
->info_dad
, l
- strlen(bc
->dad
) - 1);
4049 l
= sizeof(ch
->ast
->exten
);
4050 strncpy(ch
->ast
->exten
, bc
->dad
, l
);
4051 ch
->ast
->exten
[l
-1] = 0;
4053 /* Check for Pickup Request first */
4054 if (!strcmp(ch
->ast
->exten
, ast_pickup_ext())) {
4055 if (ast_pickup_call(ch
->ast
)) {
4058 struct ast_channel
*chan
=ch
->ast
;
4059 ch
->state
= MISDN_CALLING_ACKNOWLEDGE
;
4060 ast_setstate(chan
, AST_STATE_DOWN
);
4067 if(!ast_canmatch_extension(ch
->ast
, ch
->context
, bc
->dad
, 1, bc
->oad
)) {
4068 if (ast_exists_extension(ch
->ast
, ch
->context
, "i", 1, bc
->oad
)) {
4069 ast_log(LOG_WARNING
, "Extension can never match, So jumping to 'i' extension. port(%d)\n",bc
->port
);
4070 strcpy(ch
->ast
->exten
, "i");
4072 ch
->state
= MISDN_DIALING
;
4073 start_pbx(ch
, bc
, ch
->ast
);
4077 ast_log(LOG_WARNING
, "Extension can never match, so disconnecting on port(%d)."
4078 "maybe you want to add an 'i' extension to catch this case.\n",
4082 hanguptone_indicate(ch
);
4083 ch
->state
=MISDN_EXTCANTMATCH
;
4086 misdn_lib_send_event(bc
, EVENT_DISCONNECT
);
4090 if (ch
->overlap_dial
) {
4091 ast_mutex_lock(&ch
->overlap_tv_lock
);
4092 ch
->overlap_tv
= ast_tvnow();
4093 ast_mutex_unlock(&ch
->overlap_tv_lock
);
4094 if (ch
->overlap_dial_task
== -1) {
4095 ch
->overlap_dial_task
=
4096 misdn_tasks_add_variable(ch
->overlap_dial
, misdn_overlap_dial_task
, ch
);
4101 if (ast_exists_extension(ch
->ast
, ch
->context
, bc
->dad
, 1, bc
->oad
)) {
4103 ch
->state
= MISDN_DIALING
;
4104 start_pbx(ch
, bc
, ch
->ast
);
4107 /* sending INFOS as DTMF-Frames :) */
4109 struct ast_frame fr
;
4110 memset(&fr
, 0, sizeof(fr
));
4111 fr
.frametype
= AST_FRAME_DTMF
;
4112 fr
.subclass
= bc
->info_dad
[0] ;
4119 fr
.delivery
= ast_tv(0,0) ;
4121 misdn_cfg_get( 0, MISDN_GEN_APPEND_DIGITS2EXTEN
, &digits
, sizeof(int));
4122 if (ch
->state
!= MISDN_CONNECTED
) {
4124 int l
= sizeof(bc
->dad
);
4125 strncat(bc
->dad
, bc
->info_dad
, l
- strlen(bc
->dad
) - 1);
4126 l
= sizeof(ch
->ast
->exten
);
4127 strncpy(ch
->ast
->exten
, bc
->dad
, l
);
4128 ch
->ast
->exten
[l
-1] = 0;
4130 ast_cdr_update(ch
->ast
);
4133 ast_queue_frame(ch
->ast
, &fr
);
4140 struct chan_list
*ch
=find_chan_by_bc(cl_te
, bc
);
4142 switch (ch
->state
) {
4147 chan_misdn_log(1, bc
->port
, " --> Ignoring Call we have already one\n");
4148 return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE
; /* Ignore MSNs which are not in our List */
4153 msn_valid
= misdn_cfg_is_msn_valid(bc
->port
, bc
->dad
);
4154 if (!bc
->nt
&& ! msn_valid
) {
4155 chan_misdn_log(1, bc
->port
, " --> Ignoring Call, its not in our MSN List\n");
4156 return RESPONSE_IGNORE_SETUP
; /* Ignore MSNs which are not in our List */
4162 chan_misdn_log(0, bc
->port
, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
4163 misdn_cfg_get( bc
->port
, MISDN_CFG_REJECT_CAUSE
, &cause
, sizeof(cause
));
4164 bc
->out_cause
=cause
?cause
:16;
4165 return RESPONSE_RELEASE_SETUP
;
4171 struct chan_list
*ch
;
4172 struct ast_channel
*chan
;
4175 int msn_valid
= misdn_cfg_is_msn_valid(bc
->port
, bc
->dad
);
4177 if (!bc
->nt
&& ! msn_valid
) {
4178 chan_misdn_log(1, bc
->port
, " --> Ignoring Call, its not in our MSN List\n");
4179 return RESPONSE_IGNORE_SETUP
; /* Ignore MSNs which are not in our List */
4184 chan_misdn_log(0, bc
->port
, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
4185 misdn_cfg_get( bc
->port
, MISDN_CFG_REJECT_CAUSE
, &cause
, sizeof(cause
));
4186 bc
->out_cause
=cause
?cause
:16;
4187 return RESPONSE_RELEASE_SETUP
;
4192 ch
=init_chan_list(ORG_MISDN
);
4194 if (!ch
) { chan_misdn_log(-1, bc
->port
, "cb_events: malloc for chan_list failed!\n"); return 0;}
4199 ch
->originator
= ORG_MISDN
;
4201 chan
=misdn_new(ch
, AST_STATE_RESERVED
,bc
->dad
, bc
->oad
, AST_FORMAT_ALAW
, bc
->port
, bc
->channel
);
4204 misdn_lib_send_event(bc
,EVENT_RELEASE_COMPLETE
);
4205 ast_log(LOG_ERROR
, "cb_events: misdn_new failed !\n");
4211 if ((exceed
=add_in_calls(bc
->port
))) {
4213 sprintf(tmp
,"%d",exceed
);
4214 pbx_builtin_setvar_helper(chan
,"MAX_OVERFLOW",tmp
);
4217 read_config(ch
, ORG_MISDN
);
4219 export_ch(chan
, bc
, ch
);
4222 ast_setstate(ch
->ast
, AST_STATE_RINGING
);
4226 pres
=AST_PRES_RESTRICTED
; chan_misdn_log(2,bc
->port
," --> PRES: Restricted (1)\n");
4229 pres
=AST_PRES_UNAVAILABLE
; chan_misdn_log(2,bc
->port
," --> PRES: Restricted (2)\n");
4232 pres
=AST_PRES_ALLOWED
; chan_misdn_log(2,bc
->port
," --> PRES: Restricted (%d)\n", bc
->pres
);
4235 switch (bc
->screen
) {
4237 screen
=AST_PRES_USER_NUMBER_UNSCREENED
; chan_misdn_log(2,bc
->port
," --> SCREEN: Unscreened (0)\n");
4240 screen
=AST_PRES_USER_NUMBER_PASSED_SCREEN
; chan_misdn_log(2,bc
->port
," --> SCREEN: Passed screen (1)\n");
4243 screen
=AST_PRES_USER_NUMBER_FAILED_SCREEN
; chan_misdn_log(2,bc
->port
," --> SCREEN: failed screen (2)\n");
4246 screen
=AST_PRES_NETWORK_NUMBER
; chan_misdn_log(2,bc
->port
," --> SCREEN: Network Number (3)\n");
4249 screen
=AST_PRES_USER_NUMBER_UNSCREENED
; chan_misdn_log(2,bc
->port
," --> SCREEN: Unscreened (%d)\n",bc
->screen
);
4252 chan
->cid
.cid_pres
=pres
+screen
;
4254 pbx_builtin_setvar_helper(chan
, "TRANSFERCAPABILITY", ast_transfercapability2str(bc
->capability
));
4255 chan
->transfercapability
=bc
->capability
;
4257 switch (bc
->capability
) {
4258 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED
:
4259 pbx_builtin_setvar_helper(chan
,"CALLTYPE","DIGITAL");
4262 pbx_builtin_setvar_helper(chan
,"CALLTYPE","SPEECH");
4265 /** queue new chan **/
4266 cl_queue_chan(&cl_te
, ch
) ;
4268 if (!strstr(ch
->allowed_bearers
,"all")) {
4271 for (i
= 0; i
< ARRAY_LEN(allowed_bearers_array
); ++i
) {
4272 if (allowed_bearers_array
[i
].cap
== bc
->capability
) {
4273 if (strstr(ch
->allowed_bearers
, allowed_bearers_array
[i
].name
)) {
4274 /* The bearer capability is allowed */
4275 if (allowed_bearers_array
[i
].deprecated
) {
4276 chan_misdn_log(0, bc
->port
, "%s in allowed_bearers list is deprecated\n",
4277 allowed_bearers_array
[i
].name
);
4283 if (i
== ARRAY_LEN(allowed_bearers_array
)) {
4284 /* We did not find the bearer capability */
4285 chan_misdn_log(0, bc
->port
, "Bearer capability not allowed: %s(%d)\n",
4286 bearer2str(bc
->capability
), bc
->capability
);
4289 ch
->state
= MISDN_EXTCANTMATCH
;
4290 misdn_lib_send_event(bc
, EVENT_RELEASE_COMPLETE
);
4295 /* Check for Pickup Request first */
4296 if (!strcmp(chan
->exten
, ast_pickup_ext())) {
4297 if (!ch
->noautorespond_on_setup
) {
4298 int ret
;/** Sending SETUP_ACK**/
4299 ret
= misdn_lib_send_event(bc
, EVENT_SETUP_ACKNOWLEDGE
);
4301 ch
->state
= MISDN_INCOMING_SETUP
;
4303 if (ast_pickup_call(chan
)) {
4306 ch
->state
= MISDN_CALLING_ACKNOWLEDGE
;
4307 ast_setstate(chan
, AST_STATE_DOWN
);
4315 added support for s extension hope it will help those poor cretains
4316 which haven't overlap dial.
4318 misdn_cfg_get( bc
->port
, MISDN_CFG_ALWAYS_IMMEDIATE
, &ai
, sizeof(ai
));
4320 do_immediate_setup(bc
, ch
, chan
);
4324 /* check if we should jump into s when we have no dad */
4325 misdn_cfg_get( bc
->port
, MISDN_CFG_IMMEDIATE
, &im
, sizeof(im
));
4326 if ( im
&& ast_strlen_zero(bc
->dad
) ) {
4327 do_immediate_setup(bc
, ch
, chan
);
4331 chan_misdn_log(5,bc
->port
,"CONTEXT:%s\n",ch
->context
);
4332 if(!ast_canmatch_extension(ch
->ast
, ch
->context
, bc
->dad
, 1, bc
->oad
)) {
4333 if (ast_exists_extension(ch
->ast
, ch
->context
, "i", 1, bc
->oad
)) {
4334 ast_log(LOG_WARNING
, "Extension can never match, So jumping to 'i' extension. port(%d)\n",bc
->port
);
4335 strcpy(ch
->ast
->exten
, "i");
4336 misdn_lib_send_event(bc
, EVENT_SETUP_ACKNOWLEDGE
);
4337 ch
->state
=MISDN_DIALING
;
4338 start_pbx(ch
, bc
, chan
);
4342 ast_log(LOG_WARNING
, "Extension can never match, so disconnecting on port(%d)."
4343 "maybe you want to add an 'i' extension to catch this case.\n",
4346 hanguptone_indicate(ch
);
4348 ch
->state
=MISDN_EXTCANTMATCH
;
4352 misdn_lib_send_event(bc
, EVENT_RELEASE_COMPLETE
);
4354 misdn_lib_send_event(bc
, EVENT_RELEASE
);
4359 /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely
4360 * jump into the dialplan, when the dialed extension does not exist, the 's' extension
4361 * will be used by Asterisk automatically. */
4362 if (bc
->sending_complete
|| (!bc
->nt
&& !misdn_lib_is_ptp(bc
->port
))) {
4363 if (!ch
->noautorespond_on_setup
) {
4364 ch
->state
=MISDN_DIALING
;
4365 misdn_lib_send_event(bc
, EVENT_PROCEEDING
);
4367 ch
->state
= MISDN_INCOMING_SETUP
;
4369 start_pbx(ch
, bc
, chan
);
4375 * When we are NT and overlapdial is set and if
4376 * the number is empty, we wait for the ISDN timeout
4377 * instead of our own timer.
4379 if (ch
->overlap_dial
&& bc
->nt
&& !bc
->dad
[0] ) {
4380 wait_for_digits(ch
, bc
, chan
);
4385 * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more
4386 * Infos with a Interdigit Timeout.
4388 if (ch
->overlap_dial
) {
4389 ast_mutex_lock(&ch
->overlap_tv_lock
);
4390 ch
->overlap_tv
= ast_tvnow();
4391 ast_mutex_unlock(&ch
->overlap_tv_lock
);
4393 wait_for_digits(ch
, bc
, chan
);
4394 if (ch
->overlap_dial_task
== -1)
4395 ch
->overlap_dial_task
=
4396 misdn_tasks_add_variable(ch
->overlap_dial
, misdn_overlap_dial_task
, ch
);
4401 /* If the extension does not exist and we're not TE_PTMP we wait for more digits
4402 * without interdigit timeout.
4404 if (!ast_exists_extension(ch
->ast
, ch
->context
, bc
->dad
, 1, bc
->oad
)) {
4405 wait_for_digits(ch
, bc
, chan
);
4410 * If the extension exists let's just jump into it.
4412 if (ast_exists_extension(ch
->ast
, ch
->context
, bc
->dad
, 1, bc
->oad
)) {
4413 if (bc
->need_more_infos
)
4414 misdn_lib_send_event(bc
, EVENT_SETUP_ACKNOWLEDGE
);
4416 misdn_lib_send_event(bc
, EVENT_PROCEEDING
);
4418 ch
->state
=MISDN_DIALING
;
4419 start_pbx(ch
, bc
, chan
);
4425 case EVENT_SETUP_ACKNOWLEDGE
:
4427 ch
->state
= MISDN_CALLING_ACKNOWLEDGE
;
4430 update_name(ch
->ast
,bc
->port
,bc
->channel
);
4432 if (!ast_strlen_zero(bc
->infos_pending
)) {
4433 /* TX Pending Infos */
4436 int l
= sizeof(bc
->dad
);
4437 strncat(bc
->dad
, bc
->infos_pending
, l
- strlen(bc
->dad
) - 1);
4440 if (!ch
->ast
) break;
4442 int l
= sizeof(ch
->ast
->exten
);
4443 strncpy(ch
->ast
->exten
, bc
->dad
, l
);
4444 ch
->ast
->exten
[l
-1] = 0;
4447 int l
= sizeof(bc
->info_dad
);
4448 strncpy(bc
->info_dad
, bc
->infos_pending
, l
);
4449 bc
->info_dad
[l
-1] = 0;
4451 strncpy(bc
->infos_pending
,"", 1);
4453 misdn_lib_send_event(bc
, EVENT_INFORMATION
);
4457 case EVENT_PROCEEDING
:
4460 update_name(ch
->ast
,bc
->port
,bc
->channel
);
4462 if ( misdn_cap_is_speech(bc
->capability
) &&
4463 misdn_inband_avail(bc
) ) {
4467 ch
->state
= MISDN_PROCEEDING
;
4469 if (!ch
->ast
) break;
4471 ast_queue_control(ch
->ast
, AST_CONTROL_PROCEEDING
);
4474 case EVENT_PROGRESS
:
4476 update_name(ch
->ast
,bc
->port
,bc
->channel
);
4479 if ( misdn_cap_is_speech(bc
->capability
) &&
4480 misdn_inband_avail(bc
)
4485 ch
->state
=MISDN_PROGRESS
;
4487 if (!ch
->ast
) break;
4488 ast_queue_control(ch
->ast
, AST_CONTROL_PROGRESS
);
4493 case EVENT_ALERTING
:
4496 update_name(ch
->ast
,bc
->port
,bc
->channel
);
4498 ch
->state
= MISDN_ALERTING
;
4500 if (!ch
->ast
) break;
4502 ast_queue_control(ch
->ast
, AST_CONTROL_RINGING
);
4503 ast_setstate(ch
->ast
, AST_STATE_RINGING
);
4505 cb_log(7,bc
->port
," --> Set State Ringing\n");
4507 if ( misdn_cap_is_speech(bc
->capability
) && misdn_inband_avail(bc
)) {
4508 cb_log(1,bc
->port
,"Starting Tones, we have inband Data\n");
4511 cb_log(3,bc
->port
," --> We have no inband Data, the other end must create ringing\n");
4512 if (ch
->far_alerting
) {
4513 cb_log(1,bc
->port
," --> The other end can not do ringing eh ?.. we must do all ourself..");
4515 /*tone_indicate(ch, TONE_FAR_ALERTING);*/
4522 struct ast_channel
*bridged
;
4523 /*we answer when we've got our very new L3 ID from the NT stack */
4524 misdn_lib_send_event(bc
,EVENT_CONNECT_ACKNOWLEDGE
);
4526 if (!ch
->ast
) break;
4528 bridged
=ast_bridged_channel(ch
->ast
);
4531 if (bridged
&& !strcasecmp(bridged
->tech
->type
,"mISDN")) {
4532 struct chan_list
*bridged_ch
=MISDN_ASTERISK_TECH_PVT(bridged
);
4534 chan_misdn_log(1,bc
->port
," --> copying cpndialplan:%d and cad:%s to the A-Channel\n",bc
->cpnnumplan
,bc
->cad
);
4536 bridged_ch
->bc
->cpnnumplan
=bc
->cpnnumplan
;
4537 ast_copy_string(bridged_ch
->bc
->cad
,bc
->cad
,sizeof(bc
->cad
));
4546 ch
->state
= MISDN_CONNECTED
;
4548 ast_queue_control(ch
->ast
, AST_CONTROL_ANSWER
);
4550 case EVENT_CONNECT_ACKNOWLEDGE
:
4557 ch
->state
= MISDN_CONNECTED
;
4560 case EVENT_DISCONNECT
:
4561 /*we might not have an ch->ast ptr here anymore*/
4563 struct chan_list
*holded_ch
=find_holded(cl_te
, bc
);
4565 chan_misdn_log(3,bc
->port
," --> org:%d nt:%d, inbandavail:%d state:%d\n", ch
->originator
, bc
->nt
, misdn_inband_avail(bc
), ch
->state
);
4566 if ( ch
->originator
==ORG_AST
&& !bc
->nt
&& misdn_inband_avail(bc
) && ch
->state
!= MISDN_CONNECTED
) {
4567 /* If there's inband information available (e.g. a
4568 recorded message saying what was wrong with the
4569 dialled number, or perhaps even giving an
4570 alternative number, then play it instead of
4571 immediately releasing the call */
4572 chan_misdn_log(1,bc
->port
, " --> Inband Info Avail, not sending RELEASE\n");
4574 ch
->state
=MISDN_DISCONNECTED
;
4578 ch
->ast
->hangupcause
=bc
->cause
;
4579 if (bc
->cause
== 17)
4580 ast_queue_control(ch
->ast
, AST_CONTROL_BUSY
);
4586 /*Check for holded channel, to implement transfer*/
4590 ch
->state
== MISDN_CONNECTED
) {
4591 cb_log(1,bc
->port
," --> found holded ch\n");
4592 misdn_transfer_bc(ch
, holded_ch
) ;
4595 bc
->need_disconnect
=0;
4600 /* ch=find_holded_l3(cl_te, bc->l3_id,1);
4607 if (bc
->need_release
) misdn_lib_send_event(bc
,EVENT_RELEASE
);
4612 bc
->need_disconnect
=0;
4619 case EVENT_RELEASE_COMPLETE
:
4621 bc
->need_disconnect
=0;
4623 bc
->need_release_complete
=0;
4629 ch
->state
=MISDN_CLEANING
;
4634 case EVENT_BCHAN_ERROR
:
4641 bc
->cause
=27; /* Destination out of order */
4652 case EVENT_TONE_GENERATE
:
4654 int tone_len
=bc
->tone_cnt
;
4655 struct ast_channel
*ast
=ch
->ast
;
4658 int (*generate
)(struct ast_channel
*chan
, void *tmp
, int datalen
, int samples
);
4660 chan_misdn_log(9,bc
->port
,"TONE_GEN: len:%d\n");
4664 if (!ast
->generator
) break;
4668 tmp
= ast
->generatordata
;
4669 ast
->generatordata
= NULL
;
4670 generate
= ast
->generator
->generate
;
4672 if (tone_len
<0 || tone_len
> 512 ) {
4673 ast_log(LOG_NOTICE
, "TONE_GEN: len was %d, set to 128\n",tone_len
);
4677 res
= generate(ast
, tmp
, tone_len
, tone_len
);
4678 ast
->generatordata
= tmp
;
4681 ast_log(LOG_WARNING
, "Auto-deactivating generator\n");
4682 ast_deactivate_generator(ast
);
4689 case EVENT_BCHAN_DATA
:
4691 if ( !misdn_cap_is_speech(ch
->bc
->capability
) ) {
4692 struct ast_frame frame
;
4693 /*In Data Modes we queue frames*/
4694 frame
.frametype
= AST_FRAME_VOICE
; /*we have no data frames yet*/
4695 frame
.subclass
= AST_FORMAT_ALAW
;
4696 frame
.datalen
= bc
->bframe_len
;
4697 frame
.samples
= bc
->bframe_len
;
4700 frame
.delivery
= ast_tv(0,0) ;
4702 frame
.data
= bc
->bframe
;
4705 ast_queue_frame(ch
->ast
,&frame
);
4715 FD_SET(ch
->pipe
[1],&wrfs
);
4717 t
=select(FD_SETSIZE
,NULL
,&wrfs
,NULL
,&tv
);
4720 chan_misdn_log(9, bc
->port
, "Select Timed out\n");
4725 chan_misdn_log(-1, bc
->port
, "Select Error (err=%s)\n",strerror(errno
));
4729 if (FD_ISSET(ch
->pipe
[1],&wrfs
)) {
4731 chan_misdn_log(9, bc
->port
, "writing %d bytes 2 asterisk\n",bc
->bframe_len
);
4732 ret
=write(ch
->pipe
[1], bc
->bframe
, bc
->bframe_len
);
4735 chan_misdn_log(0, bc
->port
, "Write returned <=0 (err=%s) --> hanging up channel\n",strerror(errno
));
4742 chan_misdn_log(1, bc
->port
, "Write Pipe full!\n");
4750 chan_misdn_log(1,bc
->port
,"--> state: %s\n",misdn_get_ch_state(ch
));
4752 switch (ch
->state
) {
4754 case MISDN_PROGRESS
:
4755 if (bc
->nt
&& !ch
->nttimeout
) break;
4758 case MISDN_ALERTING
:
4759 case MISDN_PROCEEDING
:
4760 case MISDN_CALLING_ACKNOWLEDGE
:
4762 bc
->progress_indicator
=8;
4763 hanguptone_indicate(ch
);
4767 misdn_lib_send_event(bc
,EVENT_DISCONNECT
);
4770 case MISDN_WAITING4DIGS
:
4772 bc
->progress_indicator
=8;
4774 hanguptone_indicate(ch
);
4775 misdn_lib_send_event(bc
,EVENT_DISCONNECT
);
4778 misdn_lib_send_event(bc
,EVENT_RELEASE
);
4784 case MISDN_CLEANING
:
4785 chan_misdn_log(1,bc
->port
," --> in state cleaning .. so ignoring, the stack should clean it for us\n");
4789 misdn_lib_send_event(bc
,EVENT_RELEASE_COMPLETE
);
4795 /****************************/
4796 /** Supplementary Services **/
4797 /****************************/
4798 case EVENT_RETRIEVE
:
4800 struct ast_channel
*hold_ast
;
4802 chan_misdn_log(4, bc
->port
, " --> no CH, searching in holded\n");
4803 ch
=find_holded_l3(cl_te
, bc
->l3_id
,1);
4807 ast_log(LOG_WARNING
, "Found no Holded channel, cannot Retrieve\n");
4808 misdn_lib_send_event(bc
, EVENT_RETRIEVE_REJECT
);
4812 /*remember the channel again*/
4814 ch
->state
= MISDN_CONNECTED
;
4816 ch
->hold_info
.port
=0;
4817 ch
->hold_info
.channel
=0;
4819 hold_ast
=ast_bridged_channel(ch
->ast
);
4822 ast_moh_stop(hold_ast
);
4825 if ( misdn_lib_send_event(bc
, EVENT_RETRIEVE_ACKNOWLEDGE
) < 0) {
4826 chan_misdn_log(4, bc
->port
, " --> RETRIEVE_ACK failed\n");
4827 misdn_lib_send_event(bc
, EVENT_RETRIEVE_REJECT
);
4835 struct ast_channel
*bridged
;
4836 misdn_cfg_get( bc
->port
, MISDN_CFG_HOLD_ALLOWED
, &hold_allowed
, sizeof(int));
4838 if (!hold_allowed
) {
4840 chan_misdn_log(-1, bc
->port
, "Hold not allowed this port.\n");
4841 misdn_lib_send_event(bc
, EVENT_HOLD_REJECT
);
4845 bridged
=ast_bridged_channel(ch
->ast
);
4848 chan_misdn_log(2,bc
->port
,"Bridge Partner is of type: %s\n",bridged
->tech
->type
);
4849 ch
->state
= MISDN_HOLDED
;
4850 ch
->l3id
= bc
->l3_id
;
4852 misdn_lib_send_event(bc
, EVENT_HOLD_ACKNOWLEDGE
);
4854 /* XXX This should queue an AST_CONTROL_HOLD frame on this channel
4855 * instead of starting moh on the bridged channel directly */
4856 ast_moh_start(bridged
, NULL
, NULL
);
4858 /*forget the channel now*/
4860 ch
->hold_info
.port
=bc
->port
;
4861 ch
->hold_info
.channel
=bc
->channel
;
4864 misdn_lib_send_event(bc
, EVENT_HOLD_REJECT
);
4865 chan_misdn_log(0, bc
->port
, "We aren't bridged to anybody\n");
4870 case EVENT_FACILITY
:
4872 /* This may come from a call we don't know nothing about, so we ignore it. */
4873 chan_misdn_log(-1, bc
->port
, "Got EVENT_FACILITY but we don't have a ch!\n");
4877 print_facility(&(bc
->fac_in
), bc
);
4879 switch (bc
->fac_in
.Function
) {
4882 struct ast_channel
*bridged
=ast_bridged_channel(ch
->ast
);
4883 struct chan_list
*ch_br
;
4884 if (bridged
&& MISDN_ASTERISK_TECH_PVT(bridged
)) {
4885 ch_br
=MISDN_ASTERISK_TECH_PVT(bridged
);
4886 /*ch->state=MISDN_FACILITY_DEFLECTED;*/
4888 if (ast_exists_extension(bridged
, ch
->context
, (char *)bc
->fac_in
.u
.CDeflection
.DeflectedToNumber
, 1, bc
->oad
)) {
4889 ch_br
->state
=MISDN_DIALING
;
4890 if (pbx_start_chan(ch_br
) < 0) {
4891 chan_misdn_log(-1, ch_br
->bc
->port
, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
4897 misdn_lib_send_event(bc
, EVENT_DISCONNECT
);
4900 case Fac_AOCDCurrency
:
4901 bc
->AOCDtype
= Fac_AOCDCurrency
;
4902 memcpy(&(bc
->AOCD
.currency
), &(bc
->fac_in
.u
.AOCDcur
), sizeof(struct FacAOCDCurrency
));
4903 export_aoc_vars(ch
->originator
, ch
->ast
, bc
);
4905 case Fac_AOCDChargingUnit
:
4906 bc
->AOCDtype
= Fac_AOCDChargingUnit
;
4907 memcpy(&(bc
->AOCD
.chargingUnit
), &(bc
->fac_in
.u
.AOCDchu
), sizeof(struct FacAOCDChargingUnit
));
4908 export_aoc_vars(ch
->originator
, ch
->ast
, bc
);
4911 chan_misdn_log(0, bc
->port
," --> not yet handled: facility type:%p\n", bc
->fac_in
.Function
);
4926 chan_misdn_log(1,0, "Got Unknown Event\n");
4933 /** TE STUFF END **/
4935 /******************************************
4937 * Asterisk Channel Endpoint END
4940 *******************************************/
4944 static int unload_module(void)
4946 /* First, take us out of the channel loop */
4947 ast_log(LOG_VERBOSE
, "-- Unregistering mISDN Channel Driver --\n");
4949 misdn_tasks_destroy();
4951 if (!g_config_initialized
) return 0;
4953 ast_cli_unregister_multiple(chan_misdn_clis
, sizeof(chan_misdn_clis
) / sizeof(struct ast_cli_entry
));
4955 /* ast_unregister_application("misdn_crypt"); */
4956 ast_unregister_application("misdn_set_opt");
4957 ast_unregister_application("misdn_facility");
4958 ast_unregister_application("misdn_check_l2l1");
4960 ast_channel_unregister(&misdn_tech
);
4964 misdn_cfg_destroy();
4965 misdn_lib_destroy();
4969 if (misdn_debug_only
)
4970 free(misdn_debug_only
);
4976 static int load_module(void)
4982 max_ports
=misdn_lib_maxports_get();
4985 ast_log(LOG_ERROR
, "Unable to initialize mISDN\n");
4986 return AST_MODULE_LOAD_DECLINE
;
4989 if (misdn_cfg_init(max_ports
)) {
4990 ast_log(LOG_ERROR
, "Unable to initialize misdn_config.\n");
4991 return AST_MODULE_LOAD_DECLINE
;
4993 g_config_initialized
=1;
4995 misdn_debug
= (int *)malloc(sizeof(int) * (max_ports
+1));
4996 misdn_ports
= (int *)malloc(sizeof(int) * (max_ports
+1));
4997 misdn_cfg_get( 0, MISDN_GEN_DEBUG
, &misdn_debug
[0], sizeof(int));
4998 for (i
= 1; i
<= max_ports
; i
++) {
4999 misdn_debug
[i
] = misdn_debug
[0];
5003 misdn_debug_only
= (int *)calloc(max_ports
+ 1, sizeof(int));
5006 char tempbuf
[BUFFERSIZE
+1];
5007 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE
, tempbuf
, BUFFERSIZE
);
5008 if (strlen(tempbuf
))
5012 misdn_in_calls
= (int *)malloc(sizeof(int) * (max_ports
+1));
5013 misdn_out_calls
= (int *)malloc(sizeof(int) * (max_ports
+1));
5015 for (i
=1; i
<= max_ports
; i
++) {
5016 misdn_in_calls
[i
]=0;
5017 misdn_out_calls
[i
]=0;
5020 ast_mutex_init(&cl_te_lock
);
5021 ast_mutex_init(&release_lock
);
5023 misdn_cfg_update_ptp();
5024 misdn_cfg_get_ports_string(ports
);
5027 chan_misdn_log(0, 0, "Got: %s from get_ports\n",ports
);
5030 int ntflags
=0, ntkc
=0;
5031 char ntfile
[BUFFERSIZE
+1];
5032 struct misdn_lib_iface iface
= {
5033 .cb_event
= cb_events
,
5034 .cb_log
= chan_misdn_log
,
5035 .cb_jb_empty
= chan_misdn_jb_empty
,
5038 if (misdn_lib_init(ports
, &iface
, NULL
))
5039 chan_misdn_log(0, 0, "No te ports initialized\n");
5041 misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFLAGS
, &ntflags
, sizeof(int));
5042 misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFILE
, &ntfile
, BUFFERSIZE
);
5043 misdn_lib_nt_debug_init(ntflags
,ntfile
);
5045 misdn_cfg_get( 0, MISDN_GEN_NTKEEPCALLS
, &ntkc
, sizeof(int));
5046 misdn_lib_nt_keepcalls(ntkc
);
5050 if (ast_channel_register(&misdn_tech
)) {
5051 ast_log(LOG_ERROR
, "Unable to register channel class %s\n", misdn_type
);
5057 ast_cli_register_multiple(chan_misdn_clis
, sizeof(chan_misdn_clis
) / sizeof(struct ast_cli_entry
));
5059 ast_register_application("misdn_set_opt", misdn_set_opt_exec
, "misdn_set_opt",
5060 "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
5061 "Sets mISDN opts. and optargs\n"
5063 "The available options are:\n"
5064 " d - Send display text on called phone, text is the optparam\n"
5065 " n - don't detect dtmf tones on called channel\n"
5066 " h - make digital outgoing call\n"
5067 " c - make crypted outgoing call, param is keyindex\n"
5068 " e - perform echo cancelation on this channel,\n"
5069 " takes taps as arguments (32,64,128,256)\n"
5070 " s - send Non Inband DTMF as inband\n"
5071 " vr - rxgain control\n"
5072 " vt - txgain control\n"
5073 " i - Ignore detected dtmf tones, don't signal them to asterisk, they will be transported inband.\n"
5077 ast_register_application("misdn_facility", misdn_facility_exec
, "misdn_facility",
5078 "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
5079 "Sends the Facility Message FACILITY_TYPE with \n"
5080 "the given Arguments to the current ISDN Channel\n"
5081 "Supported Facilities are:\n"
5083 "type=calldeflect args=Nr where to deflect\n"
5087 ast_register_application("misdn_check_l2l1", misdn_check_l2l1
, "misdn_check_l2l1",
5088 "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
5089 "Checks if the L2 and L1 are up on either the given <port> or\n"
5090 "on the ports in the group with <groupname>\n"
5091 "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
5092 "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
5094 "This application, ensures the L1/L2 state of the Ports in a group\n"
5095 "it is intended to make the pmp_l1_check option redundant and to\n"
5096 "fix a buggy switch config from your provider\n"
5098 "a sample dialplan would look like:\n\n"
5099 "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
5100 "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
5105 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE
, global_tracefile
, BUFFERSIZE
);
5107 /* start the l1 watchers */
5109 for (port
= misdn_cfg_get_next_port(0); port
>= 0; port
= misdn_cfg_get_next_port(port
)) {
5111 misdn_cfg_get(port
, MISDN_CFG_L1_TIMEOUT
, &l1timeout
, sizeof(l1timeout
));
5113 chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port
, l1timeout
);
5114 misdn_tasks_add(l1timeout
* 1000, misdn_l1_task
, &misdn_ports
[port
]);
5118 chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
5125 static int reload(void)
5132 /*** SOME APPS ;)***/
5134 static int misdn_facility_exec(struct ast_channel
*chan
, void *data
)
5136 struct chan_list
*ch
= MISDN_ASTERISK_TECH_PVT(chan
);
5139 chan_misdn_log(0,0,"TYPE: %s\n",chan
->tech
->type
);
5141 if (strcasecmp(chan
->tech
->type
,"mISDN")) {
5142 ast_log(LOG_WARNING
, "misdn_facility makes only sense with chan_misdn channels!\n");
5146 if (ast_strlen_zero((char *)data
)) {
5147 ast_log(LOG_WARNING
, "misdn_facility Requires arguments\n");
5151 tok
=strtok_r((char*)data
,"|", &tokb
) ;
5154 ast_log(LOG_WARNING
, "misdn_facility Requires arguments\n");
5158 if (!strcasecmp(tok
,"calldeflect")) {
5159 tok
=strtok_r(NULL
,"|", &tokb
) ;
5162 ast_log(LOG_WARNING
, "Facility: Call Defl Requires arguments\n");
5165 if (strlen(tok
) >= sizeof(ch
->bc
->fac_out
.u
.CDeflection
.DeflectedToNumber
)) {
5166 ast_log(LOG_WARNING
, "Facility: Number argument too long (up to 15 digits are allowed). Ignoring.\n");
5169 ch
->bc
->fac_out
.Function
= Fac_CD
;
5170 strncpy((char *)ch
->bc
->fac_out
.u
.CDeflection
.DeflectedToNumber
, tok
, sizeof(ch
->bc
->fac_out
.u
.CDeflection
.DeflectedToNumber
));
5171 misdn_lib_send_event(ch
->bc
, EVENT_FACILITY
);
5173 chan_misdn_log(1, ch
->bc
->port
, "Unknown Facility: %s\n",tok
);
5180 static int misdn_check_l2l1(struct ast_channel
*chan
, void *data
)
5182 char group
[BUFFERSIZE
+1];
5189 AST_DECLARE_APP_ARGS(args
,
5190 AST_APP_ARG(grouppar
);
5191 AST_APP_ARG(timeout
);
5194 if (ast_strlen_zero((char *)data
)) {
5195 ast_log(LOG_WARNING
, "misdn_check_l2l1 Requires arguments\n");
5199 AST_STANDARD_APP_ARGS(args
, data
);
5201 if (args
.argc
!= 2) {
5202 ast_log(LOG_WARNING
, "Wrong argument count\n");
5206 /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
5207 timeout
=atoi(args
.timeout
);
5208 port_str
=args
.grouppar
;
5209 if (port_str
[0]=='g' && port_str
[1]==':' ) {
5210 /* We make a group call lets checkout which ports are in my group */
5212 strncpy(group
, port_str
, BUFFERSIZE
);
5213 group
[BUFFERSIZE
-1] = 0;
5214 chan_misdn_log(2, 0, "Checking Ports in group: %s\n",group
);
5216 for ( port
= misdn_cfg_get_next_port(port
);
5218 port
= misdn_cfg_get_next_port(port
))
5220 char cfg_group
[BUFFERSIZE
+1];
5222 chan_misdn_log(2,0,"trying port %d\n",port
);
5224 misdn_cfg_get(port
, MISDN_CFG_GROUPNAME
, cfg_group
, BUFFERSIZE
);
5226 if (!strcasecmp(cfg_group
, group
)) {
5227 port_up
= misdn_lib_port_up(port
, 1);
5230 chan_misdn_log(2, 0, " --> port '%d'\n", port
);
5231 misdn_lib_get_port_up(port
);
5238 port
= atoi(port_str
);
5239 chan_misdn_log(2, 0, "Checking Port: %d\n",port
);
5240 port_up
= misdn_lib_port_up(port
, 1);
5242 misdn_lib_get_port_up(port
);
5249 chan_misdn_log(2, 0, "Waiting for '%d' seconds\n",timeout
);
5256 static int misdn_set_opt_exec(struct ast_channel
*chan
, void *data
)
5258 struct chan_list
*ch
= MISDN_ASTERISK_TECH_PVT(chan
);
5263 int change_jitter
=0;
5265 if (strcasecmp(chan
->tech
->type
,"mISDN")) {
5266 ast_log(LOG_WARNING
, "misdn_set_opt makes only sense with chan_misdn channels!\n");
5270 if (ast_strlen_zero((char *)data
)) {
5271 ast_log(LOG_WARNING
, "misdn_set_opt Requires arguments\n");
5275 for (tok
=strtok_r((char*)data
, ":",&tokb
);
5277 tok
=strtok_r(NULL
,":",&tokb
) ) {
5283 if (tok
[0] == '!' ) {
5291 ast_copy_string(ch
->bc
->display
,++tok
,84);
5292 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: Display:%s\n",ch
->bc
->display
);
5296 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: No DSP\n");
5301 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: jitter\n");
5307 ch
->jb_len
=atoi(++tok
);
5308 chan_misdn_log(1, ch
->bc
->port
, " --> buffer_len:%d\n",ch
->jb_len
);
5311 ch
->jb_upper_threshold
=atoi(++tok
);
5312 chan_misdn_log(1, ch
->bc
->port
, " --> upper_threshold:%d\n",ch
->jb_upper_threshold
);
5317 chan_misdn_log(1, ch
->bc
->port
, " --> nojitter\n");
5322 ch
->jb_upper_threshold
=0;
5323 chan_misdn_log(1, ch
->bc
->port
, " --> buffer_len:%d (default)\n",ch
->jb_len
);
5324 chan_misdn_log(1, ch
->bc
->port
, " --> upper_threshold:%d (default)\n",ch
->jb_upper_threshold
);
5335 if (rxgain
<-8) rxgain
=-8;
5336 if (rxgain
>8) rxgain
=8;
5337 ch
->bc
->rxgain
=rxgain
;
5338 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: Volume:%d\n",rxgain
);
5342 if (txgain
<-8) txgain
=-8;
5343 if (txgain
>8) txgain
=8;
5344 ch
->bc
->txgain
=txgain
;
5345 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: Volume:%d\n",txgain
);
5353 misdn_cfg_get( 0, MISDN_GEN_CRYPT_KEYS
, keys
, sizeof(keys
));
5357 for (i
=0; i
<keyidx
; i
++) {
5358 key
=strsep(&tmp
,",");
5362 ast_copy_string(ch
->bc
->crypt_key
, key
, sizeof(ch
->bc
->crypt_key
));
5365 chan_misdn_log(0, ch
->bc
->port
, "SETOPT: crypt with key:%s\n",ch
->bc
->crypt_key
);
5369 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: EchoCancel\n");
5372 chan_misdn_log(1, ch
->bc
->port
, " --> disabled\n");
5374 *ch
->bc
->pipeline
=0;
5376 ch
->bc
->ec_enable
=0;
5380 update_pipeline_config(ch
->bc
);
5382 ch
->bc
->ec_enable
=1;
5383 ch
->bc
->orig
=ch
->originator
;
5386 ch
->bc
->ec_deftaps
=atoi(tok
);
5394 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: Digital\n");
5396 if (strlen(tok
) > 1 && tok
[1]=='1') {
5397 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: HDLC \n");
5398 if (!ch
->bc
->hdlc
) {
5402 ch
->bc
->capability
=INFO_CAPABILITY_DIGITAL_UNRESTRICTED
;
5406 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: Send DTMF\n");
5407 ch
->bc
->send_dtmf
=1;
5411 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: Faxdetect\n");
5413 misdn_cfg_get(ch
->bc
->port
, MISDN_CFG_FAXDETECT_TIMEOUT
, &ch
->faxdetect_timeout
, sizeof(ch
->faxdetect_timeout
));
5417 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: AST_DSP (for DTMF)\n");
5422 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: callerpres: %s\n",&tok
[1]);
5423 /* CRICH: callingpres!!! */
5424 if (strstr(tok
,"allowed") ) {
5426 } else if (strstr(tok
,"not_screened")) {
5431 chan_misdn_log(1, ch
->bc
->port
, "Ignoring dtmf tones, just use them inband\n");
5440 config_jitterbuffer(ch
);
5443 if (ch
->faxdetect
|| ch
->ast_dsp
) {
5444 if (!ch
->dsp
) ch
->dsp
= ast_dsp_new();
5445 if (ch
->dsp
) ast_dsp_set_features(ch
->dsp
, DSP_FEATURE_DTMF_DETECT
| DSP_FEATURE_FAX_DETECT
);
5446 if (!ch
->trans
) ch
->trans
=ast_translator_build_path(AST_FORMAT_SLINEAR
, AST_FORMAT_ALAW
);
5450 chan_misdn_log(1,ch
->bc
->port
,"SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
5459 int chan_misdn_jb_empty ( struct misdn_bchannel
*bc
, char *buf
, int len
)
5461 struct chan_list
*ch
=find_chan_by_bc(cl_te
, bc
);
5464 return misdn_jb_empty(ch
->jb
, buf
, len
);
5472 /*******************************************************/
5473 /***************** JITTERBUFFER ************************/
5474 /*******************************************************/
5477 /* allocates the jb-structure and initialize the elements*/
5478 struct misdn_jb
*misdn_jb_init(int size
, int upper_threshold
)
5481 struct misdn_jb
*jb
= (struct misdn_jb
*) malloc(sizeof(struct misdn_jb
));
5483 jb
->upper_threshold
= upper_threshold
;
5487 jb
->state_empty
= 0;
5488 jb
->bytes_wrote
= 0;
5489 jb
->samples
= (char *)malloc(size
*sizeof(char));
5492 chan_misdn_log(-1,0,"No free Mem for jb->samples\n");
5496 jb
->ok
= (char *)malloc(size
*sizeof(char));
5499 chan_misdn_log(-1,0,"No free Mem for jb->ok\n");
5503 for(i
=0; i
<size
; i
++)
5506 ast_mutex_init(&jb
->mutexjb
);
5511 /* frees the data and destroys the given jitterbuffer struct */
5512 void misdn_jb_destroy(struct misdn_jb
*jb
)
5514 ast_mutex_destroy(&jb
->mutexjb
);
5520 /* fills the jitterbuffer with len data returns < 0 if there was an
5521 error (buffer overflow). */
5522 int misdn_jb_fill(struct misdn_jb
*jb
, const char *data
, int len
)
5526 if (!jb
|| ! data
) return 0;
5528 ast_mutex_lock (&jb
->mutexjb
);
5533 for(i
=0; i
<len
; i
++)
5535 jb
->samples
[wp
]=data
[i
];
5537 wp
= (wp
!=jb
->size
-1 ? wp
+1 : 0);
5544 jb
->state_buffer
=wp
-rp
;
5546 jb
->state_buffer
= jb
->size
-rp
+wp
;
5547 chan_misdn_log(9,0,"misdn_jb_fill: written:%d | Buffer status:%d p:%x\n",len
,jb
->state_buffer
,jb
);
5554 for(j
=0; j
<jb
->upper_threshold
; j
++)
5555 rp
= (rp
!=0 ? rp
-1 : jb
->size
-1);
5560 ast_mutex_unlock (&jb
->mutexjb
);
5565 if(!jb
->state_empty
)
5567 jb
->bytes_wrote
+=len
;
5568 if(jb
->bytes_wrote
>=jb
->upper_threshold
)
5576 ast_mutex_unlock (&jb
->mutexjb
);
5581 /* gets len bytes out of the jitterbuffer if available, else only the
5582 available data is returned and the return value indicates the number
5584 int misdn_jb_empty(struct misdn_jb
*jb
, char *data
, int len
)
5586 int i
, wp
, rp
, read
=0;
5588 ast_mutex_lock (&jb
->mutexjb
);
5595 for(i
=0; i
<len
; i
++)
5602 ast_mutex_unlock (&jb
->mutexjb
);
5610 data
[i
]=jb
->samples
[rp
];
5612 rp
=(rp
!=jb
->size
-1 ? rp
+1 : 0);
5619 jb
->state_buffer
=wp
-rp
;
5621 jb
->state_buffer
= jb
->size
-rp
+wp
;
5622 chan_misdn_log(9,0,"misdn_jb_empty: read:%d | Buffer status:%d p:%x\n",len
,jb
->state_buffer
,jb
);
5627 chan_misdn_log(9,0,"misdn_jb_empty: Wait...requested:%d p:%x\n",len
,jb
);
5629 ast_mutex_unlock (&jb
->mutexjb
);
5637 /*******************************************************/
5638 /*************** JITTERBUFFER END *********************/
5639 /*******************************************************/
5644 static void chan_misdn_log(int level
, int port
, char *tmpl
, ...)
5650 if (! ((0 <= port
) && (port
<= max_ports
))) {
5651 ast_log(LOG_WARNING
, "cb_log called with out-of-range port number! (%d)\n", port
);
5656 sprintf(port_buf
,"P[%2d] ",port
);
5659 vsnprintf( buf
, 1023, tmpl
, ap
);
5663 ast_log(LOG_WARNING
, buf
);
5665 else if (misdn_debug_only
[port
] ?
5666 (level
==1 && misdn_debug
[port
]) || (level
==misdn_debug
[port
])
5667 : level
<= misdn_debug
[port
]) {
5669 ast_console_puts(port_buf
);
5670 ast_console_puts(buf
);
5673 if ((level
<= misdn_debug
[0]) && !ast_strlen_zero(global_tracefile
) ) {
5674 time_t tm
= time(NULL
);
5675 char *tmp
=ctime(&tm
),*p
;
5677 FILE *fp
= fopen(global_tracefile
, "a+");
5683 ast_console_puts("Error opening Tracefile: [ ");
5684 ast_console_puts(global_tracefile
);
5685 ast_console_puts(" ] ");
5687 ast_console_puts(strerror(errno
));
5688 ast_console_puts("\n");
5702 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_DEFAULT
, "Channel driver for mISDN Support (BRI/PRI)",
5703 .load
= load_module
,
5704 .unload
= unload_module
,