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 initialise 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 (bufferoverun). */
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 couldnt 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 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
);
369 int chan_misdn_jb_empty ( struct misdn_bchannel
*bc
, char *buf
, int len
);
371 /*************** Helpers *****************/
373 static struct chan_list
* get_chan_by_ast(struct ast_channel
*ast
)
375 struct chan_list
*tmp
;
377 for (tmp
=cl_te
; tmp
; tmp
= tmp
->next
) {
378 if ( tmp
->ast
== ast
) return tmp
;
384 static struct chan_list
* get_chan_by_ast_name(char *name
)
386 struct chan_list
*tmp
;
388 for (tmp
=cl_te
; tmp
; tmp
= tmp
->next
) {
389 if ( tmp
->ast
&& strcmp(tmp
->ast
->name
,name
) == 0) return tmp
;
397 struct allowed_bearers
{
403 struct allowed_bearers allowed_bearers_array
[]={
404 {INFO_CAPABILITY_SPEECH
,1,"speech"},
405 {INFO_CAPABILITY_AUDIO_3_1K
,2,"3_1khz"},
406 {INFO_CAPABILITY_DIGITAL_UNRESTRICTED
,4,"digital_unrestricted"},
407 {INFO_CAPABILITY_DIGITAL_RESTRICTED
,8,"digital_restriced"},
408 {INFO_CAPABILITY_VIDEO
,16,"video"}
411 static char *bearer2str(int cap
) {
412 static char *bearers
[]={
422 case INFO_CAPABILITY_SPEECH
:
425 case INFO_CAPABILITY_AUDIO_3_1K
:
428 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED
:
431 case INFO_CAPABILITY_DIGITAL_RESTRICTED
:
434 case INFO_CAPABILITY_VIDEO
:
444 static void print_facility(struct FacParm
*fac
, struct misdn_bchannel
*bc
)
446 switch (fac
->Function
) {
448 chan_misdn_log(1,bc
->port
," --> calldeflect to: %s, screened: %s\n", fac
->u
.CDeflection
.DeflectedToNumber
,
449 fac
->u
.CDeflection
.PresentationAllowed
? "yes" : "no");
451 case Fac_AOCDCurrency
:
452 if (fac
->u
.AOCDcur
.chargeNotAvailable
)
453 chan_misdn_log(1,bc
->port
," --> AOCD currency: charge not available\n");
454 else if (fac
->u
.AOCDcur
.freeOfCharge
)
455 chan_misdn_log(1,bc
->port
," --> AOCD currency: free of charge\n");
456 else if (fac
->u
.AOCDchu
.billingId
>= 0)
457 chan_misdn_log(1,bc
->port
," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d billingId:%d\n",
458 fac
->u
.AOCDcur
.currency
, fac
->u
.AOCDcur
.currencyAmount
, fac
->u
.AOCDcur
.multiplier
,
459 (fac
->u
.AOCDcur
.typeOfChargingInfo
== 0) ? "subTotal" : "total", fac
->u
.AOCDcur
.billingId
);
461 chan_misdn_log(1,bc
->port
," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d\n",
462 fac
->u
.AOCDcur
.currency
, fac
->u
.AOCDcur
.currencyAmount
, fac
->u
.AOCDcur
.multiplier
,
463 (fac
->u
.AOCDcur
.typeOfChargingInfo
== 0) ? "subTotal" : "total");
465 case Fac_AOCDChargingUnit
:
466 if (fac
->u
.AOCDchu
.chargeNotAvailable
)
467 chan_misdn_log(1,bc
->port
," --> AOCD charging unit: charge not available\n");
468 else if (fac
->u
.AOCDchu
.freeOfCharge
)
469 chan_misdn_log(1,bc
->port
," --> AOCD charging unit: free of charge\n");
470 else if (fac
->u
.AOCDchu
.billingId
>= 0)
471 chan_misdn_log(1,bc
->port
," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
472 fac
->u
.AOCDchu
.recordedUnits
, (fac
->u
.AOCDchu
.typeOfChargingInfo
== 0) ? "subTotal" : "total", fac
->u
.AOCDchu
.billingId
);
474 chan_misdn_log(1,bc
->port
," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
475 fac
->u
.AOCDchu
.recordedUnits
, (fac
->u
.AOCDchu
.typeOfChargingInfo
== 0) ? "subTotal" : "total");
478 chan_misdn_log(1,bc
->port
," --> unknown\n");
482 static void print_bearer(struct misdn_bchannel
*bc
)
485 chan_misdn_log(2, bc
->port
, " --> Bearer: %s\n",bearer2str(bc
->capability
));
488 case INFO_CODEC_ALAW
:
489 chan_misdn_log(2, bc
->port
, " --> Codec: Alaw\n");
491 case INFO_CODEC_ULAW
:
492 chan_misdn_log(2, bc
->port
, " --> Codec: Ulaw\n");
497 static void export_aoc_vars(int originator
, struct ast_channel
*ast
, struct misdn_bchannel
*bc
)
504 if (originator
== ORG_AST
) {
505 ast
= ast_bridged_channel(ast
);
510 switch (bc
->AOCDtype
) {
511 case Fac_AOCDCurrency
:
512 pbx_builtin_setvar_helper(ast
, "AOCD_Type", "currency");
513 if (bc
->AOCD
.currency
.chargeNotAvailable
)
514 pbx_builtin_setvar_helper(ast
, "AOCD_ChargeAvailable", "no");
516 pbx_builtin_setvar_helper(ast
, "AOCD_ChargeAvailable", "yes");
517 if (bc
->AOCD
.currency
.freeOfCharge
)
518 pbx_builtin_setvar_helper(ast
, "AOCD_FreeOfCharge", "yes");
520 pbx_builtin_setvar_helper(ast
, "AOCD_FreeOfCharge", "no");
521 if (snprintf(buf
, sizeof(buf
), "%d %s", bc
->AOCD
.currency
.currencyAmount
* bc
->AOCD
.currency
.multiplier
, bc
->AOCD
.currency
.currency
) < sizeof(buf
)) {
522 pbx_builtin_setvar_helper(ast
, "AOCD_Amount", buf
);
523 if (bc
->AOCD
.currency
.billingId
>= 0 && snprintf(buf
, sizeof(buf
), "%d", bc
->AOCD
.currency
.billingId
) < sizeof(buf
))
524 pbx_builtin_setvar_helper(ast
, "AOCD_BillingId", buf
);
529 case Fac_AOCDChargingUnit
:
530 pbx_builtin_setvar_helper(ast
, "AOCD_Type", "charging_unit");
531 if (bc
->AOCD
.chargingUnit
.chargeNotAvailable
)
532 pbx_builtin_setvar_helper(ast
, "AOCD_ChargeAvailable", "no");
534 pbx_builtin_setvar_helper(ast
, "AOCD_ChargeAvailable", "yes");
535 if (bc
->AOCD
.chargingUnit
.freeOfCharge
)
536 pbx_builtin_setvar_helper(ast
, "AOCD_FreeOfCharge", "yes");
538 pbx_builtin_setvar_helper(ast
, "AOCD_FreeOfCharge", "no");
539 if (snprintf(buf
, sizeof(buf
), "%d", bc
->AOCD
.chargingUnit
.recordedUnits
) < sizeof(buf
)) {
540 pbx_builtin_setvar_helper(ast
, "AOCD_RecordedUnits", buf
);
541 if (bc
->AOCD
.chargingUnit
.billingId
>= 0 && snprintf(buf
, sizeof(buf
), "%d", bc
->AOCD
.chargingUnit
.billingId
) < sizeof(buf
))
542 pbx_builtin_setvar_helper(ast
, "AOCD_BillingId", buf
);
552 /*************** Helpers END *************/
554 static void sighandler(int sig
)
557 static void* misdn_tasks_thread_func (void *data
)
562 sa
.sa_handler
= sighandler
;
563 sa
.sa_flags
= SA_NODEFER
;
564 sigemptyset(&sa
.sa_mask
);
565 sigaddset(&sa
.sa_mask
, SIGUSR1
);
566 sigaction(SIGUSR1
, &sa
, NULL
);
568 sem_post((sem_t
*)data
);
571 wait
= ast_sched_wait(misdn_tasks
);
574 if (poll(NULL
, 0, wait
) < 0)
575 chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
576 ast_sched_runq(misdn_tasks
);
581 static void misdn_tasks_init (void)
586 if (sem_init(&blocker
, 0, 0)) {
587 perror("chan_misdn: Failed to initialize semaphore!");
591 chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
593 misdn_tasks
= sched_context_create();
594 pthread_create(&misdn_tasks_thread
, NULL
, misdn_tasks_thread_func
, &blocker
);
596 while (sem_wait(&blocker
) && --i
);
597 sem_destroy(&blocker
);
600 static void misdn_tasks_destroy (void)
603 chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
604 if ( pthread_cancel(misdn_tasks_thread
) == 0 ) {
605 cb_log(4, 0, "Joining misdn_tasks thread\n");
606 pthread_join(misdn_tasks_thread
, NULL
);
608 sched_context_destroy(misdn_tasks
);
612 static inline void misdn_tasks_wakeup (void)
614 pthread_kill(misdn_tasks_thread
, SIGUSR1
);
617 static inline int _misdn_tasks_add_variable (int timeout
, ast_sched_cb callback
, const void *data
, int variable
)
624 task_id
= ast_sched_add_variable(misdn_tasks
, timeout
, callback
, data
, variable
);
625 misdn_tasks_wakeup();
630 static int misdn_tasks_add (int timeout
, ast_sched_cb callback
, const void *data
)
632 return _misdn_tasks_add_variable(timeout
, callback
, data
, 0);
635 static int misdn_tasks_add_variable (int timeout
, ast_sched_cb callback
, const void *data
)
637 return _misdn_tasks_add_variable(timeout
, callback
, data
, 1);
640 static void misdn_tasks_remove (int task_id
)
642 ast_sched_del(misdn_tasks
, task_id
);
645 static int misdn_l1_task (const void *data
)
647 misdn_lib_isdn_l1watcher(*(int *)data
);
648 chan_misdn_log(5, *(int *)data
, "L1watcher timeout\n");
652 static int misdn_overlap_dial_task (const void *data
)
654 struct timeval tv_end
, tv_now
;
656 struct chan_list
*ch
= (struct chan_list
*)data
;
658 chan_misdn_log(4, ch
->bc
->port
, "overlap dial task, chan_state: %d\n", ch
->state
);
660 if (ch
->state
!= MISDN_WAITING4DIGS
) {
661 ch
->overlap_dial_task
= -1;
665 ast_mutex_lock(&ch
->overlap_tv_lock
);
666 tv_end
= ch
->overlap_tv
;
667 ast_mutex_unlock(&ch
->overlap_tv_lock
);
669 tv_end
.tv_sec
+= ch
->overlap_dial
;
670 tv_now
= ast_tvnow();
672 diff
= ast_tvdiff_ms(tv_end
, tv_now
);
675 char *dad
=ch
->bc
->dad
, sexten
[]="s";
676 /* if we are 100ms near the timeout, we are satisfied.. */
679 if (ast_strlen_zero(ch
->bc
->dad
)) {
681 strcpy(ch
->ast
->exten
, sexten
);
684 if (ast_exists_extension(ch
->ast
, ch
->context
, dad
, 1, ch
->bc
->oad
)) {
685 ch
->state
=MISDN_DIALING
;
686 if (pbx_start_chan(ch
) < 0) {
687 chan_misdn_log(-1, ch
->bc
->port
, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
688 goto misdn_overlap_dial_task_disconnect
;
691 misdn_overlap_dial_task_disconnect
:
692 hanguptone_indicate(ch
);
694 ch
->state
=MISDN_CLEANING
;
695 misdn_lib_send_event(ch
->bc
, EVENT_DISCONNECT
);
697 ch
->overlap_dial_task
= -1;
703 static void send_digit_to_chan(struct chan_list
*cl
, char digit
)
705 static const char* dtmf_tones
[] = {
706 "!941+1336/100,!0/100", /* 0 */
707 "!697+1209/100,!0/100", /* 1 */
708 "!697+1336/100,!0/100", /* 2 */
709 "!697+1477/100,!0/100", /* 3 */
710 "!770+1209/100,!0/100", /* 4 */
711 "!770+1336/100,!0/100", /* 5 */
712 "!770+1477/100,!0/100", /* 6 */
713 "!852+1209/100,!0/100", /* 7 */
714 "!852+1336/100,!0/100", /* 8 */
715 "!852+1477/100,!0/100", /* 9 */
716 "!697+1633/100,!0/100", /* A */
717 "!770+1633/100,!0/100", /* B */
718 "!852+1633/100,!0/100", /* C */
719 "!941+1633/100,!0/100", /* D */
720 "!941+1209/100,!0/100", /* * */
721 "!941+1477/100,!0/100" }; /* # */
722 struct ast_channel
*chan
=cl
->ast
;
724 if (digit
>= '0' && digit
<='9')
725 ast_playtones_start(chan
,0,dtmf_tones
[digit
-'0'], 0);
726 else if (digit
>= 'A' && digit
<= 'D')
727 ast_playtones_start(chan
,0,dtmf_tones
[digit
-'A'+10], 0);
728 else if (digit
== '*')
729 ast_playtones_start(chan
,0,dtmf_tones
[14], 0);
730 else if (digit
== '#')
731 ast_playtones_start(chan
,0,dtmf_tones
[15], 0);
734 ast_log(LOG_DEBUG
, "Unable to handle DTMF tone '%c' for '%s'\n", digit
, chan
->name
);
739 /*** CLI HANDLING ***/
740 static int misdn_set_debug(int fd
, int argc
, char *argv
[])
744 if (argc
!= 4 && argc
!= 5 && argc
!= 6 && argc
!= 7)
745 return RESULT_SHOWUSAGE
;
747 level
= atoi(argv
[3]);
755 if (strncasecmp(argv
[4], "only", strlen(argv
[4])))
756 return RESULT_SHOWUSAGE
;
760 for (i
=0; i
<=max_ports
; i
++) {
761 misdn_debug
[i
] = level
;
762 misdn_debug_only
[i
] = only
;
764 ast_cli(fd
, "changing debug level for all ports to %d%s\n",misdn_debug
[0], only
?" (only)":"");
770 if (strncasecmp(argv
[4], "port", strlen(argv
[4])))
771 return RESULT_SHOWUSAGE
;
772 port
= atoi(argv
[5]);
773 if (port
<= 0 || port
> max_ports
) {
776 ast_cli(fd
, "port number not valid! no ports available so you won't get lucky with any number here...\n");
779 ast_cli(fd
, "port number not valid! only port 1 is availble.\n");
782 ast_cli(fd
, "port number not valid! only ports 1 to %d are available.\n", max_ports
);
787 if (strncasecmp(argv
[6], "only", strlen(argv
[6])))
788 return RESULT_SHOWUSAGE
;
790 misdn_debug_only
[port
] = 1;
792 misdn_debug_only
[port
] = 0;
793 misdn_debug
[port
] = level
;
794 ast_cli(fd
, "changing debug level to %d%s for port %d\n", misdn_debug
[port
], misdn_debug_only
[port
]?" (only)":"", port
);
800 static int misdn_set_crypt_debug(int fd
, int argc
, char *argv
[])
802 if (argc
!= 5) return RESULT_SHOWUSAGE
;
807 static int misdn_port_block(int fd
, int argc
, char *argv
[])
812 return RESULT_SHOWUSAGE
;
814 port
= atoi(argv
[3]);
816 misdn_lib_port_block(port
);
821 static int misdn_port_unblock(int fd
, int argc
, char *argv
[])
826 return RESULT_SHOWUSAGE
;
828 port
= atoi(argv
[3]);
830 misdn_lib_port_unblock(port
);
836 static int misdn_restart_port (int fd
, int argc
, char *argv
[])
841 return RESULT_SHOWUSAGE
;
843 port
= atoi(argv
[3]);
845 misdn_lib_port_restart(port
);
850 static int misdn_restart_pid (int fd
, int argc
, char *argv
[])
855 return RESULT_SHOWUSAGE
;
859 misdn_lib_pid_restart(pid
);
864 static int misdn_port_up (int fd
, int argc
, char *argv
[])
869 return RESULT_SHOWUSAGE
;
871 port
= atoi(argv
[3]);
873 misdn_lib_get_port_up(port
);
878 static int misdn_port_down (int fd
, int argc
, char *argv
[])
883 return RESULT_SHOWUSAGE
;
885 port
= atoi(argv
[3]);
887 misdn_lib_get_port_down(port
);
892 static inline void show_config_description (int fd
, enum misdn_cfg_elements elem
)
894 char section
[BUFFERSIZE
];
895 char name
[BUFFERSIZE
];
896 char desc
[BUFFERSIZE
];
897 char def
[BUFFERSIZE
];
898 char tmp
[BUFFERSIZE
];
900 misdn_cfg_get_name(elem
, tmp
, sizeof(tmp
));
901 term_color(name
, tmp
, COLOR_BRWHITE
, 0, sizeof(tmp
));
902 misdn_cfg_get_desc(elem
, desc
, sizeof(desc
), def
, sizeof(def
));
904 if (elem
< MISDN_CFG_LAST
)
905 term_color(section
, "PORTS SECTION", COLOR_YELLOW
, 0, sizeof(section
));
907 term_color(section
, "GENERAL SECTION", COLOR_YELLOW
, 0, sizeof(section
));
910 ast_cli(fd
, "[%s] %s (Default: %s)\n\t%s\n", section
, name
, def
, desc
);
912 ast_cli(fd
, "[%s] %s\n\t%s\n", section
, name
, desc
);
915 static int misdn_show_config (int fd
, int argc
, char *argv
[])
917 char buffer
[BUFFERSIZE
];
918 enum misdn_cfg_elements elem
;
924 if (!strcmp(argv
[3], "description")) {
926 enum misdn_cfg_elements elem
= misdn_cfg_get_elem (argv
[4]);
927 if (elem
== MISDN_CFG_FIRST
)
928 ast_cli(fd
, "Unknown element: %s\n", argv
[4]);
930 show_config_description(fd
, elem
);
933 return RESULT_SHOWUSAGE
;
935 if (!strcmp(argv
[3], "descriptions")) {
936 if ((argc
== 4) || ((argc
== 5) && !strcmp(argv
[4], "general"))) {
937 for (elem
= MISDN_GEN_FIRST
+ 1; elem
< MISDN_GEN_LAST
; ++elem
) {
938 show_config_description(fd
, elem
);
943 if ((argc
== 4) || ((argc
== 5) && !strcmp(argv
[4], "ports"))) {
944 for (elem
= MISDN_CFG_FIRST
+ 1; elem
< MISDN_CFG_LAST
- 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem
) {
945 show_config_description(fd
, elem
);
950 return ok
? 0 : RESULT_SHOWUSAGE
;
952 if (!sscanf(argv
[3], "%d", &onlyport
) || onlyport
< 0) {
953 ast_cli(fd
, "Unknown option: %s\n", argv
[3]);
954 return RESULT_SHOWUSAGE
;
958 if (argc
== 3 || onlyport
== 0) {
959 ast_cli(fd
,"Misdn General-Config: \n");
960 for (elem
= MISDN_GEN_FIRST
+ 1, linebreak
= 1; elem
< MISDN_GEN_LAST
; elem
++, linebreak
++) {
961 misdn_cfg_get_config_string( 0, elem
, buffer
, BUFFERSIZE
);
962 ast_cli(fd
, "%-36s%s", buffer
, !(linebreak
% 2) ? "\n" : "");
968 int port
= misdn_cfg_get_next_port(0);
969 for (; port
> 0; port
= misdn_cfg_get_next_port(port
)) {
970 ast_cli(fd
, "\n[PORT %d]\n", port
);
971 for (elem
= MISDN_CFG_FIRST
+ 1, linebreak
= 1; elem
< MISDN_CFG_LAST
; elem
++, linebreak
++) {
972 misdn_cfg_get_config_string( port
, elem
, buffer
, BUFFERSIZE
);
973 ast_cli(fd
, "%-36s%s", buffer
, !(linebreak
% 2) ? "\n" : "");
980 if (misdn_cfg_is_port_valid(onlyport
)) {
981 ast_cli(fd
, "[PORT %d]\n", onlyport
);
982 for (elem
= MISDN_CFG_FIRST
+ 1, linebreak
= 1; elem
< MISDN_CFG_LAST
; elem
++, linebreak
++) {
983 misdn_cfg_get_config_string(onlyport
, elem
, buffer
, BUFFERSIZE
);
984 ast_cli(fd
, "%-36s%s", buffer
, !(linebreak
% 2) ? "\n" : "");
988 ast_cli(fd
, "Port %d is not active!\n", onlyport
);
994 struct state_struct
{
995 enum misdn_chan_state state
;
999 static struct state_struct state_array
[] = {
1000 {MISDN_NOTHING
,"NOTHING"}, /* at beginning */
1001 {MISDN_WAITING4DIGS
,"WAITING4DIGS"}, /* when waiting for infos */
1002 {MISDN_EXTCANTMATCH
,"EXTCANTMATCH"}, /* when asterisk couldnt match our ext */
1003 {MISDN_INCOMING_SETUP
,"INCOMING SETUP"}, /* when pbx_start */
1004 {MISDN_DIALING
,"DIALING"}, /* when pbx_start */
1005 {MISDN_PROGRESS
,"PROGRESS"}, /* when pbx_start */
1006 {MISDN_PROCEEDING
,"PROCEEDING"}, /* when pbx_start */
1007 {MISDN_CALLING
,"CALLING"}, /* when misdn_call is called */
1008 {MISDN_CALLING_ACKNOWLEDGE
,"CALLING_ACKNOWLEDGE"}, /* when misdn_call is called */
1009 {MISDN_ALERTING
,"ALERTING"}, /* when Alerting */
1010 {MISDN_BUSY
,"BUSY"}, /* when BUSY */
1011 {MISDN_CONNECTED
,"CONNECTED"}, /* when connected */
1012 {MISDN_PRECONNECTED
,"PRECONNECTED"}, /* when connected */
1013 {MISDN_DISCONNECTED
,"DISCONNECTED"}, /* when connected */
1014 {MISDN_RELEASED
,"RELEASED"}, /* when connected */
1015 {MISDN_BRIDGED
,"BRIDGED"}, /* when bridged */
1016 {MISDN_CLEANING
,"CLEANING"}, /* when hangup from * but we were connected before */
1017 {MISDN_HUNGUP_FROM_MISDN
,"HUNGUP_FROM_MISDN"}, /* when DISCONNECT/RELEASE/REL_COMP cam from misdn */
1018 {MISDN_HOLDED
,"HOLDED"}, /* when DISCONNECT/RELEASE/REL_COMP cam from misdn */
1019 {MISDN_HOLD_DISCONNECT
,"HOLD_DISCONNECT"}, /* when DISCONNECT/RELEASE/REL_COMP cam from misdn */
1020 {MISDN_HUNGUP_FROM_AST
,"HUNGUP_FROM_AST"} /* when DISCONNECT/RELEASE/REL_COMP came out of */
1024 static char *misdn_get_ch_state(struct chan_list
*p
)
1027 static char state
[8];
1029 if( !p
) return NULL
;
1031 for (i
=0; i
< sizeof(state_array
)/sizeof(struct state_struct
); i
++) {
1032 if ( state_array
[i
].state
== p
->state
) return state_array
[i
].txt
;
1035 sprintf(state
,"%d",p
->state
) ;
1042 static void reload_config(void)
1046 if (!g_config_initialized
) {
1047 ast_log(LOG_WARNING
, "chan_misdn is not initialized properly, still reloading ?\n");
1053 misdn_cfg_update_ptp();
1054 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE
, global_tracefile
, BUFFERSIZE
);
1055 misdn_cfg_get( 0, MISDN_GEN_DEBUG
, &cfg_debug
, sizeof(int));
1057 for (i
= 0; i
<= max_ports
; i
++) {
1058 misdn_debug
[i
] = cfg_debug
;
1059 misdn_debug_only
[i
] = 0;
1063 static int misdn_reload (int fd
, int argc
, char *argv
[])
1065 ast_cli(fd
, "Reloading mISDN Config\n");
1070 static void print_bc_info (int fd
, struct chan_list
* help
, struct misdn_bchannel
* bc
)
1072 struct ast_channel
*ast
=help
->ast
;
1074 "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
1076 bc
->pid
, bc
->port
, bc
->channel
,
1078 help
->originator
== ORG_AST
?"*":"I",
1079 ast
?ast
->exten
:NULL
,
1080 ast
?ast
->cid
.cid_num
:NULL
,
1082 ast
?ast
->context
:NULL
,
1083 misdn_get_ch_state(help
)
1085 if (misdn_debug
[bc
->port
] > 0)
1087 " --> astname: %s\n"
1088 " --> ch_l3id: %x\n"
1089 " --> ch_addr: %x\n"
1090 " --> bc_addr: %x\n"
1091 " --> bc_l3id: %x\n"
1092 " --> display: %s\n"
1093 " --> activated: %d\n"
1095 " --> capability: %s\n"
1097 " --> pipeline: %s\n"
1099 " --> echo_cancel: %d\n"
1101 " --> notone : rx %d tx:%d\n"
1102 " --> bc_hold: %d\n",
1111 bc_state2str(bc
->bc_state
),
1112 bearer2str(bc
->capability
),
1119 help
->norxtone
,help
->notxtone
,
1125 static int misdn_show_cls (int fd
, int argc
, char *argv
[])
1127 struct chan_list
*help
=cl_te
;
1129 ast_cli(fd
,"Chan List: %p\n",cl_te
);
1131 for (;help
; help
=help
->next
) {
1132 struct misdn_bchannel
*bc
=help
->bc
;
1133 struct ast_channel
*ast
=help
->ast
;
1134 if (misdn_debug
[0] > 2) ast_cli(fd
, "Bc:%p Ast:%p\n", bc
, ast
);
1136 print_bc_info(fd
, help
, bc
);
1138 if (help
->state
== MISDN_HOLDED
) {
1139 ast_cli(fd
, "ITS A HOLDED BC:\n");
1140 ast_cli(fd
, " --> l3_id: %x\n"
1141 " --> dad:%s oad:%s\n"
1142 " --> hold_port: %d\n"
1143 " --> hold_channel: %d\n"
1148 ,help
->hold_info
.port
1149 ,help
->hold_info
.channel
1152 ast_cli(fd
,"* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast
->exten
, ast
->cid
.cid_num
);
1157 misdn_dump_chanlist();
1161 static int misdn_show_cl (int fd
, int argc
, char *argv
[])
1163 struct chan_list
*help
=cl_te
;
1166 return RESULT_SHOWUSAGE
;
1168 for (;help
; help
=help
->next
) {
1169 struct misdn_bchannel
*bc
=help
->bc
;
1170 struct ast_channel
*ast
=help
->ast
;
1173 if (!strcasecmp(ast
->name
,argv
[3])) {
1174 print_bc_info(fd
, help
, bc
);
1187 static int misdn_set_tics (int fd
, int argc
, char *argv
[])
1190 return RESULT_SHOWUSAGE
;
1192 MAXTICS
=atoi(argv
[3]);
1197 static int misdn_show_stacks (int fd
, int argc
, char *argv
[])
1201 ast_cli(fd
, "BEGIN STACK_LIST:\n");
1203 for (port
=misdn_cfg_get_next_port(0); port
> 0;
1204 port
=misdn_cfg_get_next_port(port
)) {
1206 get_show_stack_details(port
,buf
);
1207 ast_cli(fd
," %s Debug:%d%s\n", buf
, misdn_debug
[port
], misdn_debug_only
[port
]?"(only)":"");
1214 static int misdn_show_ports_stats (int fd
, int argc
, char *argv
[])
1218 ast_cli(fd
, "Port\tin_calls\tout_calls\n");
1220 for (port
=misdn_cfg_get_next_port(0); port
> 0;
1221 port
=misdn_cfg_get_next_port(port
)) {
1222 ast_cli(fd
,"%d\t%d\t\t%d\n",port
,misdn_in_calls
[port
],misdn_out_calls
[port
]);
1231 static int misdn_show_port (int fd
, int argc
, char *argv
[])
1237 return RESULT_SHOWUSAGE
;
1239 port
= atoi(argv
[3]);
1241 ast_cli(fd
, "BEGIN STACK_LIST:\n");
1243 get_show_stack_details(port
,buf
);
1244 ast_cli(fd
," %s Debug:%d%s\n",buf
, misdn_debug
[port
], misdn_debug_only
[port
]?"(only)":"");
1250 static int misdn_send_cd (int fd
, int argc
, char *argv
[])
1256 return RESULT_SHOWUSAGE
;
1261 ast_cli(fd
, "Sending Calldeflection (%s) to %s\n",nr
, channame
);
1264 struct chan_list
*tmp
=get_chan_by_ast_name(channame
);
1267 ast_cli(fd
, "Sending CD with nr %s to %s failed: Channel does not exist.\n",nr
, channame
);
1270 if (strlen(nr
) >= 15) {
1271 ast_cli(fd
, "Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n",nr
, channame
);
1274 tmp
->bc
->fac_out
.Function
= Fac_CD
;
1275 strncpy((char *)tmp
->bc
->fac_out
.u
.CDeflection
.DeflectedToNumber
, nr
, sizeof(tmp
->bc
->fac_out
.u
.CDeflection
.DeflectedToNumber
));
1276 misdn_lib_send_event(tmp
->bc
, EVENT_FACILITY
);
1283 static int misdn_send_restart(int fd
, int argc
, char *argv
[])
1288 if ( (argc
< 4) || (argc
> 5) )
1289 return RESULT_SHOWUSAGE
;
1291 port
= atoi(argv
[3]);
1294 channel
= atoi(argv
[4]);
1295 misdn_lib_send_restart(port
, channel
);
1297 misdn_lib_send_restart(port
, -1 );
1302 static int misdn_send_digit (int fd
, int argc
, char *argv
[])
1308 return RESULT_SHOWUSAGE
;
1313 ast_cli(fd
, "Sending %s to %s\n",msg
, channame
);
1316 struct chan_list
*tmp
=get_chan_by_ast_name(channame
);
1319 ast_cli(fd
, "Sending %s to %s failed Channel does not exist\n",msg
, channame
);
1324 int msglen
= strlen(msg
);
1325 for (i
=0; i
<msglen
; i
++) {
1326 ast_cli(fd
, "Sending: %c\n",msg
[i
]);
1327 send_digit_to_chan(tmp
, msg
[i
]);
1328 /* res = ast_safe_sleep(tmp->ast, 250); */
1330 /* res = ast_waitfor(tmp->ast,100); */
1334 res
= ast_dtmf_stream(tmp
->ast
,NULL
,msg
,250);
1342 static int misdn_toggle_echocancel (int fd
, int argc
, char *argv
[])
1347 return RESULT_SHOWUSAGE
;
1351 ast_cli(fd
, "Toggling EchoCancel on %s\n", channame
);
1354 struct chan_list
*tmp
=get_chan_by_ast_name(channame
);
1357 ast_cli(fd
, "Toggling EchoCancel %s failed Channel does not exist\n", channame
);
1361 tmp
->toggle_ec
=tmp
->toggle_ec
?0:1;
1363 if (tmp
->toggle_ec
) {
1365 update_pipeline_config(tmp
->bc
);
1367 update_ec_config(tmp
->bc
);
1369 manager_ec_enable(tmp
->bc
);
1371 manager_ec_disable(tmp
->bc
);
1379 static int misdn_send_display (int fd
, int argc
, char *argv
[])
1385 return RESULT_SHOWUSAGE
;
1390 ast_cli(fd
, "Sending %s to %s\n",msg
, channame
);
1392 struct chan_list
*tmp
;
1393 tmp
=get_chan_by_ast_name(channame
);
1395 if (tmp
&& tmp
->bc
) {
1396 ast_copy_string(tmp
->bc
->display
, msg
, sizeof(tmp
->bc
->display
));
1397 misdn_lib_send_event(tmp
->bc
, EVENT_INFORMATION
);
1399 ast_cli(fd
,"No such channel %s\n",channame
);
1400 return RESULT_FAILURE
;
1404 return RESULT_SUCCESS
;
1407 static char *complete_ch_helper(const char *line
, const char *word
, int pos
, int state
, int rpos
)
1409 struct ast_channel
*c
;
1414 c
= ast_channel_walk_locked(NULL
);
1416 if (!strncasecmp(word
, c
->name
, strlen(word
))) {
1417 if (++which
> state
)
1420 ast_mutex_unlock(&c
->lock
);
1421 c
= ast_channel_walk_locked(c
);
1424 ret
= strdup(c
->name
);
1425 ast_mutex_unlock(&c
->lock
);
1431 static char *complete_ch(const char *line
, const char *word
, int pos
, int state
)
1433 return complete_ch_helper(line
, word
, pos
, state
, 3);
1436 static char *complete_debug_port (const char *line
, const char *word
, int pos
, int state
)
1442 case 4: if (*word
== 'p')
1443 return strdup("port");
1444 else if (*word
== 'o')
1445 return strdup("only");
1447 case 6: if (*word
== 'o')
1448 return strdup("only");
1454 static char *complete_show_config (const char *line
, const char *word
, int pos
, int state
)
1456 char buffer
[BUFFERSIZE
];
1457 enum misdn_cfg_elements elem
;
1458 int wordlen
= strlen(word
);
1463 case 3: if ((!strncmp(word
, "description", wordlen
)) && (++which
> state
))
1464 return strdup("description");
1465 if ((!strncmp(word
, "descriptions", wordlen
)) && (++which
> state
))
1466 return strdup("descriptions");
1467 if ((!strncmp(word
, "0", wordlen
)) && (++which
> state
))
1469 while ((port
= misdn_cfg_get_next_port(port
)) != -1) {
1470 snprintf(buffer
, sizeof(buffer
), "%d", port
);
1471 if ((!strncmp(word
, buffer
, wordlen
)) && (++which
> state
)) {
1472 return strdup(buffer
);
1477 if (strstr(line
, "description ")) {
1478 for (elem
= MISDN_CFG_FIRST
+ 1; elem
< MISDN_GEN_LAST
; ++elem
) {
1479 if ((elem
== MISDN_CFG_LAST
) || (elem
== MISDN_GEN_FIRST
))
1481 misdn_cfg_get_name(elem
, buffer
, BUFFERSIZE
);
1482 if (!wordlen
|| !strncmp(word
, buffer
, wordlen
)) {
1483 if (++which
> state
)
1484 return strdup(buffer
);
1487 } else if (strstr(line
, "descriptions ")) {
1488 if ((!wordlen
|| !strncmp(word
, "general", wordlen
)) && (++which
> state
))
1489 return strdup("general");
1490 if ((!wordlen
|| !strncmp(word
, "ports", wordlen
)) && (++which
> state
))
1491 return strdup("ports");
1498 static struct ast_cli_entry chan_misdn_clis
[] = {
1499 { {"misdn","send","calldeflect", NULL
}, misdn_send_cd
, "Sends CallDeflection to mISDN Channel",
1500 "Usage: misdn send calldeflect <channel> \"<nr>\" \n", complete_ch
},
1501 { {"misdn","send","digit", NULL
}, misdn_send_digit
, "Sends DTMF Digit to mISDN Channel",
1502 "Usage: misdn send digit <channel> \"<msg>\" \n"
1503 " Send <digit> to <channel> as DTMF Tone\n"
1504 " when channel is a mISDN channel\n", complete_ch
},
1505 { {"misdn","toggle","echocancel", NULL
}, misdn_toggle_echocancel
, "Toggles EchoCancel on mISDN Channel",
1506 "Usage: misdn toggle echocancel <channel>\n", complete_ch
},
1507 { {"misdn","send","display", NULL
}, misdn_send_display
, "Sends Text to mISDN Channel",
1508 "Usage: misdn send display <channel> \"<msg>\" \n"
1509 " Send <msg> to <channel> as Display Message\n"
1510 " when channel is a mISDN channel\n", complete_ch
},
1511 { {"misdn","show","config", NULL
}, misdn_show_config
, "Shows internal mISDN config, read from cfg-file",
1512 "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
1513 " Use 0 for <port> to only print the general config.\n", complete_show_config
},
1514 { {"misdn","reload", NULL
}, misdn_reload
, "Reloads internal mISDN config, read from cfg-file",
1515 "Usage: misdn reload\n" },
1516 { {"misdn","set","tics", NULL
}, misdn_set_tics
, "",
1518 { {"misdn","show","channels", NULL
}, misdn_show_cls
, "Shows internal mISDN chan_list",
1519 "Usage: misdn show channels\n" },
1520 { {"misdn","show","channel", NULL
}, misdn_show_cl
, "Shows internal mISDN chan_list",
1521 "Usage: misdn show channels\n", complete_ch
},
1522 { {"misdn","port","block", NULL
}, misdn_port_block
, "Blocks the given port",
1523 "Usage: misdn port block\n" },
1524 { {"misdn","port","unblock", NULL
}, misdn_port_unblock
, "Unblocks the given port",
1525 "Usage: misdn port unblock\n" },
1526 { {"misdn","restart","port", NULL
}, misdn_restart_port
, "Restarts the given port",
1527 "Usage: misdn restart port\n" },
1528 { {"misdn","restart","pid", NULL
}, misdn_restart_pid
, "Restarts the given pid",
1529 "Usage: misdn restart pid\n" },
1530 { {"misdn","send","restart", NULL
}, misdn_send_restart
,
1531 "Sends a restart for every bchannel on the given port",
1532 "Usage: misdn send restart <port>\n"},
1533 { {"misdn","port","up", NULL
}, misdn_port_up
, "Tries to establish L1 on the given port",
1534 "Usage: misdn port up <port>\n" },
1535 { {"misdn","port","down", NULL
}, misdn_port_down
, "Tries to deacivate the L1 on the given port",
1536 "Usage: misdn port down <port>\n" },
1537 { {"misdn","show","stacks", NULL
}, misdn_show_stacks
, "Shows internal mISDN stack_list",
1538 "Usage: misdn show stacks\n" },
1539 { {"misdn","show","ports","stats", NULL
}, misdn_show_ports_stats
, "Shows chan_misdns call statistics per port",
1540 "Usage: misdn show port stats\n" },
1541 { {"misdn","show","port", NULL
}, misdn_show_port
, "Shows detailed information for given port",
1542 "Usage: misdn show port <port>\n" },
1543 { {"misdn","set","debug", NULL
}, misdn_set_debug
, "Sets Debuglevel of chan_misdn",
1544 "Usage: misdn set debug <level> [only] | [port <port> [only]]\n", complete_debug_port
},
1545 { {"misdn","set","crypt","debug", NULL
}, misdn_set_crypt_debug
, "Sets CryptDebuglevel of chan_misdn, at the moment, level={1,2}",
1546 "Usage: misdn set crypt debug <level>\n" }
1549 static int update_config (struct chan_list
*ch
, int orig
)
1551 struct ast_channel
*ast
=ch
->ast
;
1552 struct misdn_bchannel
*bc
=ch
->bc
;
1558 ast_log(LOG_WARNING
, "Cannot configure without chanlist\n");
1564 if (! ast
|| ! bc
) {
1565 ast_log(LOG_WARNING
, "Cannot configure without ast || bc\n");
1571 chan_misdn_log(7,port
,"update_config: Getting Config\n");
1573 misdn_cfg_get( port
, MISDN_CFG_HDLC
, &hdlc
, sizeof(int));
1576 switch (bc
->capability
) {
1577 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED
:
1578 case INFO_CAPABILITY_DIGITAL_RESTRICTED
:
1579 chan_misdn_log(1,bc
->port
," --> CONF HDLC\n");
1586 misdn_cfg_get( port
, MISDN_CFG_PRES
, &pres
, sizeof(int));
1587 misdn_cfg_get( port
, MISDN_CFG_SCREEN
, &screen
, sizeof(int));
1588 chan_misdn_log(2,port
," --> pres: %d screen: %d\n",pres
, screen
);
1590 if ( (pres
+ screen
) < 0 ) {
1592 chan_misdn_log(2,port
," --> pres: %x\n", ast
->cid
.cid_pres
);
1594 switch (ast
->cid
.cid_pres
& 0x60){
1596 case AST_PRES_RESTRICTED
:
1598 chan_misdn_log(2, port
, " --> PRES: Restricted (0x1)\n");
1602 case AST_PRES_UNAVAILABLE
:
1604 chan_misdn_log(2, port
, " --> PRES: Unavailable (0x2)\n");
1609 chan_misdn_log(2, port
, " --> PRES: Allowed (0x0)\n");
1612 switch (ast
->cid
.cid_pres
& 0x3){
1614 case AST_PRES_USER_NUMBER_UNSCREENED
:
1616 chan_misdn_log(2, port
, " --> SCREEN: Unscreened (0x0)\n");
1619 case AST_PRES_USER_NUMBER_PASSED_SCREEN
:
1621 chan_misdn_log(2, port
, " --> SCREEN: Passed Screen (0x1)\n");
1623 case AST_PRES_USER_NUMBER_FAILED_SCREEN
:
1625 chan_misdn_log(2, port
, " --> SCREEN: Failed Screen (0x2)\n");
1628 case AST_PRES_NETWORK_NUMBER
:
1630 chan_misdn_log(2, port
, " --> SCREEN: Network Nr. (0x3)\n");
1635 chan_misdn_log(2, port
, " --> SCREEN: Unscreened (0x0)\n");
1651 static void config_jitterbuffer(struct chan_list
*ch
)
1653 struct misdn_bchannel
*bc
=ch
->bc
;
1654 int len
=ch
->jb_len
, threshold
=ch
->jb_upper_threshold
;
1656 chan_misdn_log(5,bc
->port
, "config_jb: Called\n");
1659 chan_misdn_log(1,bc
->port
, "config_jb: Deactivating Jitterbuffer\n");
1663 if (len
<=100 || len
> 8000) {
1664 chan_misdn_log(0,bc
->port
,"config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
1668 if ( threshold
> len
) {
1669 chan_misdn_log(0,bc
->port
,"config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
1673 cb_log(0,bc
->port
,"config_jb: We've got a Jitterbuffer Already on this port.\n");
1674 misdn_jb_destroy(ch
->jb
);
1678 ch
->jb
=misdn_jb_init(len
, threshold
);
1686 void debug_numplan(int port
, int numplan
, char *type
)
1689 case NUMPLAN_INTERNATIONAL
:
1690 chan_misdn_log(2, port
, " --> %s: International\n",type
);
1692 case NUMPLAN_NATIONAL
:
1693 chan_misdn_log(2, port
, " --> %s: National\n",type
);
1695 case NUMPLAN_SUBSCRIBER
:
1696 chan_misdn_log(2, port
, " --> %s: Subscriber\n",type
);
1698 case NUMPLAN_UNKNOWN
:
1699 chan_misdn_log(2, port
, " --> %s: Unknown\n",type
);
1701 /* Maybe we should cut off the prefix if present ? */
1703 chan_misdn_log(0, port
, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
1712 static int update_pipeline_config(struct misdn_bchannel
*bc
)
1716 misdn_cfg_get(bc
->port
, MISDN_CFG_PIPELINE
, bc
->pipeline
, sizeof(bc
->pipeline
));
1721 misdn_cfg_get(bc
->port
, MISDN_CFG_ECHOCANCEL
, &ec
, sizeof(int));
1723 snprintf(bc
->pipeline
, sizeof(bc
->pipeline
) - 1, "mg2ec");
1725 snprintf(bc
->pipeline
, sizeof(bc
->pipeline
) - 1, "mg2ec(deftaps=%d)", ec
);
1730 static int update_ec_config(struct misdn_bchannel
*bc
)
1735 misdn_cfg_get( port
, MISDN_CFG_ECHOCANCEL
, &ec
, sizeof(int));
1739 } else if ( ec
> 1 ) {
1749 static int read_config(struct chan_list
*ch
, int orig
)
1751 struct ast_channel
*ast
;
1752 struct misdn_bchannel
*bc
;
1754 char lang
[BUFFERSIZE
+1];
1755 char localmusicclass
[BUFFERSIZE
+1];
1756 char faxdetect
[BUFFERSIZE
+1];
1760 ast_log(LOG_WARNING
, "Cannot configure without chanlist\n");
1766 if (! ast
|| ! bc
) {
1767 ast_log(LOG_WARNING
, "Cannot configure without ast || bc\n");
1774 chan_misdn_log(1,port
,"read_config: Getting Config\n");
1776 misdn_cfg_get( port
, MISDN_CFG_LANGUAGE
, lang
, BUFFERSIZE
);
1777 ast_string_field_set(ast
, language
, lang
);
1779 misdn_cfg_get( port
, MISDN_CFG_MUSICCLASS
, localmusicclass
, BUFFERSIZE
);
1780 ast_string_field_set(ast
, musicclass
, localmusicclass
);
1783 misdn_cfg_get( port
, MISDN_CFG_TXGAIN
, &bc
->txgain
, sizeof(int));
1784 misdn_cfg_get( port
, MISDN_CFG_RXGAIN
, &bc
->rxgain
, sizeof(int));
1786 misdn_cfg_get( port
, MISDN_CFG_INCOMING_EARLY_AUDIO
, &ch
->incoming_early_audio
, sizeof(int));
1788 misdn_cfg_get( port
, MISDN_CFG_SENDDTMF
, &bc
->send_dtmf
, sizeof(int));
1790 misdn_cfg_get( port
, MISDN_CFG_ASTDTMF
, &ch
->ast_dsp
, sizeof(int));
1796 misdn_cfg_get( port
, MISDN_CFG_NEED_MORE_INFOS
, &bc
->need_more_infos
, sizeof(int));
1797 misdn_cfg_get( port
, MISDN_CFG_NTTIMEOUT
, &ch
->nttimeout
, sizeof(int));
1799 misdn_cfg_get( port
, MISDN_CFG_NOAUTORESPOND_ON_SETUP
, &ch
->noautorespond_on_setup
, sizeof(int));
1801 misdn_cfg_get( port
, MISDN_CFG_FAR_ALERTING
, &ch
->far_alerting
, sizeof(int));
1803 misdn_cfg_get( port
, MISDN_CFG_ALLOWED_BEARERS
, &ch
->allowed_bearers
, BUFFERSIZE
);
1805 misdn_cfg_get( port
, MISDN_CFG_FAXDETECT
, faxdetect
, BUFFERSIZE
);
1807 misdn_cfg_get( port
, MISDN_CFG_HDLC
, &hdlc
, sizeof(int));
1810 switch (bc
->capability
) {
1811 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED
:
1812 case INFO_CAPABILITY_DIGITAL_RESTRICTED
:
1813 chan_misdn_log(1,bc
->port
," --> CONF HDLC\n");
1819 /*Initialize new Jitterbuffer*/
1821 misdn_cfg_get( port
, MISDN_CFG_JITTERBUFFER
, &ch
->jb_len
, sizeof(int));
1822 misdn_cfg_get( port
, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD
, &ch
->jb_upper_threshold
, sizeof(int));
1824 config_jitterbuffer(ch
);
1827 misdn_cfg_get( bc
->port
, MISDN_CFG_CONTEXT
, ch
->context
, sizeof(ch
->context
));
1829 ast_copy_string (ast
->context
,ch
->context
,sizeof(ast
->context
));
1832 update_pipeline_config(bc
);
1834 update_ec_config(bc
);
1840 misdn_cfg_get( bc
->port
, MISDN_CFG_EARLY_BCONNECT
, &eb3
, sizeof(int));
1841 bc
->early_bconnect
=eb3
;
1850 misdn_cfg_get(port
, MISDN_CFG_PICKUPGROUP
, &pg
, sizeof(pg
));
1851 misdn_cfg_get(port
, MISDN_CFG_CALLGROUP
, &cg
, sizeof(cg
));
1853 chan_misdn_log(5, port
, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf
,sizeof(buf
),cg
),ast_print_group(buf
,sizeof(buf
),pg
));
1854 ast
->pickupgroup
=pg
;
1858 if ( orig
== ORG_AST
) {
1859 misdn_cfg_get( port
, MISDN_CFG_TE_CHOOSE_CHANNEL
, &(bc
->te_choose_channel
), sizeof(int));
1861 if (strstr(faxdetect
, "outgoing") || strstr(faxdetect
, "both")) {
1862 if (strstr(faxdetect
, "nojump"))
1869 char callerid
[BUFFERSIZE
+1];
1870 misdn_cfg_get( port
, MISDN_CFG_CALLERID
, callerid
, BUFFERSIZE
);
1871 if ( ! ast_strlen_zero(callerid
) ) {
1872 chan_misdn_log(1, port
, " --> * Setting Cid to %s\n", callerid
);
1874 int l
= sizeof(bc
->oad
);
1875 strncpy(bc
->oad
,callerid
, l
);
1882 misdn_cfg_get( port
, MISDN_CFG_DIALPLAN
, &bc
->dnumplan
, sizeof(int));
1883 misdn_cfg_get( port
, MISDN_CFG_LOCALDIALPLAN
, &bc
->onumplan
, sizeof(int));
1884 misdn_cfg_get( port
, MISDN_CFG_CPNDIALPLAN
, &bc
->cpnnumplan
, sizeof(int));
1885 debug_numplan(port
, bc
->dnumplan
,"TON");
1886 debug_numplan(port
, bc
->onumplan
,"LTON");
1887 debug_numplan(port
, bc
->cpnnumplan
,"CTON");
1890 ch
->overlap_dial
= 0;
1891 } else { /** ORIGINATOR MISDN **/
1892 char prefix
[BUFFERSIZE
+1]="";
1893 if (strstr(faxdetect
, "incoming") || strstr(faxdetect
, "both")) {
1894 if (strstr(faxdetect
, "nojump"))
1900 misdn_cfg_get( port
, MISDN_CFG_CPNDIALPLAN
, &bc
->cpnnumplan
, sizeof(int));
1901 debug_numplan(port
, bc
->cpnnumplan
,"CTON");
1903 switch( bc
->onumplan
) {
1904 case NUMPLAN_INTERNATIONAL
:
1905 misdn_cfg_get( bc
->port
, MISDN_CFG_INTERNATPREFIX
, prefix
, BUFFERSIZE
);
1908 case NUMPLAN_NATIONAL
:
1909 misdn_cfg_get( bc
->port
, MISDN_CFG_NATPREFIX
, prefix
, BUFFERSIZE
);
1916 int l
= strlen(prefix
) + strlen(bc
->oad
);
1917 char *tmp
= alloca(l
+1);
1919 strcat(tmp
,bc
->oad
);
1920 strcpy(bc
->oad
,tmp
);
1923 if (!ast_strlen_zero(bc
->dad
)) {
1924 ast_copy_string(bc
->orig_dad
,bc
->dad
, sizeof(bc
->orig_dad
));
1927 if ( ast_strlen_zero(bc
->dad
) && !ast_strlen_zero(bc
->keypad
)) {
1928 ast_copy_string(bc
->dad
,bc
->keypad
, sizeof(bc
->dad
));
1933 switch( bc
->dnumplan
) {
1934 case NUMPLAN_INTERNATIONAL
:
1935 misdn_cfg_get( bc
->port
, MISDN_CFG_INTERNATPREFIX
, prefix
, BUFFERSIZE
);
1937 case NUMPLAN_NATIONAL
:
1938 misdn_cfg_get( bc
->port
, MISDN_CFG_NATPREFIX
, prefix
, BUFFERSIZE
);
1945 int l
= strlen(prefix
) + strlen(bc
->dad
);
1946 char *tmp
= alloca(l
+1);
1948 strcat(tmp
,bc
->dad
);
1949 strcpy(bc
->dad
,tmp
);
1952 if ( strcmp(bc
->dad
,ast
->exten
)) {
1953 ast_copy_string(ast
->exten
, bc
->dad
, sizeof(ast
->exten
));
1956 ast_set_callerid(ast
, bc
->oad
, NULL
, bc
->oad
);
1958 if ( !ast_strlen_zero(bc
->rad
) ) {
1959 if (ast
->cid
.cid_rdnis
)
1960 free(ast
->cid
.cid_rdnis
);
1961 ast
->cid
.cid_rdnis
= strdup(bc
->rad
);
1964 misdn_cfg_get(bc
->port
, MISDN_CFG_OVERLAP_DIAL
, &ch
->overlap_dial
, sizeof(ch
->overlap_dial
));
1965 ast_mutex_init(&ch
->overlap_tv_lock
);
1966 } /* ORIG MISDN END */
1968 ch
->overlap_dial_task
= -1;
1970 if (ch
->faxdetect
|| ch
->ast_dsp
) {
1971 misdn_cfg_get( port
, MISDN_CFG_FAXDETECT_TIMEOUT
, &ch
->faxdetect_timeout
, sizeof(ch
->faxdetect_timeout
));
1973 ch
->dsp
= ast_dsp_new();
1976 ast_dsp_set_features(ch
->dsp
, DSP_FEATURE_DTMF_DETECT
| DSP_FEATURE_FAX_DETECT
);
1978 ast_dsp_set_features(ch
->dsp
, DSP_FEATURE_DTMF_DETECT
);
1981 ch
->trans
=ast_translator_build_path(AST_FORMAT_SLINEAR
, AST_FORMAT_ALAW
);
1984 /* AOCD initialization */
1985 bc
->AOCDtype
= Fac_None
;
1991 /*****************************/
1992 /*** AST Indications Start ***/
1993 /*****************************/
1995 static int misdn_call(struct ast_channel
*ast
, char *dest
, int timeout
)
2000 struct chan_list
*ch
=MISDN_ASTERISK_TECH_PVT(ast
);
2001 struct misdn_bchannel
*newbc
;
2002 char *opts
=NULL
, *ext
;
2006 strncpy(dest_cp
,dest
,sizeof(dest_cp
)-1);
2007 dest_cp
[sizeof(dest_cp
)]=0;
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 withut having bchannel Object\n");
2232 switch (p
->state
) {
2240 l
= sizeof(bc
->infos_pending
);
2241 strncat(bc
->infos_pending
,buf
,l
);
2242 bc
->infos_pending
[l
-1] = 0;
2245 case MISDN_CALLING_ACKNOWLEDGE
:
2247 bc
->info_dad
[0]=digit
;
2251 int l
= sizeof(bc
->dad
);
2252 strncat(bc
->dad
,bc
->info_dad
, l
- strlen(bc
->dad
));
2256 int l
= sizeof(p
->ast
->exten
);
2257 strncpy(p
->ast
->exten
, bc
->dad
, l
);
2258 p
->ast
->exten
[l
-1] = 0;
2261 misdn_lib_send_event( bc
, EVENT_INFORMATION
);
2266 /* Do not send Digits in CONNECTED State, when
2267 * the other side is too mISDN. */
2271 if ( bc
->send_dtmf
)
2272 send_digit_to_chan(p
,digit
);
2280 static int misdn_fixup(struct ast_channel
*oldast
, struct ast_channel
*ast
)
2282 struct chan_list
*p
;
2284 if (!ast
|| ! (p
=MISDN_ASTERISK_TECH_PVT(ast
) )) return -1;
2286 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
);
2295 static int misdn_indication(struct ast_channel
*ast
, int cond
, const void *data
, size_t datalen
)
2297 struct chan_list
*p
;
2300 if (!ast
|| ! (p
=MISDN_ASTERISK_TECH_PVT(ast
))) {
2301 ast_log(LOG_WARNING
, "Returnded -1 in misdn_indication\n");
2306 chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast
->exten
);
2307 ast_log(LOG_WARNING
, "Private Pointer but no bc ?\n");
2311 chan_misdn_log(5, p
->bc
->port
, "* IND : Indication [%d] from %s\n",cond
, ast
->exten
);
2314 case AST_CONTROL_BUSY
:
2315 chan_misdn_log(1, p
->bc
->port
, "* IND :\tbusy pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2316 ast_setstate(ast
,AST_STATE_BUSY
);
2318 p
->bc
->out_cause
=17;
2319 if (p
->state
!= MISDN_CONNECTED
) {
2321 misdn_lib_send_event( p
->bc
, EVENT_DISCONNECT
);
2323 chan_misdn_log(-1, p
->bc
->port
, " --> !! Got Busy in Connected State !?! ast:%s\n", ast
->name
);
2327 case AST_CONTROL_RING
:
2328 chan_misdn_log(1, p
->bc
->port
, "* IND :\tring pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2332 case AST_CONTROL_RINGING
:
2333 chan_misdn_log(1, p
->bc
->port
, "* IND :\tringing pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2335 case MISDN_ALERTING
:
2336 chan_misdn_log(2, p
->bc
->port
, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoreing it\n",p
->bc
?p
->bc
->pid
:-1);
2338 case MISDN_CONNECTED
:
2339 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);
2343 p
->state
=MISDN_ALERTING
;
2344 chan_misdn_log(2, p
->bc
->port
, " --> * IND :\tringing pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2345 misdn_lib_send_event( p
->bc
, EVENT_ALERTING
);
2347 if (p
->other_ch
&& p
->other_ch
->bc
) {
2348 if (misdn_inband_avail(p
->other_ch
->bc
)) {
2349 chan_misdn_log(2,p
->bc
->port
, " --> other End is mISDN and has inband info available\n");
2353 if (!p
->other_ch
->bc
->nt
) {
2354 chan_misdn_log(2,p
->bc
->port
, " --> other End is mISDN TE so it has inband info for sure (?)\n");
2359 chan_misdn_log(3, p
->bc
->port
, " --> * SEND: State Ring pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2360 ast_setstate(ast
,AST_STATE_RINGING
);
2362 if ( !p
->bc
->nt
&& (p
->originator
==ORG_MISDN
) && !p
->incoming_early_audio
)
2363 chan_misdn_log(2,p
->bc
->port
, " --> incoming_early_audio off\n");
2368 case AST_CONTROL_ANSWER
:
2369 chan_misdn_log(1, p
->bc
->port
, " --> * IND :\tanswer pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2372 case AST_CONTROL_TAKEOFFHOOK
:
2373 chan_misdn_log(1, p
->bc
->port
, " --> *\ttakeoffhook pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2376 case AST_CONTROL_OFFHOOK
:
2377 chan_misdn_log(1, p
->bc
->port
, " --> *\toffhook pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2380 case AST_CONTROL_FLASH
:
2381 chan_misdn_log(1, p
->bc
->port
, " --> *\tflash pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2383 case AST_CONTROL_PROGRESS
:
2384 chan_misdn_log(1, p
->bc
->port
, " --> * IND :\tprogress pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2385 misdn_lib_send_event( p
->bc
, EVENT_PROGRESS
);
2387 case AST_CONTROL_PROCEEDING
:
2388 chan_misdn_log(1, p
->bc
->port
, " --> * IND :\tproceeding pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2389 misdn_lib_send_event( p
->bc
, EVENT_PROCEEDING
);
2391 case AST_CONTROL_CONGESTION
:
2392 chan_misdn_log(1, p
->bc
->port
, " --> * IND :\tcongestion pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2394 p
->bc
->out_cause
=42;
2396 misdn_lib_send_event( p
->bc
, EVENT_DISCONNECT
);
2399 hanguptone_indicate(p
);
2403 chan_misdn_log(1, p
->bc
->port
, " --> * IND :\t-1! (stop indication) pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2407 if (p
->state
== MISDN_CONNECTED
)
2412 case AST_CONTROL_HOLD
:
2413 ast_moh_start(ast
,data
,ast
->musicclass
);
2414 chan_misdn_log(1, p
->bc
->port
, " --> *\tHOLD pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2416 case AST_CONTROL_UNHOLD
:
2418 chan_misdn_log(1, p
->bc
->port
, " --> *\tUNHOLD pid:%d\n",p
->bc
?p
->bc
->pid
:-1);
2421 chan_misdn_log(1, p
->bc
->port
, " --> * Unknown Indication:%d pid:%d\n",cond
,p
->bc
?p
->bc
->pid
:-1);
2427 static int misdn_hangup(struct ast_channel
*ast
)
2429 struct chan_list
*p
;
2430 struct misdn_bchannel
*bc
=NULL
;
2432 ast_log(LOG_DEBUG
, "misdn_hangup(%s)\n", ast
->name
);
2434 if (!ast
|| ! (p
=MISDN_ASTERISK_TECH_PVT(ast
) ) ) return -1;
2437 chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
2444 const char *tmp
=pbx_builtin_getvar_helper(ast
,"MISDN_USERUSER");
2446 ast_log(LOG_NOTICE
, "MISDN_USERUSER: %s\n", tmp
);
2447 strcpy(bc
->uu
, tmp
);
2448 bc
->uulen
=strlen(bc
->uu
);
2452 MISDN_ASTERISK_TECH_PVT(ast
)=NULL
;
2455 if (ast
->_state
== AST_STATE_RESERVED
||
2456 p
->state
== MISDN_NOTHING
||
2457 p
->state
== MISDN_HOLDED
||
2458 p
->state
== MISDN_HOLD_DISCONNECT
) {
2461 /* between request and call */
2462 ast_log(LOG_DEBUG
, "State Reserved (or nothing) => chanIsAvail\n");
2463 MISDN_ASTERISK_TECH_PVT(ast
)=NULL
;
2465 ast_mutex_lock(&release_lock
);
2466 cl_dequeue_chan(&cl_te
, p
);
2470 ast_mutex_unlock(&release_lock
);
2473 misdn_lib_release(bc
);
2479 ast_log(LOG_WARNING
,"Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p
), p
->l3id
);
2485 p
->need_queue_hangup
=0;
2494 const char *varcause
=NULL
;
2495 bc
->out_cause
=ast
->hangupcause
?ast
->hangupcause
:16;
2497 if ( (varcause
=pbx_builtin_getvar_helper(ast
, "HANGUPCAUSE")) ||
2498 (varcause
=pbx_builtin_getvar_helper(ast
, "PRI_CAUSE"))) {
2499 int tmpcause
=atoi(varcause
);
2500 bc
->out_cause
=tmpcause
?tmpcause
:16;
2503 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
));
2504 chan_misdn_log(3, bc
->port
, " --> l3id:%x\n",p
->l3id
);
2505 chan_misdn_log(3, bc
->port
, " --> cause:%d\n",bc
->cause
);
2506 chan_misdn_log(2, bc
->port
, " --> out_cause:%d\n",bc
->out_cause
);
2507 chan_misdn_log(2, bc
->port
, " --> state:%s\n", misdn_get_ch_state(p
));
2511 case MISDN_INCOMING_SETUP
:
2512 /* This is the only place in misdn_hangup, where we
2513 * can call release_chan, else it might create lot's of trouble
2515 ast_log(LOG_NOTICE
, "release channel, in CALLING/INCOMING_SETUP state.. no other events happened\n");
2518 p
->state
=MISDN_CLEANING
;
2519 if (bc
->need_release_complete
)
2520 misdn_lib_send_event( bc
, EVENT_RELEASE_COMPLETE
);
2525 hanguptone_indicate(p
);
2527 if (bc
->need_disconnect
)
2528 misdn_lib_send_event( bc
, EVENT_DISCONNECT
);
2531 case MISDN_CALLING_ACKNOWLEDGE
:
2533 hanguptone_indicate(p
);
2535 if (bc
->need_disconnect
)
2536 misdn_lib_send_event( bc
, EVENT_DISCONNECT
);
2539 case MISDN_ALERTING
:
2540 case MISDN_PROGRESS
:
2541 case MISDN_PROCEEDING
:
2542 if (p
->originator
!= ORG_AST
)
2543 hanguptone_indicate(p
);
2545 /*p->state=MISDN_CLEANING;*/
2546 if (bc
->need_disconnect
)
2547 misdn_lib_send_event( bc
, EVENT_DISCONNECT
);
2549 case MISDN_CONNECTED
:
2550 case MISDN_PRECONNECTED
:
2551 /* Alerting or Disconect */
2554 hanguptone_indicate(p
);
2555 p
->bc
->progress_indicator
=8;
2557 if (bc
->need_disconnect
)
2558 misdn_lib_send_event( bc
, EVENT_DISCONNECT
);
2560 /*p->state=MISDN_CLEANING;*/
2562 case MISDN_DISCONNECTED
:
2563 if (bc
->need_release
)
2564 misdn_lib_send_event( bc
, EVENT_RELEASE
);
2565 p
->state
=MISDN_CLEANING
; /* MISDN_HUNGUP_FROM_AST; */
2568 case MISDN_RELEASED
:
2569 case MISDN_CLEANING
:
2570 p
->state
=MISDN_CLEANING
;
2576 case MISDN_HOLD_DISCONNECT
:
2577 /* need to send release here */
2578 chan_misdn_log(1, bc
->port
, " --> cause %d\n",bc
->cause
);
2579 chan_misdn_log(1, bc
->port
, " --> out_cause %d\n",bc
->out_cause
);
2582 if (bc
->need_release
)
2583 misdn_lib_send_event(bc
,EVENT_RELEASE
);
2584 p
->state
=MISDN_CLEANING
;
2589 if (bc
->need_release
)
2590 misdn_lib_send_event(bc
, EVENT_RELEASE
);
2591 p
->state
=MISDN_CLEANING
;
2593 if (bc
->need_disconnect
)
2594 misdn_lib_send_event(bc
, EVENT_DISCONNECT
);
2598 p
->state
=MISDN_CLEANING
;
2603 chan_misdn_log(3, bc
->port
, " --> Channel: %s hanguped new state:%s\n",ast
->name
,misdn_get_ch_state(p
));
2609 static struct ast_frame
*process_ast_dsp(struct chan_list
*tmp
, struct ast_frame
*frame
)
2611 struct ast_frame
*f
,*f2
;
2614 f2
= ast_translate(tmp
->trans
, frame
, 0);
2615 f
= ast_dsp_process(tmp
->ast
, tmp
->dsp
, f2
);
2617 chan_misdn_log(0, tmp
->bc
->port
, "No T-Path found\n");
2622 if (!f
|| (f
->frametype
!= AST_FRAME_DTMF
))
2625 ast_log(LOG_DEBUG
, "Detected inband DTMF digit: %c\n", f
->subclass
);
2627 if (tmp
->faxdetect
&& (f
->subclass
== 'f')) {
2628 /* Fax tone -- Handle and return NULL */
2629 if (!tmp
->faxhandled
) {
2630 struct ast_channel
*ast
= tmp
->ast
;
2632 chan_misdn_log(0, tmp
->bc
->port
, "Fax detected, preparing %s for fax transfer.\n", ast
->name
);
2633 tmp
->bc
->rxgain
= 0;
2634 isdn_lib_update_rxgain(tmp
->bc
);
2635 tmp
->bc
->txgain
= 0;
2636 isdn_lib_update_txgain(tmp
->bc
);
2638 *tmp
->bc
->pipeline
= 0;
2640 tmp
->bc
->ec_enable
= 0;
2642 isdn_lib_update_ec(tmp
->bc
);
2643 isdn_lib_stop_dtmf(tmp
->bc
);
2644 switch (tmp
->faxdetect
) {
2646 if (strcmp(ast
->exten
, "fax")) {
2648 char context_tmp
[BUFFERSIZE
];
2649 misdn_cfg_get(tmp
->bc
->port
, MISDN_CFG_FAXDETECT_CONTEXT
, &context_tmp
, sizeof(context_tmp
));
2650 context
= ast_strlen_zero(context_tmp
) ? (ast_strlen_zero(ast
->macrocontext
) ? ast
->context
: ast
->macrocontext
) : context_tmp
;
2651 if (ast_exists_extension(ast
, context
, "fax", 1, ast
->cid
.cid_num
)) {
2652 if (option_verbose
> 2)
2653 ast_verbose(VERBOSE_PREFIX_3
"Redirecting %s to fax extension (context:%s)\n", ast
->name
, context
);
2654 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
2655 pbx_builtin_setvar_helper(ast
,"FAXEXTEN",ast
->exten
);
2656 if (ast_async_goto(ast
, context
, "fax", 1))
2657 ast_log(LOG_WARNING
, "Failed to async goto '%s' into fax of '%s'\n", ast
->name
, context
);
2659 ast_log(LOG_NOTICE
, "Fax detected, but no fax extension ctx:%s exten:%s\n", context
, ast
->exten
);
2661 ast_log(LOG_DEBUG
, "Already in a fax extension, not redirecting\n");
2664 ast_verbose(VERBOSE_PREFIX_3
"Not redirecting %s to fax extension, nojump is set.\n", ast
->name
);
2668 ast_log(LOG_DEBUG
, "Fax already handled\n");
2671 if (tmp
->ast_dsp
&& (f
->subclass
!= 'f')) {
2672 chan_misdn_log(2, tmp
->bc
->port
, " --> * SEND: DTMF (AST_DSP) :%c\n", f
->subclass
);
2679 static struct ast_frame
*misdn_read(struct ast_channel
*ast
)
2681 struct chan_list
*tmp
;
2687 chan_misdn_log(1,0,"misdn_read called without ast\n");
2690 if (!(tmp
=MISDN_ASTERISK_TECH_PVT(ast
))) {
2691 chan_misdn_log(1,0,"misdn_read called without ast->pvt\n");
2695 if (!tmp
->bc
&& !(tmp
->state
==MISDN_HOLDED
)) {
2696 chan_misdn_log(1,0,"misdn_read called without bc\n");
2704 FD_SET(tmp
->pipe
[0],&rrfs
);
2706 t
=select(FD_SETSIZE
,&rrfs
,NULL
, NULL
,&tv
);
2709 chan_misdn_log(3, tmp
->bc
->port
, "read Select Timed out\n");
2714 chan_misdn_log(-1, tmp
->bc
->port
, "Select Error (err=%s)\n",strerror(errno
));
2718 if (FD_ISSET(tmp
->pipe
[0],&rrfs
)) {
2719 len
=read(tmp
->pipe
[0],tmp
->ast_rd_buf
,sizeof(tmp
->ast_rd_buf
));
2722 /* we hangup here, since our pipe is closed */
2723 chan_misdn_log(2,tmp
->bc
->port
,"misdn_read: Pipe closed, hanging up\n");
2731 tmp
->frame
.frametype
= AST_FRAME_VOICE
;
2732 tmp
->frame
.subclass
= AST_FORMAT_ALAW
;
2733 tmp
->frame
.datalen
= len
;
2734 tmp
->frame
.samples
= len
;
2735 tmp
->frame
.mallocd
= 0;
2736 tmp
->frame
.offset
= 0;
2737 tmp
->frame
.delivery
= ast_tv(0,0) ;
2738 tmp
->frame
.src
= NULL
;
2739 tmp
->frame
.data
= tmp
->ast_rd_buf
;
2741 if (tmp
->faxdetect
&& !tmp
->faxhandled
) {
2742 if (tmp
->faxdetect_timeout
) {
2743 if (ast_tvzero(tmp
->faxdetect_tv
)) {
2744 tmp
->faxdetect_tv
= ast_tvnow();
2745 chan_misdn_log(2,tmp
->bc
->port
,"faxdetect: starting detection with timeout: %ds ...\n", tmp
->faxdetect_timeout
);
2746 return process_ast_dsp(tmp
, &tmp
->frame
);
2748 struct timeval tv_now
= ast_tvnow();
2749 int diff
= ast_tvdiff_ms(tv_now
, tmp
->faxdetect_tv
);
2750 if (diff
<= (tmp
->faxdetect_timeout
* 1000)) {
2751 chan_misdn_log(5,tmp
->bc
->port
,"faxdetect: detecting ...\n");
2752 return process_ast_dsp(tmp
, &tmp
->frame
);
2754 chan_misdn_log(2,tmp
->bc
->port
,"faxdetect: stopping detection (time ran out) ...\n");
2760 chan_misdn_log(5,tmp
->bc
->port
,"faxdetect: detecting ... (no timeout)\n");
2761 return process_ast_dsp(tmp
, &tmp
->frame
);
2765 return process_ast_dsp(tmp
, &tmp
->frame
);
2772 static int misdn_write(struct ast_channel
*ast
, struct ast_frame
*frame
)
2774 struct chan_list
*ch
;
2777 if (!ast
|| ! (ch
=MISDN_ASTERISK_TECH_PVT(ast
)) ) return -1;
2779 if (ch
->state
== MISDN_HOLDED
) {
2780 chan_misdn_log(7, 0, "misdn_write: Returning because holded\n");
2785 ast_log(LOG_WARNING
, "private but no bc\n");
2790 chan_misdn_log(7, ch
->bc
->port
, "misdn_write: Returning because notxone\n");
2795 if ( !frame
->subclass
) {
2796 chan_misdn_log(4, ch
->bc
->port
, "misdn_write: * prods us\n");
2800 if ( !(frame
->subclass
& prefformat
)) {
2802 chan_misdn_log(-1, ch
->bc
->port
, "Got Unsupported Frame with Format:%d\n", frame
->subclass
);
2807 if ( !frame
->samples
) {
2808 chan_misdn_log(4, ch
->bc
->port
, "misdn_write: zero write\n");
2810 if (!strcmp(frame
->src
,"ast_prod")) {
2811 chan_misdn_log(1, ch
->bc
->port
, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch
));
2814 chan_misdn_log(4,ch
->bc
->port
,"Starting Playtones\n");
2815 misdn_lib_tone_generator_start(ch
->bc
);
2823 if ( ! ch
->bc
->addr
) {
2824 chan_misdn_log(8, ch
->bc
->port
, "misdn_write: no addr for bc dropping:%d\n", frame
->samples
);
2830 int i
, max
=5>frame
->samples
?frame
->samples
:5;
2832 printf("write2mISDN %p %d bytes: ", p
, frame
->samples
);
2834 for (i
=0; i
< max
; i
++) printf("%2.2x ",((char*) frame
->data
)[i
]);
2840 switch (ch
->bc
->bc_state
) {
2841 case BCHAN_ACTIVATED
:
2845 if (!ch
->dropped_frame_cnt
)
2846 chan_misdn_log(5, ch
->bc
->port
, "BC not active (nor bridged) droping: %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
);
2848 ch
->dropped_frame_cnt
++;
2849 if (ch
->dropped_frame_cnt
> 100) {
2850 ch
->dropped_frame_cnt
=0;
2851 chan_misdn_log(5, ch
->bc
->port
, "BC not active (nor bridged) droping: %d frames addr:%x dropped > 100 frames!\n",frame
->samples
,ch
->bc
->addr
);
2858 chan_misdn_log(9, ch
->bc
->port
, "Sending :%d bytes 2 MISDN\n",frame
->samples
);
2859 if ( !ch
->bc
->nojitter
&& misdn_cap_is_speech(ch
->bc
->capability
) ) {
2860 /* Buffered Transmit (triggert by read from isdn side)*/
2861 if (misdn_jb_fill(ch
->jb
,frame
->data
,frame
->samples
) < 0) {
2863 cb_log(0,ch
->bc
->port
,"Misdn Jitterbuffer Overflow.\n");
2867 /*transmit without jitterbuffer*/
2868 i
=misdn_lib_tx2misdn_frm(ch
->bc
, frame
->data
, frame
->samples
);
2879 static enum ast_bridge_result
misdn_bridge (struct ast_channel
*c0
,
2880 struct ast_channel
*c1
, int flags
,
2881 struct ast_frame
**fo
,
2882 struct ast_channel
**rc
,
2886 struct chan_list
*ch1
,*ch2
;
2887 struct ast_channel
*carr
[2], *who
;
2889 struct ast_frame
*f
;
2893 ch1
=get_chan_by_ast(c0
);
2894 ch2
=get_chan_by_ast(c1
);
2903 misdn_cfg_get(ch1
->bc
->port
, MISDN_CFG_BRIDGING
, &p1_b
, sizeof(int));
2904 misdn_cfg_get(ch2
->bc
->port
, MISDN_CFG_BRIDGING
, &p2_b
, sizeof(int));
2906 if ( ! p1_b
|| ! p2_b
) {
2907 ast_log(LOG_NOTICE
, "Falling back to Asterisk bridging\n");
2908 return AST_BRIDGE_FAILED
;
2911 misdn_cfg_get( 0, MISDN_GEN_BRIDGING
, &bridging
, sizeof(int));
2913 /* trying to make a mISDN_dsp conference */
2914 chan_misdn_log(1, ch1
->bc
->port
, "I SEND: Making conference with Number:%d\n", ch1
->bc
->pid
+1);
2915 misdn_lib_bridge(ch1
->bc
,ch2
->bc
);
2918 if (option_verbose
> 2)
2919 ast_verbose(VERBOSE_PREFIX_3
"Native bridging %s and %s\n", c0
->name
, c1
->name
);
2921 chan_misdn_log(1, ch1
->bc
->port
, "* Making Native Bridge between %s and %s\n", ch1
->bc
->oad
, ch2
->bc
->oad
);
2923 if (! (flags
&AST_BRIDGE_DTMF_CHANNEL_0
) )
2926 if (! (flags
&AST_BRIDGE_DTMF_CHANNEL_1
) )
2931 who
= ast_waitfor_n(carr
, 2, &to
);
2934 ast_log(LOG_NOTICE
,"misdn_bridge: empty read, breaking out\n");
2939 if (!f
|| f
->frametype
== AST_FRAME_CONTROL
) {
2943 chan_misdn_log(4,ch1
->bc
->port
,"Read Null Frame\n");
2945 chan_misdn_log(4,ch1
->bc
->port
,"Read Frame Controll class:%d\n",f
->subclass
);
2953 if ( f
->frametype
== AST_FRAME_DTMF
) {
2954 chan_misdn_log(1,0,"Read DTMF %d from %s\n",f
->subclass
, who
->exten
);
2962 if (f
->frametype
== AST_FRAME_VOICE
) {
2963 chan_misdn_log(1, ch1
->bc
->port
, "I SEND: Splitting conference with Number:%d\n", ch1
->bc
->pid
+1);
2978 chan_misdn_log(1, ch1
->bc
->port
, "I SEND: Splitting conference with Number:%d\n", ch1
->bc
->pid
+1);
2980 misdn_lib_split_bridge(ch1
->bc
,ch2
->bc
);
2983 return AST_BRIDGE_COMPLETE
;
2986 /** AST INDICATIONS END **/
2988 static int dialtone_indicate(struct chan_list
*cl
)
2990 const struct tone_zone_sound
*ts
= NULL
;
2991 struct ast_channel
*ast
=cl
->ast
;
2995 chan_misdn_log(0,cl
->bc
->port
,"No Ast in dialtone_indicate\n");
2999 misdn_cfg_get( cl
->bc
->port
, MISDN_CFG_NODIALTONE
, &nd
, sizeof(nd
));
3002 chan_misdn_log(1,cl
->bc
->port
,"Not sending Dialtone, because config wants it\n");
3006 chan_misdn_log(3,cl
->bc
->port
," --> Dial\n");
3007 ts
=ast_get_indication_tone(ast
->zone
,"dial");
3013 /* This prods us in misdn_write */
3014 ast_playtones_start(ast
,0, ts
->data
, 0);
3020 static int hanguptone_indicate(struct chan_list
*cl
)
3022 misdn_lib_send_tone(cl
->bc
,TONE_HANGUP
);
3026 static int stop_indicate(struct chan_list
*cl
)
3028 struct ast_channel
*ast
=cl
->ast
;
3031 chan_misdn_log(0,cl
->bc
->port
,"No Ast in stop_indicate\n");
3035 chan_misdn_log(3,cl
->bc
->port
," --> None\n");
3036 misdn_lib_tone_generator_stop(cl
->bc
);
3037 ast_playtones_stop(ast
);
3040 /*ast_deactivate_generator(ast);*/
3046 static int start_bc_tones(struct chan_list
* cl
)
3048 misdn_lib_tone_generator_stop(cl
->bc
);
3054 static int stop_bc_tones(struct chan_list
*cl
)
3065 static struct chan_list
*init_chan_list(int orig
)
3067 struct chan_list
*cl
=malloc(sizeof(struct chan_list
));
3070 chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
3074 memset(cl
,0,sizeof(struct chan_list
));
3076 cl
->originator
=orig
;
3077 cl
->need_queue_hangup
=1;
3080 cl
->overlap_dial_task
=-1;
3086 static struct ast_channel
*misdn_request(const char *type
, int format
, void *data
, int *cause
)
3089 struct ast_channel
*tmp
= NULL
;
3090 char group
[BUFFERSIZE
+1]="";
3092 char buf2
[128], *ext
=NULL
, *port_str
;
3093 char *tokb
=NULL
, *p
=NULL
;
3094 int channel
=0, port
=0;
3095 struct misdn_bchannel
*newbc
= NULL
;
3098 struct chan_list
*cl
=init_chan_list(ORG_AST
);
3100 sprintf(buf
,"%s/%s",misdn_type
,(char*)data
);
3101 ast_copy_string(buf2
,data
, 128);
3103 port_str
=strtok_r(buf2
,"/", &tokb
);
3105 ext
=strtok_r(NULL
,"/", &tokb
);
3108 if (port_str
[0]=='g' && port_str
[1]==':' ) {
3109 /* We make a group call lets checkout which ports are in my group */
3111 strncpy(group
, port_str
, BUFFERSIZE
);
3113 chan_misdn_log(2, 0, " --> Group Call group: %s\n",group
);
3115 else if ((p
= strchr(port_str
, ':'))) {
3116 /* we have a preselected channel */
3118 channel
= atoi(++p
);
3119 port
= atoi(port_str
);
3120 chan_misdn_log(2, port
, " --> Call on preselected Channel (%d).\n", channel
);
3123 port
= atoi(port_str
);
3126 ast_log(LOG_WARNING
, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extension.conf\n",ext
);
3130 if (misdn_cfg_is_group_method(group
, METHOD_STANDARD_DEC
)) {
3131 chan_misdn_log(4, port
, " --> STARTING STANDARDDEC...\n");
3135 if (!ast_strlen_zero(group
)) {
3137 char cfg_group
[BUFFERSIZE
+1];
3138 struct robin_list
*rr
= NULL
;
3140 if (misdn_cfg_is_group_method(group
, METHOD_ROUND_ROBIN
)) {
3141 chan_misdn_log(4, port
, " --> STARTING ROUND ROBIN...\n");
3142 rr
= get_robin_position(group
);
3147 int port_bak
= rr
->port
;
3148 int chan_bak
= rr
->channel
;
3151 rr
->port
= misdn_cfg_get_next_port_spin(rr
->port
);
3153 for (; rr
->port
> 0; rr
->port
= misdn_cfg_get_next_port_spin(rr
->port
)) {
3157 int last_chance
= 0;
3159 misdn_cfg_get(rr
->port
, MISDN_CFG_GROUPNAME
, cfg_group
, BUFFERSIZE
);
3160 if (strcasecmp(cfg_group
, group
))
3163 misdn_cfg_get(rr
->port
, MISDN_CFG_PMP_L1_CHECK
, &check
, sizeof(int));
3164 port_up
= misdn_lib_port_up(rr
->port
, check
);
3166 if (check
&& !port_up
)
3167 chan_misdn_log(1, rr
->port
, "L1 is not Up on this Port\n");
3169 if (check
&& port_up
< 0)
3170 ast_log(LOG_WARNING
,"This port (%d) is blocked\n", rr
->port
);
3172 if ((port_start
== rr
->port
) && (port_up
<= 0))
3176 port_start
= rr
->port
;
3181 max_chan
= misdn_lib_get_maxchans(rr
->port
);
3183 for (++rr
->channel
; !last_chance
&& rr
->channel
<= max_chan
; ++rr
->channel
) {
3184 if (rr
->port
== port_bak
&& rr
->channel
== chan_bak
)
3187 chan_misdn_log(1, 0, "trying port:%d channel:%d\n", rr
->port
, rr
->channel
);
3188 newbc
= misdn_lib_get_free_bc(rr
->port
, rr
->channel
, 0, 0);
3190 chan_misdn_log(4, rr
->port
, " Success! Found port:%d channel:%d\n", newbc
->port
, newbc
->channel
);
3192 chan_misdn_log(4, rr
->port
, "portup:%d\n", port_up
);
3198 if (newbc
|| last_chance
)
3204 rr
->port
= port_bak
;
3205 rr
->channel
= chan_bak
;
3208 for (port
=misdn_cfg_get_next_port(0); port
> 0;
3209 port
=misdn_cfg_get_next_port(port
)) {
3211 misdn_cfg_get( port
, MISDN_CFG_GROUPNAME
, cfg_group
, BUFFERSIZE
);
3213 chan_misdn_log(3,port
, "Group [%s] Port [%d]\n", group
, port
);
3214 if (!strcasecmp(cfg_group
, group
)) {
3217 misdn_cfg_get(port
, MISDN_CFG_PMP_L1_CHECK
, &check
, sizeof(int));
3218 port_up
= misdn_lib_port_up(port
, check
);
3220 chan_misdn_log(4, port
, "portup:%d\n", port_up
);
3223 newbc
= misdn_lib_get_free_bc(port
, 0, 0, dec
);
3231 /* Group dial failed ?*/
3233 ast_log(LOG_WARNING
,
3234 "Could not Dial out on group '%s'.\n"
3235 "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
3236 "\tOr there was no free channel on none of the ports\n\n"
3240 } else { /* 'Normal' Port dial * Port dial */
3242 chan_misdn_log(1, port
," --> preselected_channel: %d\n",channel
);
3243 newbc
= misdn_lib_get_free_bc(port
, channel
, 0, dec
);
3246 ast_log(LOG_WARNING
, "Could not create channel on port:%d with extensions:%s\n",port
,ext
);
3252 /* create ast_channel and link all the objects together */
3255 tmp
= misdn_new(cl
, AST_STATE_RESERVED
, ext
, NULL
, format
, port
, channel
);
3257 ast_log(LOG_ERROR
,"Could not create Asterisk object\n");
3263 /* register chan in local list */
3264 cl_queue_chan(&cl_te
, cl
) ;
3266 /* fill in the config into the objects */
3267 read_config(cl
, ORG_AST
);
3276 static int misdn_send_text (struct ast_channel
*chan
, const char *text
)
3278 struct chan_list
*tmp
=chan
->tech_pvt
;
3280 if (tmp
&& tmp
->bc
) {
3281 ast_copy_string(tmp
->bc
->display
,text
,sizeof(tmp
->bc
->display
));
3282 misdn_lib_send_event(tmp
->bc
, EVENT_INFORMATION
);
3284 ast_log(LOG_WARNING
, "No chan_list but send_text request?\n");
3291 static struct ast_channel_tech misdn_tech
= {
3293 .description
="Channel driver for mISDN Support (Bri/Pri)",
3294 .capabilities
= AST_FORMAT_ALAW
,
3295 .requester
=misdn_request
,
3296 .send_digit_begin
=misdn_digit_begin
,
3297 .send_digit_end
=misdn_digit_end
,
3299 .bridge
=misdn_bridge
,
3300 .hangup
=misdn_hangup
,
3301 .answer
=misdn_answer
,
3304 .indicate
=misdn_indication
,
3306 .send_text
=misdn_send_text
,
3310 static struct ast_channel_tech misdn_tech_wo_bridge
= {
3312 .description
="Channel driver for mISDN Support (Bri/Pri)",
3313 .capabilities
=AST_FORMAT_ALAW
,
3314 .requester
=misdn_request
,
3315 .send_digit_begin
=misdn_digit_begin
,
3316 .send_digit_end
=misdn_digit_end
,
3318 .hangup
=misdn_hangup
,
3319 .answer
=misdn_answer
,
3322 .indicate
=misdn_indication
,
3324 .send_text
=misdn_send_text
,
3329 static int glob_channel
=0;
3331 static void update_name(struct ast_channel
*tmp
, int port
, int c
)
3334 int tmp_port
= misdn_cfg_get_next_port(0);
3335 for (; tmp_port
> 0; tmp_port
=misdn_cfg_get_next_port(tmp_port
)) {
3336 if (tmp_port
== port
) break;
3337 chan_offset
+=misdn_lib_port_is_pri(tmp_port
)?30:2;
3341 ast_string_field_build(tmp
, name
, "%s/%d-u%d",
3342 misdn_type
, chan_offset
+c
, glob_channel
++);
3344 chan_misdn_log(3,port
," --> updating channel name to [%s]\n",tmp
->name
);
3348 static struct ast_channel
*misdn_new(struct chan_list
*chlist
, int state
, char *exten
, char *callerid
, int format
, int port
, int c
)
3350 struct ast_channel
*tmp
;
3351 char *cid_name
= 0, *cid_num
= 0;
3353 int tmp_port
= misdn_cfg_get_next_port(0);
3355 for (; tmp_port
> 0; tmp_port
=misdn_cfg_get_next_port(tmp_port
)) {
3356 if (tmp_port
== port
) break;
3357 chan_offset
+=misdn_lib_port_is_pri(tmp_port
)?30:2;
3363 ast_callerid_parse(callerid
, &cid_name
, &cid_num
);
3365 tmp
= ast_channel_alloc(1, state
, cid_num
, cid_name
, "", exten
, "", 0, "%s/%d-u%d", misdn_type
, chan_offset
+ c
, glob_channel
++);
3369 chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n",exten
,callerid
);
3371 tmp
->nativeformats
= prefformat
;
3373 tmp
->readformat
= format
;
3374 tmp
->rawreadformat
= format
;
3375 tmp
->writeformat
= format
;
3376 tmp
->rawwriteformat
= format
;
3378 tmp
->tech_pvt
= chlist
;
3380 misdn_cfg_get( 0, MISDN_GEN_BRIDGING
, &bridging
, sizeof(int));
3383 tmp
->tech
= &misdn_tech
;
3385 tmp
->tech
= &misdn_tech_wo_bridge
;
3387 tmp
->writeformat
= format
;
3388 tmp
->readformat
= format
;
3392 ast_copy_string(tmp
->exten
, exten
, sizeof(tmp
->exten
));
3394 chan_misdn_log(1,0,"misdn_new: no exten given.\n");
3397 /* Don't use ast_set_callerid() here because it will
3398 * generate a needless NewCallerID event */
3399 tmp
->cid
.cid_ani
= ast_strdup(cid_num
);
3402 if (pipe(chlist
->pipe
)<0)
3403 perror("Pipe failed\n");
3405 tmp
->fds
[0]=chlist
->pipe
[0];
3409 if (state
== AST_STATE_RING
)
3416 chan_misdn_log(-1,0,"Unable to allocate channel structure\n");
3422 static struct chan_list
*find_chan_by_bc(struct chan_list
*list
, struct misdn_bchannel
*bc
)
3424 struct chan_list
*help
=list
;
3425 for (;help
; help
=help
->next
) {
3426 if (help
->bc
== bc
) return help
;
3429 chan_misdn_log(6, bc
->port
, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc
->oad
,bc
->dad
);
3434 static struct chan_list
*find_chan_by_pid(struct chan_list
*list
, int pid
)
3436 struct chan_list
*help
=list
;
3437 for (;help
; help
=help
->next
) {
3438 if ( help
->bc
&& (help
->bc
->pid
== pid
) ) return help
;
3441 chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n",pid
);
3446 static struct chan_list
*find_holded(struct chan_list
*list
, struct misdn_bchannel
*bc
)
3448 struct chan_list
*help
=list
;
3450 if (bc
->pri
) return NULL
;
3452 chan_misdn_log(6, bc
->port
, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc
->channel
, bc
->oad
,bc
->dad
);
3453 for (;help
; help
=help
->next
) {
3454 chan_misdn_log(4, bc
->port
, "$$$ find_holded: --> holded:%d channel:%d\n",help
->state
==MISDN_HOLDED
, help
->hold_info
.channel
);
3455 if ( (help
->state
== MISDN_HOLDED
) &&
3456 (help
->hold_info
.port
== bc
->port
) )
3459 chan_misdn_log(6, bc
->port
, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc
->oad
,bc
->dad
);
3465 static struct chan_list
*find_holded_l3(struct chan_list
*list
, unsigned long l3_id
, int w
)
3468 struct chan_list
*help
=list
;
3470 for (;help
; help
=help
->next
) {
3471 if ( (help
->state
== MISDN_HOLDED
) &&
3472 (help
->l3id
== l3_id
)
3480 static void cl_queue_chan(struct chan_list
**list
, struct chan_list
*chan
)
3482 chan_misdn_log(4, chan
->bc
? chan
->bc
->port
: 0, "* Queuing chan %p\n",chan
);
3484 ast_mutex_lock(&cl_te_lock
);
3488 struct chan_list
*help
=*list
;
3489 for (;help
->next
; help
=help
->next
);
3493 ast_mutex_unlock(&cl_te_lock
);
3496 static void cl_dequeue_chan(struct chan_list
**list
, struct chan_list
*chan
)
3499 ast_dsp_free(chan
->dsp
);
3501 ast_translator_free_path(chan
->trans
);
3505 ast_mutex_lock(&cl_te_lock
);
3507 ast_mutex_unlock(&cl_te_lock
);
3511 if (*list
== chan
) {
3512 *list
=(*list
)->next
;
3513 ast_mutex_unlock(&cl_te_lock
);
3518 struct chan_list
*help
=*list
;
3519 for (;help
->next
; help
=help
->next
) {
3520 if (help
->next
== chan
) {
3521 help
->next
=help
->next
->next
;
3522 ast_mutex_unlock(&cl_te_lock
);
3528 ast_mutex_unlock(&cl_te_lock
);
3531 /** Channel Queue End **/
3534 int pbx_start_chan(struct chan_list
*ch
)
3536 int ret
=ast_pbx_start(ch
->ast
);
3546 static void hangup_chan(struct chan_list
*ch
)
3548 int port
=ch
?ch
->bc
?ch
->bc
->port
:0:0;
3550 cb_log(1,0,"Cannot hangup chan, no ch\n");
3554 cb_log(5,port
,"hangup_chan called\n");
3556 if (ch
->need_hangup
)
3558 cb_log(2,port
," --> hangup\n");
3559 send_cause2ast(ch
->ast
,ch
->bc
,ch
);
3561 ch
->need_queue_hangup
=0;
3563 ast_hangup(ch
->ast
);
3567 if (!ch
->need_queue_hangup
) {
3568 cb_log(2,port
," --> No need to queue hangup\n");
3571 ch
->need_queue_hangup
=0;
3573 send_cause2ast(ch
->ast
,ch
->bc
,ch
);
3576 ast_queue_hangup(ch
->ast
);
3577 cb_log(2,port
," --> queue_hangup\n");
3579 cb_log(1,port
,"Cannot hangup chan, no ast\n");
3583 /** Isdn asks us to release channel, pendant to misdn_hangup **/
3584 static void release_chan(struct misdn_bchannel
*bc
) {
3585 struct ast_channel
*ast
=NULL
;
3587 ast_mutex_lock(&release_lock
);
3589 struct chan_list
*ch
=find_chan_by_bc(cl_te
, bc
);
3591 chan_misdn_log(1, bc
->port
, "release_chan: Ch not found!\n");
3592 ast_mutex_unlock(&release_lock
);
3600 chan_misdn_log(5, bc
->port
, "release_chan: bc with l3id: %x\n",bc
->l3_id
);
3602 /*releaseing jitterbuffer*/
3604 misdn_jb_destroy(ch
->jb
);
3608 chan_misdn_log(5,bc
->port
,"Jitterbuffer already destroyed.\n");
3611 if (ch
->overlap_dial
) {
3612 if (ch
->overlap_dial_task
!= -1) {
3613 misdn_tasks_remove(ch
->overlap_dial_task
);
3614 ch
->overlap_dial_task
= -1;
3616 ast_mutex_destroy(&ch
->overlap_tv_lock
);
3619 if (ch
->originator
== ORG_AST
) {
3620 misdn_out_calls
[bc
->port
]--;
3622 misdn_in_calls
[bc
->port
]--;
3631 if (ast
&& MISDN_ASTERISK_TECH_PVT(ast
)) {
3632 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
));
3633 chan_misdn_log(3, bc
->port
, " --> * State Down\n");
3634 MISDN_ASTERISK_TECH_PVT(ast
)=NULL
;
3637 if (ast
->_state
!= AST_STATE_RESERVED
) {
3638 chan_misdn_log(3, bc
->port
, " --> Setting AST State to down\n");
3639 ast_setstate(ast
, AST_STATE_DOWN
);
3643 ch
->state
=MISDN_CLEANING
;
3644 cl_dequeue_chan(&cl_te
, ch
);
3648 /* chan is already cleaned, so exiting */
3652 ast_mutex_unlock(&release_lock
);
3654 /*** release end **/
3656 static void misdn_transfer_bc(struct chan_list
*tmp_ch
, struct chan_list
*holded_chan
)
3658 chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan
->ast
->name
, tmp_ch
->ast
->name
);
3660 tmp_ch
->state
=MISDN_HOLD_DISCONNECT
;
3662 ast_moh_stop(ast_bridged_channel(holded_chan
->ast
));
3664 holded_chan
->state
=MISDN_CONNECTED
;
3665 //misdn_lib_transfer(holded_chan->bc);
3666 ast_channel_masquerade(holded_chan
->ast
, ast_bridged_channel(tmp_ch
->ast
));
3670 static void do_immediate_setup(struct misdn_bchannel
*bc
,struct chan_list
*ch
, struct ast_channel
*ast
)
3672 char predial
[256]="";
3675 struct ast_frame fr
;
3677 strncpy(predial
, ast
->exten
, sizeof(predial
) -1 );
3679 ch
->state
=MISDN_DIALING
;
3681 if (!ch
->noautorespond_on_setup
) {
3684 ret
= misdn_lib_send_event(bc
, EVENT_SETUP_ACKNOWLEDGE
);
3687 if ( misdn_lib_is_ptp(bc
->port
)) {
3688 ret
= misdn_lib_send_event(bc
, EVENT_SETUP_ACKNOWLEDGE
);
3690 ret
= misdn_lib_send_event(bc
, EVENT_PROCEEDING
);
3694 ch
->state
= MISDN_INCOMING_SETUP
;
3697 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
);
3699 strncpy(ast
->exten
,"s", 2);
3701 if (pbx_start_chan(ch
)<0) {
3704 hanguptone_indicate(ch
);
3707 misdn_lib_send_event(bc
, EVENT_RELEASE_COMPLETE
);
3709 misdn_lib_send_event(bc
, EVENT_DISCONNECT
);
3713 while (!ast_strlen_zero(p
) ) {
3714 fr
.frametype
= AST_FRAME_DTMF
;
3722 fr
.delivery
= ast_tv(0,0) ;
3724 if (ch
->ast
&& MISDN_ASTERISK_PVT(ch
->ast
) && MISDN_ASTERISK_TECH_PVT(ch
->ast
)) {
3725 ast_queue_frame(ch
->ast
, &fr
);
3733 static void send_cause2ast(struct ast_channel
*ast
, struct misdn_bchannel
*bc
, struct chan_list
*ch
) {
3735 chan_misdn_log(1,0,"send_cause2ast: No Ast\n");
3739 chan_misdn_log(1,0,"send_cause2ast: No BC\n");
3743 chan_misdn_log(1,0,"send_cause2ast: No Ch\n");
3747 ast
->hangupcause
=bc
->cause
;
3749 switch ( bc
->cause
) {
3751 case 1: /** Congestion Cases **/
3758 * Not Queueing the Congestion anymore, since we want to hear
3759 * the inband message
3761 chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Congestion pid:%d\n", bc?bc->pid:-1);
3762 ch->state=MISDN_BUSY;
3764 ast_queue_control(ast, AST_CONTROL_CONGESTION);
3769 case 17: /* user busy */
3771 ch
->state
=MISDN_BUSY
;
3773 if (!ch
->need_busy
) {
3774 chan_misdn_log(1,bc
?bc
->port
:0, "Queued busy already\n");
3778 chan_misdn_log(1, bc
?bc
->port
:0, " --> * SEND: Queue Busy pid:%d\n", bc
?bc
->pid
:-1);
3780 ast_queue_control(ast
, AST_CONTROL_BUSY
);
3791 void import_ch(struct ast_channel
*chan
, struct misdn_bchannel
*bc
, struct chan_list
*ch
)
3794 tmp
=pbx_builtin_getvar_helper(chan
,"MISDN_PID");
3796 ch
->other_pid
=atoi(tmp
);
3797 chan_misdn_log(3,bc
->port
," --> IMPORT_PID: importing pid:%s\n",tmp
);
3798 if (ch
->other_pid
>0) {
3799 ch
->other_ch
=find_chan_by_pid(cl_te
,ch
->other_pid
);
3800 if (ch
->other_ch
) ch
->other_ch
->other_ch
=ch
;
3804 tmp
=pbx_builtin_getvar_helper(chan
,"MISDN_ADDRESS_COMPLETE");
3805 if (tmp
&& (atoi(tmp
) == 1)) {
3806 bc
->sending_complete
=1;
3809 tmp
=pbx_builtin_getvar_helper(chan
,"MISDN_USERUSER");
3811 ast_log(LOG_NOTICE
, "MISDN_USERUSER: %s\n", tmp
);
3812 strcpy(bc
->uu
, tmp
);
3813 bc
->uulen
=strlen(bc
->uu
);
3816 tmp
=pbx_builtin_getvar_helper(chan
,"MISDN_KEYPAD");
3818 strncpy(bc
->keypad
,tmp
,sizeof(bc
->keypad
));
3819 bc
->keypad
[sizeof(bc
->keypad
)-1]=0;
3825 void export_ch(struct ast_channel
*chan
, struct misdn_bchannel
*bc
, struct chan_list
*ch
)
3828 chan_misdn_log(3,bc
->port
," --> EXPORT_PID: pid:%d\n",bc
->pid
);
3829 sprintf(tmp
,"%d",bc
->pid
);
3830 pbx_builtin_setvar_helper(chan
,"_MISDN_PID",tmp
);
3832 if (bc
->sending_complete
) {
3833 sprintf(tmp
,"%d",bc
->sending_complete
);
3834 pbx_builtin_setvar_helper(chan
,"MISDN_ADDRESS_COMPLETE",tmp
);
3838 sprintf(tmp
,"%d",bc
->urate
);
3839 pbx_builtin_setvar_helper(chan
,"MISDN_URATE",tmp
);
3842 if (bc
->uulen
&& (bc
->uulen
< sizeof(bc
->uu
))) {
3843 bc
->uu
[bc
->uulen
]=0;
3844 pbx_builtin_setvar_helper(chan
,"MISDN_USERUSER",bc
->uu
);
3848 pbx_builtin_setvar_helper(chan
,"MISDN_KEYPAD",bc
->keypad
);
3851 int add_in_calls(int port
)
3855 misdn_cfg_get( port
, MISDN_CFG_MAX_IN
, &max_in_calls
, sizeof(max_in_calls
));
3856 misdn_in_calls
[port
]++;
3858 if (max_in_calls
>=0 && max_in_calls
<misdn_in_calls
[port
]) {
3859 ast_log(LOG_NOTICE
,"Marking Incoming Call on port[%d]\n",port
);
3860 return misdn_in_calls
[port
]-max_in_calls
;
3866 int add_out_calls(int port
)
3870 misdn_cfg_get( port
, MISDN_CFG_MAX_OUT
, &max_out_calls
, sizeof(max_out_calls
));
3873 if (max_out_calls
>=0 && max_out_calls
<=misdn_out_calls
[port
]) {
3874 ast_log(LOG_NOTICE
,"Rejecting Outgoing Call on port[%d]\n",port
);
3875 return (misdn_out_calls
[port
]+1)-max_out_calls
;
3878 misdn_out_calls
[port
]++;
3883 static void start_pbx(struct chan_list
*ch
, struct misdn_bchannel
*bc
, struct ast_channel
*chan
) {
3884 if (pbx_start_chan(ch
)<0) {
3886 chan_misdn_log(-1, bc
->port
, "ast_pbx_start returned <0 in SETUP\n");
3888 hanguptone_indicate(ch
);
3889 misdn_lib_send_event(bc
, EVENT_RELEASE_COMPLETE
);
3891 misdn_lib_send_event(bc
, EVENT_RELEASE
);
3895 static void wait_for_digits(struct chan_list
*ch
, struct misdn_bchannel
*bc
, struct ast_channel
*chan
) {
3896 ch
->state
=MISDN_WAITING4DIGS
;
3897 misdn_lib_send_event(bc
, EVENT_SETUP_ACKNOWLEDGE
);
3898 if (bc
->nt
&& !bc
->dad
[0])
3899 dialtone_indicate(ch
);
3903 /************************************************************/
3904 /* Receive Events from isdn_lib here */
3905 /************************************************************/
3906 static enum event_response_e
3907 cb_events(enum event_e event
, struct misdn_bchannel
*bc
, void *user_data
)
3910 struct chan_list
*ch
=find_chan_by_bc(cl_te
, bc
);
3912 if (event
!= EVENT_BCHAN_DATA
&& event
!= EVENT_TONE_GENERATE
) { /* Debug Only Non-Bchan */
3914 if ( event
==EVENT_CLEANUP
&& !user_data
)
3917 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");
3918 if (debuglevel
==1) {
3919 misdn_lib_log_ies(bc
);
3920 chan_misdn_log(4,bc
->port
," --> bc_state:%s\n",bc_state2str(bc
->bc_state
));
3927 case EVENT_DISCONNECT
:
3928 case EVENT_PORT_ALARM
:
3929 case EVENT_RETRIEVE
:
3931 case EVENT_FACILITY
:
3933 case EVENT_RELEASE_COMPLETE
:
3934 chan_misdn_log(1, bc
->port
, " --> no Ch, so we've already released.\n");
3937 case EVENT_TONE_GENERATE
:
3938 case EVENT_BCHAN_DATA
:
3942 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
);
3949 case EVENT_TONE_GENERATE
:
3951 case EVENT_DISCONNECT
:
3953 case EVENT_RELEASE_COMPLETE
:
3957 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
));
3960 if ( !ch
->ast
|| !MISDN_ASTERISK_PVT(ch
->ast
) || !MISDN_ASTERISK_TECH_PVT(ch
->ast
)) {
3961 if (event
!=EVENT_BCHAN_DATA
)
3962 ast_log(LOG_NOTICE
, "No Ast or No private Pointer in Event (%d:%s)\n", event
, manager_isdn_get_info(event
));
3970 case EVENT_PORT_ALARM
:
3973 misdn_cfg_get( bc
->port
, MISDN_CFG_ALARM_BLOCK
, &boa
, sizeof(int));
3975 cb_log(1,bc
->port
," --> blocking\n");
3976 misdn_lib_port_block(bc
->port
);
3980 case EVENT_BCHAN_ACTIVATED
:
3983 case EVENT_NEW_CHANNEL
:
3984 update_name(ch
->ast
,bc
->port
,bc
->channel
);
3987 case EVENT_NEW_L3ID
:
3994 ch
=find_holded(cl_te
,bc
);
3998 ast_log(LOG_WARNING
,"NEW_BC without chan_list?\n");
4003 ch
->bc
=(struct misdn_bchannel
*)user_data
;
4006 case EVENT_DTMF_TONE
:
4008 /* sending INFOS as DTMF-Frames :) */
4009 struct ast_frame fr
;
4010 memset(&fr
, 0 , sizeof(fr
));
4011 fr
.frametype
= AST_FRAME_DTMF
;
4012 fr
.subclass
= bc
->dtmf
;
4019 fr
.delivery
= ast_tv(0,0) ;
4021 if (!ch
->ignore_dtmf
) {
4022 chan_misdn_log(2, bc
->port
, " --> DTMF:%c\n", bc
->dtmf
);
4023 ast_queue_frame(ch
->ast
, &fr
);
4025 chan_misdn_log(2, bc
->port
, " --> Ingoring DTMF:%c due to bridge flags\n", bc
->dtmf
);
4032 case EVENT_INFORMATION
:
4036 if ( ch
->state
!= MISDN_CONNECTED
)
4039 if (!ch
->ast
) break;
4041 if (ch
->state
== MISDN_WAITING4DIGS
) {
4042 /* Ok, incomplete Setup, waiting till extension exists */
4043 if (ast_strlen_zero(bc
->info_dad
) && ! ast_strlen_zero(bc
->keypad
)) {
4044 chan_misdn_log(1, bc
->port
, " --> using keypad as info\n");
4045 strcpy(bc
->info_dad
,bc
->keypad
);
4048 l
= sizeof(bc
->dad
);
4049 strncat(bc
->dad
,bc
->info_dad
, l
);
4052 l
= sizeof(ch
->ast
->exten
);
4053 strncpy(ch
->ast
->exten
, bc
->dad
, l
);
4054 ch
->ast
->exten
[l
-1] = 0;
4056 /* Check for Pickup Request first */
4057 if (!strcmp(ch
->ast
->exten
, ast_pickup_ext())) {
4058 if (ast_pickup_call(ch
->ast
)) {
4061 struct ast_channel
*chan
=ch
->ast
;
4062 ch
->state
= MISDN_CALLING_ACKNOWLEDGE
;
4063 ast_setstate(chan
, AST_STATE_DOWN
);
4070 if(!ast_canmatch_extension(ch
->ast
, ch
->context
, bc
->dad
, 1, bc
->oad
)) {
4071 if (ast_exists_extension(ch
->ast
, ch
->context
, "i", 1, bc
->oad
)) {
4072 ast_log(LOG_WARNING
, "Extension can never match, So jumping to 'i' extension. port(%d)\n",bc
->port
);
4073 strcpy(ch
->ast
->exten
, "i");
4075 ch
->state
= MISDN_DIALING
;
4076 start_pbx(ch
, bc
, ch
->ast
);
4080 ast_log(LOG_WARNING
, "Extension can never match, so disconnecting on port(%d)."
4081 "maybe you want to add an 'i' extension to catch this case.\n",
4085 hanguptone_indicate(ch
);
4086 ch
->state
=MISDN_EXTCANTMATCH
;
4089 misdn_lib_send_event(bc
, EVENT_DISCONNECT
);
4093 if (ch
->overlap_dial
) {
4094 ast_mutex_lock(&ch
->overlap_tv_lock
);
4095 ch
->overlap_tv
= ast_tvnow();
4096 ast_mutex_unlock(&ch
->overlap_tv_lock
);
4097 if (ch
->overlap_dial_task
== -1) {
4098 ch
->overlap_dial_task
=
4099 misdn_tasks_add_variable(ch
->overlap_dial
, misdn_overlap_dial_task
, ch
);
4104 if (ast_exists_extension(ch
->ast
, ch
->context
, bc
->dad
, 1, bc
->oad
)) {
4106 ch
->state
= MISDN_DIALING
;
4107 start_pbx(ch
, bc
, ch
->ast
);
4110 /* sending INFOS as DTMF-Frames :) */
4112 struct ast_frame fr
;
4113 memset(&fr
, 0, sizeof(fr
));
4114 fr
.frametype
= AST_FRAME_DTMF
;
4115 fr
.subclass
= bc
->info_dad
[0] ;
4122 fr
.delivery
= ast_tv(0,0) ;
4124 misdn_cfg_get( 0, MISDN_GEN_APPEND_DIGITS2EXTEN
, &digits
, sizeof(int));
4125 if (ch
->state
!= MISDN_CONNECTED
) {
4127 int l
= sizeof(bc
->dad
);
4128 strncat(bc
->dad
,bc
->info_dad
, l
);
4130 l
= sizeof(ch
->ast
->exten
);
4131 strncpy(ch
->ast
->exten
, bc
->dad
, l
);
4132 ch
->ast
->exten
[l
-1] = 0;
4134 ast_cdr_update(ch
->ast
);
4137 ast_queue_frame(ch
->ast
, &fr
);
4144 struct chan_list
*ch
=find_chan_by_bc(cl_te
, bc
);
4146 switch (ch
->state
) {
4151 chan_misdn_log(1, bc
->port
, " --> Ignoring Call we have already one\n");
4152 return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE
; /* Ignore MSNs which are not in our List */
4157 msn_valid
= misdn_cfg_is_msn_valid(bc
->port
, bc
->dad
);
4158 if (!bc
->nt
&& ! msn_valid
) {
4159 chan_misdn_log(1, bc
->port
, " --> Ignoring Call, its not in our MSN List\n");
4160 return RESPONSE_IGNORE_SETUP
; /* Ignore MSNs which are not in our List */
4166 chan_misdn_log(0, bc
->port
, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
4167 misdn_cfg_get( bc
->port
, MISDN_CFG_REJECT_CAUSE
, &cause
, sizeof(cause
));
4168 bc
->out_cause
=cause
?cause
:16;
4169 return RESPONSE_RELEASE_SETUP
;
4175 struct chan_list
*ch
;
4176 struct ast_channel
*chan
;
4179 int msn_valid
= misdn_cfg_is_msn_valid(bc
->port
, bc
->dad
);
4181 if (!bc
->nt
&& ! msn_valid
) {
4182 chan_misdn_log(1, bc
->port
, " --> Ignoring Call, its not in our MSN List\n");
4183 return RESPONSE_IGNORE_SETUP
; /* Ignore MSNs which are not in our List */
4188 chan_misdn_log(0, bc
->port
, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
4189 misdn_cfg_get( bc
->port
, MISDN_CFG_REJECT_CAUSE
, &cause
, sizeof(cause
));
4190 bc
->out_cause
=cause
?cause
:16;
4191 return RESPONSE_RELEASE_SETUP
;
4196 ch
=init_chan_list(ORG_MISDN
);
4198 if (!ch
) { chan_misdn_log(-1, bc
->port
, "cb_events: malloc for chan_list failed!\n"); return 0;}
4203 ch
->originator
= ORG_MISDN
;
4205 chan
=misdn_new(ch
, AST_STATE_RESERVED
,bc
->dad
, bc
->oad
, AST_FORMAT_ALAW
, bc
->port
, bc
->channel
);
4208 misdn_lib_send_event(bc
,EVENT_RELEASE_COMPLETE
);
4209 ast_log(LOG_ERROR
, "cb_events: misdn_new failed !\n");
4215 if ((exceed
=add_in_calls(bc
->port
))) {
4217 sprintf(tmp
,"%d",exceed
);
4218 pbx_builtin_setvar_helper(chan
,"MAX_OVERFLOW",tmp
);
4221 read_config(ch
, ORG_MISDN
);
4223 export_ch(chan
, bc
, ch
);
4226 ast_setstate(ch
->ast
, AST_STATE_RINGING
);
4230 pres
=AST_PRES_RESTRICTED
; chan_misdn_log(2,bc
->port
," --> PRES: Restricted (1)\n");
4233 pres
=AST_PRES_UNAVAILABLE
; chan_misdn_log(2,bc
->port
," --> PRES: Restricted (2)\n");
4236 pres
=AST_PRES_ALLOWED
; chan_misdn_log(2,bc
->port
," --> PRES: Restricted (%d)\n", bc
->pres
);
4239 switch (bc
->screen
) {
4241 screen
=AST_PRES_USER_NUMBER_UNSCREENED
; chan_misdn_log(2,bc
->port
," --> SCREEN: Unscreened (0)\n");
4244 screen
=AST_PRES_USER_NUMBER_PASSED_SCREEN
; chan_misdn_log(2,bc
->port
," --> SCREEN: Passed screen (1)\n");
4247 screen
=AST_PRES_USER_NUMBER_FAILED_SCREEN
; chan_misdn_log(2,bc
->port
," --> SCREEN: failed screen (2)\n");
4250 screen
=AST_PRES_NETWORK_NUMBER
; chan_misdn_log(2,bc
->port
," --> SCREEN: Network Number (3)\n");
4253 screen
=AST_PRES_USER_NUMBER_UNSCREENED
; chan_misdn_log(2,bc
->port
," --> SCREEN: Unscreened (%d)\n",bc
->screen
);
4256 chan
->cid
.cid_pres
=pres
+screen
;
4258 pbx_builtin_setvar_helper(chan
, "TRANSFERCAPABILITY", ast_transfercapability2str(bc
->capability
));
4259 chan
->transfercapability
=bc
->capability
;
4261 switch (bc
->capability
) {
4262 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED
:
4263 pbx_builtin_setvar_helper(chan
,"CALLTYPE","DIGITAL");
4266 pbx_builtin_setvar_helper(chan
,"CALLTYPE","SPEECH");
4269 /** queue new chan **/
4270 cl_queue_chan(&cl_te
, ch
) ;
4272 if (!strstr(ch
->allowed_bearers
,"all")) {
4274 for (i
=0; i
< sizeof(allowed_bearers_array
)/sizeof(struct allowed_bearers
); i
++) {
4275 if (allowed_bearers_array
[i
].cap
== bc
->capability
) {
4276 if ( !strstr( ch
->allowed_bearers
, allowed_bearers_array
[i
].name
)) {
4277 chan_misdn_log(0,bc
->port
,"Bearer Not allowed\b");
4280 ch
->state
=MISDN_EXTCANTMATCH
;
4281 misdn_lib_send_event(bc
, EVENT_RELEASE_COMPLETE
);
4289 /* Check for Pickup Request first */
4290 if (!strcmp(chan
->exten
, ast_pickup_ext())) {
4291 if (!ch
->noautorespond_on_setup
) {
4292 int ret
;/** Sending SETUP_ACK**/
4293 ret
= misdn_lib_send_event(bc
, EVENT_SETUP_ACKNOWLEDGE
);
4295 ch
->state
= MISDN_INCOMING_SETUP
;
4297 if (ast_pickup_call(chan
)) {
4300 ch
->state
= MISDN_CALLING_ACKNOWLEDGE
;
4301 ast_setstate(chan
, AST_STATE_DOWN
);
4309 added support for s extension hope it will help those poor cretains
4310 which haven't overlap dial.
4312 misdn_cfg_get( bc
->port
, MISDN_CFG_ALWAYS_IMMEDIATE
, &ai
, sizeof(ai
));
4314 do_immediate_setup(bc
, ch
, chan
);
4318 /* check if we should jump into s when we have no dad */
4319 misdn_cfg_get( bc
->port
, MISDN_CFG_IMMEDIATE
, &im
, sizeof(im
));
4320 if ( im
&& ast_strlen_zero(bc
->dad
) ) {
4321 do_immediate_setup(bc
, ch
, chan
);
4325 chan_misdn_log(5,bc
->port
,"CONTEXT:%s\n",ch
->context
);
4326 if(!ast_canmatch_extension(ch
->ast
, ch
->context
, bc
->dad
, 1, bc
->oad
)) {
4327 if (ast_exists_extension(ch
->ast
, ch
->context
, "i", 1, bc
->oad
)) {
4328 ast_log(LOG_WARNING
, "Extension can never match, So jumping to 'i' extension. port(%d)\n",bc
->port
);
4329 strcpy(ch
->ast
->exten
, "i");
4330 misdn_lib_send_event(bc
, EVENT_SETUP_ACKNOWLEDGE
);
4331 ch
->state
=MISDN_DIALING
;
4332 start_pbx(ch
, bc
, chan
);
4336 ast_log(LOG_WARNING
, "Extension can never match, so disconnecting on port(%d)."
4337 "maybe you want to add an 'i' extension to catch this case.\n",
4340 hanguptone_indicate(ch
);
4342 ch
->state
=MISDN_EXTCANTMATCH
;
4346 misdn_lib_send_event(bc
, EVENT_RELEASE_COMPLETE
);
4348 misdn_lib_send_event(bc
, EVENT_RELEASE
);
4353 /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely
4354 * jump into the dialplan, when the dialed extension does not exist, the 's' extension
4355 * will be used by Asterisk automatically. */
4356 if (bc
->sending_complete
|| (!bc
->nt
&& !misdn_lib_is_ptp(bc
->port
))) {
4357 if (!ch
->noautorespond_on_setup
) {
4358 ch
->state
=MISDN_DIALING
;
4359 misdn_lib_send_event(bc
, EVENT_PROCEEDING
);
4361 ch
->state
= MISDN_INCOMING_SETUP
;
4363 start_pbx(ch
, bc
, chan
);
4369 * When we are NT and overlapdial is set and if
4370 * the number is empty, we wait for the ISDN timeout
4371 * instead of our own timer.
4373 if (ch
->overlap_dial
&& bc
->nt
&& !bc
->dad
[0] ) {
4374 wait_for_digits(ch
, bc
, chan
);
4379 * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more
4380 * Infos with a Interdigit Timeout.
4382 if (ch
->overlap_dial
) {
4383 ast_mutex_lock(&ch
->overlap_tv_lock
);
4384 ch
->overlap_tv
= ast_tvnow();
4385 ast_mutex_unlock(&ch
->overlap_tv_lock
);
4387 wait_for_digits(ch
, bc
, chan
);
4388 if (ch
->overlap_dial_task
== -1)
4389 ch
->overlap_dial_task
=
4390 misdn_tasks_add_variable(ch
->overlap_dial
, misdn_overlap_dial_task
, ch
);
4395 /* If the extension does not exist and we're not TE_PTMP we wait for more digis
4396 * without interdigit timeout.
4398 if (!ast_exists_extension(ch
->ast
, ch
->context
, bc
->dad
, 1, bc
->oad
)) {
4399 wait_for_digits(ch
, bc
, chan
);
4404 * If the extension exists let's just jump into it.
4406 if (ast_exists_extension(ch
->ast
, ch
->context
, bc
->dad
, 1, bc
->oad
)) {
4407 if (bc
->need_more_infos
)
4408 misdn_lib_send_event(bc
, EVENT_SETUP_ACKNOWLEDGE
);
4410 misdn_lib_send_event(bc
, EVENT_PROCEEDING
);
4412 ch
->state
=MISDN_DIALING
;
4413 start_pbx(ch
, bc
, chan
);
4419 case EVENT_SETUP_ACKNOWLEDGE
:
4421 ch
->state
= MISDN_CALLING_ACKNOWLEDGE
;
4424 update_name(ch
->ast
,bc
->port
,bc
->channel
);
4426 if (!ast_strlen_zero(bc
->infos_pending
)) {
4427 /* TX Pending Infos */
4430 int l
= sizeof(bc
->dad
);
4431 strncat(bc
->dad
,bc
->infos_pending
, l
- strlen(bc
->dad
));
4435 if (!ch
->ast
) break;
4437 int l
= sizeof(ch
->ast
->exten
);
4438 strncpy(ch
->ast
->exten
, bc
->dad
, l
);
4439 ch
->ast
->exten
[l
-1] = 0;
4442 int l
= sizeof(bc
->info_dad
);
4443 strncpy(bc
->info_dad
, bc
->infos_pending
, l
);
4444 bc
->info_dad
[l
-1] = 0;
4446 strncpy(bc
->infos_pending
,"", 1);
4448 misdn_lib_send_event(bc
, EVENT_INFORMATION
);
4452 case EVENT_PROCEEDING
:
4455 update_name(ch
->ast
,bc
->port
,bc
->channel
);
4457 if ( misdn_cap_is_speech(bc
->capability
) &&
4458 misdn_inband_avail(bc
) ) {
4462 ch
->state
= MISDN_PROCEEDING
;
4464 if (!ch
->ast
) break;
4466 ast_queue_control(ch
->ast
, AST_CONTROL_PROCEEDING
);
4469 case EVENT_PROGRESS
:
4471 update_name(ch
->ast
,bc
->port
,bc
->channel
);
4474 if ( misdn_cap_is_speech(bc
->capability
) &&
4475 misdn_inband_avail(bc
)
4480 ch
->state
=MISDN_PROGRESS
;
4482 if (!ch
->ast
) break;
4483 ast_queue_control(ch
->ast
, AST_CONTROL_PROGRESS
);
4488 case EVENT_ALERTING
:
4491 update_name(ch
->ast
,bc
->port
,bc
->channel
);
4493 ch
->state
= MISDN_ALERTING
;
4495 if (!ch
->ast
) break;
4497 ast_queue_control(ch
->ast
, AST_CONTROL_RINGING
);
4498 ast_setstate(ch
->ast
, AST_STATE_RINGING
);
4500 cb_log(7,bc
->port
," --> Set State Ringing\n");
4502 if ( misdn_cap_is_speech(bc
->capability
) && misdn_inband_avail(bc
)) {
4503 cb_log(1,bc
->port
,"Starting Tones, we have inband Data\n");
4506 cb_log(3,bc
->port
," --> We have no inband Data, the other end must create ringing\n");
4507 if (ch
->far_alerting
) {
4508 cb_log(1,bc
->port
," --> The other end can not do ringing eh ?.. we must do all ourself..");
4510 /*tone_indicate(ch, TONE_FAR_ALERTING);*/
4517 struct ast_channel
*bridged
;
4518 /*we answer when we've got our very new L3 ID from the NT stack */
4519 misdn_lib_send_event(bc
,EVENT_CONNECT_ACKNOWLEDGE
);
4521 if (!ch
->ast
) break;
4523 bridged
=ast_bridged_channel(ch
->ast
);
4526 if (bridged
&& !strcasecmp(bridged
->tech
->type
,"mISDN")) {
4527 struct chan_list
*bridged_ch
=MISDN_ASTERISK_TECH_PVT(bridged
);
4529 chan_misdn_log(1,bc
->port
," --> copying cpndialplan:%d and cad:%s to the A-Channel\n",bc
->cpnnumplan
,bc
->cad
);
4531 bridged_ch
->bc
->cpnnumplan
=bc
->cpnnumplan
;
4532 ast_copy_string(bridged_ch
->bc
->cad
,bc
->cad
,sizeof(bc
->cad
));
4541 ch
->state
= MISDN_CONNECTED
;
4543 ast_queue_control(ch
->ast
, AST_CONTROL_ANSWER
);
4545 case EVENT_CONNECT_ACKNOWLEDGE
:
4552 ch
->state
= MISDN_CONNECTED
;
4555 case EVENT_DISCONNECT
:
4556 /*we might not have an ch->ast ptr here anymore*/
4558 struct chan_list
*holded_ch
=find_holded(cl_te
, bc
);
4560 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
);
4561 if ( ch
->originator
==ORG_AST
&& !bc
->nt
&& misdn_inband_avail(bc
) && ch
->state
!= MISDN_CONNECTED
) {
4562 /* If there's inband information available (e.g. a
4563 recorded message saying what was wrong with the
4564 dialled number, or perhaps even giving an
4565 alternative number, then play it instead of
4566 immediately releasing the call */
4567 chan_misdn_log(1,bc
->port
, " --> Inband Info Avail, not sending RELEASE\n");
4569 ch
->state
=MISDN_DISCONNECTED
;
4573 ch
->ast
->hangupcause
=bc
->cause
;
4574 if (bc
->cause
== 17)
4575 ast_queue_control(ch
->ast
, AST_CONTROL_BUSY
);
4581 /*Check for holded channel, to implement transfer*/
4585 ch
->state
== MISDN_CONNECTED
) {
4586 cb_log(1,bc
->port
," --> found holded ch\n");
4587 misdn_transfer_bc(ch
, holded_ch
) ;
4590 bc
->need_disconnect
=0;
4595 /* ch=find_holded_l3(cl_te, bc->l3_id,1);
4602 if (bc
->need_release
) misdn_lib_send_event(bc
,EVENT_RELEASE
);
4607 bc
->need_disconnect
=0;
4614 case EVENT_RELEASE_COMPLETE
:
4616 bc
->need_disconnect
=0;
4618 bc
->need_release_complete
=0;
4624 ch
->state
=MISDN_CLEANING
;
4629 case EVENT_BCHAN_ERROR
:
4636 bc
->cause
=27; /* Destination out of order */
4647 case EVENT_TONE_GENERATE
:
4649 int tone_len
=bc
->tone_cnt
;
4650 struct ast_channel
*ast
=ch
->ast
;
4653 int (*generate
)(struct ast_channel
*chan
, void *tmp
, int datalen
, int samples
);
4655 chan_misdn_log(9,bc
->port
,"TONE_GEN: len:%d\n");
4659 if (!ast
->generator
) break;
4663 tmp
= ast
->generatordata
;
4664 ast
->generatordata
= NULL
;
4665 generate
= ast
->generator
->generate
;
4667 if (tone_len
<0 || tone_len
> 512 ) {
4668 ast_log(LOG_NOTICE
, "TONE_GEN: len was %d, set to 128\n",tone_len
);
4672 res
= generate(ast
, tmp
, tone_len
, tone_len
);
4673 ast
->generatordata
= tmp
;
4676 ast_log(LOG_WARNING
, "Auto-deactivating generator\n");
4677 ast_deactivate_generator(ast
);
4684 case EVENT_BCHAN_DATA
:
4686 if ( !misdn_cap_is_speech(ch
->bc
->capability
) ) {
4687 struct ast_frame frame
;
4688 /*In Data Modes we queue frames*/
4689 frame
.frametype
= AST_FRAME_VOICE
; /*we have no data frames yet*/
4690 frame
.subclass
= AST_FORMAT_ALAW
;
4691 frame
.datalen
= bc
->bframe_len
;
4692 frame
.samples
= bc
->bframe_len
;
4695 frame
.delivery
= ast_tv(0,0) ;
4697 frame
.data
= bc
->bframe
;
4700 ast_queue_frame(ch
->ast
,&frame
);
4710 FD_SET(ch
->pipe
[1],&wrfs
);
4712 t
=select(FD_SETSIZE
,NULL
,&wrfs
,NULL
,&tv
);
4715 chan_misdn_log(9, bc
->port
, "Select Timed out\n");
4720 chan_misdn_log(-1, bc
->port
, "Select Error (err=%s)\n",strerror(errno
));
4724 if (FD_ISSET(ch
->pipe
[1],&wrfs
)) {
4726 chan_misdn_log(9, bc
->port
, "writing %d bytes 2 asterisk\n",bc
->bframe_len
);
4727 ret
=write(ch
->pipe
[1], bc
->bframe
, bc
->bframe_len
);
4730 chan_misdn_log(0, bc
->port
, "Write returned <=0 (err=%s) --> hanging up channel\n",strerror(errno
));
4737 chan_misdn_log(1, bc
->port
, "Wripe Pipe full!\n");
4745 chan_misdn_log(1,bc
->port
,"--> state: %s\n",misdn_get_ch_state(ch
));
4747 switch (ch
->state
) {
4749 case MISDN_PROGRESS
:
4750 if (bc
->nt
&& !ch
->nttimeout
) break;
4753 case MISDN_ALERTING
:
4754 case MISDN_PROCEEDING
:
4755 case MISDN_CALLING_ACKNOWLEDGE
:
4757 bc
->progress_indicator
=8;
4758 hanguptone_indicate(ch
);
4762 misdn_lib_send_event(bc
,EVENT_DISCONNECT
);
4765 case MISDN_WAITING4DIGS
:
4767 bc
->progress_indicator
=8;
4769 hanguptone_indicate(ch
);
4770 misdn_lib_send_event(bc
,EVENT_DISCONNECT
);
4773 misdn_lib_send_event(bc
,EVENT_RELEASE
);
4779 case MISDN_CLEANING
:
4780 chan_misdn_log(1,bc
->port
," --> in state cleaning .. so ingoring, the stack should clean it for us\n");
4784 misdn_lib_send_event(bc
,EVENT_RELEASE_COMPLETE
);
4790 /***************************/
4791 /** Suplementary Services **/
4792 /***************************/
4793 case EVENT_RETRIEVE
:
4795 struct ast_channel
*hold_ast
;
4797 chan_misdn_log(4, bc
->port
, " --> no CH, searching in holded\n");
4798 ch
=find_holded_l3(cl_te
, bc
->l3_id
,1);
4802 ast_log(LOG_WARNING
, "Found no Holded channel, cannot Retrieve\n");
4803 misdn_lib_send_event(bc
, EVENT_RETRIEVE_REJECT
);
4807 /*remember the channel again*/
4809 ch
->state
= MISDN_CONNECTED
;
4811 ch
->hold_info
.port
=0;
4812 ch
->hold_info
.channel
=0;
4814 hold_ast
=ast_bridged_channel(ch
->ast
);
4817 ast_moh_stop(hold_ast
);
4820 if ( misdn_lib_send_event(bc
, EVENT_RETRIEVE_ACKNOWLEDGE
) < 0) {
4821 chan_misdn_log(4, bc
->port
, " --> RETRIEVE_ACK failed\n");
4822 misdn_lib_send_event(bc
, EVENT_RETRIEVE_REJECT
);
4830 struct ast_channel
*bridged
;
4831 misdn_cfg_get( bc
->port
, MISDN_CFG_HOLD_ALLOWED
, &hold_allowed
, sizeof(int));
4833 if (!hold_allowed
) {
4835 chan_misdn_log(-1, bc
->port
, "Hold not allowed this port.\n");
4836 misdn_lib_send_event(bc
, EVENT_HOLD_REJECT
);
4840 bridged
=ast_bridged_channel(ch
->ast
);
4843 chan_misdn_log(2,bc
->port
,"Bridge Partner is of type: %s\n",bridged
->tech
->type
);
4844 ch
->state
= MISDN_HOLDED
;
4845 ch
->l3id
= bc
->l3_id
;
4847 misdn_lib_send_event(bc
, EVENT_HOLD_ACKNOWLEDGE
);
4849 /* XXX This should queue an AST_CONTROL_HOLD frame on this channel
4850 * instead of starting moh on the bridged channel directly */
4851 ast_moh_start(bridged
, NULL
, NULL
);
4853 /*forget the channel now*/
4855 ch
->hold_info
.port
=bc
->port
;
4856 ch
->hold_info
.channel
=bc
->channel
;
4859 misdn_lib_send_event(bc
, EVENT_HOLD_REJECT
);
4860 chan_misdn_log(0, bc
->port
, "We aren't bridged to anybody\n");
4865 case EVENT_FACILITY
:
4867 /* This may come from a call we don't know nothing about, so we ignore it. */
4868 chan_misdn_log(-1, bc
->port
, "Got EVENT_FACILITY but we don't have a ch!\n");
4872 print_facility(&(bc
->fac_in
), bc
);
4874 switch (bc
->fac_in
.Function
) {
4877 struct ast_channel
*bridged
=ast_bridged_channel(ch
->ast
);
4878 struct chan_list
*ch_br
;
4879 if (bridged
&& MISDN_ASTERISK_TECH_PVT(bridged
)) {
4880 ch_br
=MISDN_ASTERISK_TECH_PVT(bridged
);
4881 /*ch->state=MISDN_FACILITY_DEFLECTED;*/
4883 if (ast_exists_extension(bridged
, ch
->context
, (char *)bc
->fac_in
.u
.CDeflection
.DeflectedToNumber
, 1, bc
->oad
)) {
4884 ch_br
->state
=MISDN_DIALING
;
4885 if (pbx_start_chan(ch_br
) < 0) {
4886 chan_misdn_log(-1, ch_br
->bc
->port
, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
4892 misdn_lib_send_event(bc
, EVENT_DISCONNECT
);
4895 case Fac_AOCDCurrency
:
4896 bc
->AOCDtype
= Fac_AOCDCurrency
;
4897 memcpy(&(bc
->AOCD
.currency
), &(bc
->fac_in
.u
.AOCDcur
), sizeof(struct FacAOCDCurrency
));
4898 export_aoc_vars(ch
->originator
, ch
->ast
, bc
);
4900 case Fac_AOCDChargingUnit
:
4901 bc
->AOCDtype
= Fac_AOCDChargingUnit
;
4902 memcpy(&(bc
->AOCD
.chargingUnit
), &(bc
->fac_in
.u
.AOCDchu
), sizeof(struct FacAOCDChargingUnit
));
4903 export_aoc_vars(ch
->originator
, ch
->ast
, bc
);
4906 chan_misdn_log(0, bc
->port
," --> not yet handled: facility type:%p\n", bc
->fac_in
.Function
);
4921 chan_misdn_log(1,0, "Got Unknown Event\n");
4928 /** TE STUFF END **/
4930 /******************************************
4932 * Asterisk Channel Endpoint END
4935 *******************************************/
4939 static int unload_module(void)
4941 /* First, take us out of the channel loop */
4942 ast_log(LOG_VERBOSE
, "-- Unregistering mISDN Channel Driver --\n");
4944 misdn_tasks_destroy();
4946 if (!g_config_initialized
) return 0;
4948 ast_cli_unregister_multiple(chan_misdn_clis
, sizeof(chan_misdn_clis
) / sizeof(struct ast_cli_entry
));
4950 /* ast_unregister_application("misdn_crypt"); */
4951 ast_unregister_application("misdn_set_opt");
4952 ast_unregister_application("misdn_facility");
4953 ast_unregister_application("misdn_check_l2l1");
4955 ast_channel_unregister(&misdn_tech
);
4959 misdn_cfg_destroy();
4960 misdn_lib_destroy();
4964 if (misdn_debug_only
)
4965 free(misdn_debug_only
);
4971 static int load_module(void)
4977 max_ports
=misdn_lib_maxports_get();
4980 ast_log(LOG_ERROR
, "Unable to initialize mISDN\n");
4981 return AST_MODULE_LOAD_DECLINE
;
4984 if (misdn_cfg_init(max_ports
)) {
4985 ast_log(LOG_ERROR
, "Unable to initialize misdn_config.\n");
4986 return AST_MODULE_LOAD_DECLINE
;
4988 g_config_initialized
=1;
4990 misdn_debug
= (int *)malloc(sizeof(int) * (max_ports
+1));
4991 misdn_ports
= (int *)malloc(sizeof(int) * (max_ports
+1));
4992 misdn_cfg_get( 0, MISDN_GEN_DEBUG
, &misdn_debug
[0], sizeof(int));
4993 for (i
= 1; i
<= max_ports
; i
++) {
4994 misdn_debug
[i
] = misdn_debug
[0];
4998 misdn_debug_only
= (int *)calloc(max_ports
+ 1, sizeof(int));
5001 char tempbuf
[BUFFERSIZE
+1];
5002 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE
, tempbuf
, BUFFERSIZE
);
5003 if (strlen(tempbuf
))
5007 misdn_in_calls
= (int *)malloc(sizeof(int) * (max_ports
+1));
5008 misdn_out_calls
= (int *)malloc(sizeof(int) * (max_ports
+1));
5010 for (i
=1; i
<= max_ports
; i
++) {
5011 misdn_in_calls
[i
]=0;
5012 misdn_out_calls
[i
]=0;
5015 ast_mutex_init(&cl_te_lock
);
5016 ast_mutex_init(&release_lock
);
5018 misdn_cfg_update_ptp();
5019 misdn_cfg_get_ports_string(ports
);
5022 chan_misdn_log(0, 0, "Got: %s from get_ports\n",ports
);
5025 int ntflags
=0, ntkc
=0;
5026 char ntfile
[BUFFERSIZE
+1];
5027 struct misdn_lib_iface iface
= {
5028 .cb_event
= cb_events
,
5029 .cb_log
= chan_misdn_log
,
5030 .cb_jb_empty
= chan_misdn_jb_empty
,
5033 if (misdn_lib_init(ports
, &iface
, NULL
))
5034 chan_misdn_log(0, 0, "No te ports initialized\n");
5036 misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFLAGS
, &ntflags
, sizeof(int));
5037 misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFILE
, &ntfile
, BUFFERSIZE
);
5038 misdn_lib_nt_debug_init(ntflags
,ntfile
);
5040 misdn_cfg_get( 0, MISDN_GEN_NTKEEPCALLS
, &ntkc
, sizeof(int));
5041 misdn_lib_nt_keepcalls(ntkc
);
5045 if (ast_channel_register(&misdn_tech
)) {
5046 ast_log(LOG_ERROR
, "Unable to register channel class %s\n", misdn_type
);
5052 ast_cli_register_multiple(chan_misdn_clis
, sizeof(chan_misdn_clis
) / sizeof(struct ast_cli_entry
));
5054 ast_register_application("misdn_set_opt", misdn_set_opt_exec
, "misdn_set_opt",
5055 "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
5056 "Sets mISDN opts. and optargs\n"
5058 "The available options are:\n"
5059 " d - Send display text on called phone, text is the optparam\n"
5060 " n - don't detect dtmf tones on called channel\n"
5061 " h - make digital outgoing call\n"
5062 " c - make crypted outgoing call, param is keyindex\n"
5063 " e - perform echo cancelation on this channel,\n"
5064 " takes taps as arguments (32,64,128,256)\n"
5065 " s - send Non Inband DTMF as inband\n"
5066 " vr - rxgain control\n"
5067 " vt - txgain control\n"
5068 " i - Ignore detected dtmf tones, don't signal them to asterisk, they will be transported inband.\n"
5072 ast_register_application("misdn_facility", misdn_facility_exec
, "misdn_facility",
5073 "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
5074 "Sends the Facility Message FACILITY_TYPE with \n"
5075 "the given Arguments to the current ISDN Channel\n"
5076 "Supported Facilities are:\n"
5078 "type=calldeflect args=Nr where to deflect\n"
5082 ast_register_application("misdn_check_l2l1", misdn_check_l2l1
, "misdn_check_l2l1",
5083 "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
5084 "Checks if the L2 and L1 are up on either the given <port> or\n"
5085 "on the ports in the group with <groupname>\n"
5086 "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
5087 "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
5089 "This application, ensures the L1/L2 state of the Ports in a group\n"
5090 "it is intended to make the pmp_l1_check option redundant and to\n"
5091 "fix a buggy switch config from your provider\n"
5093 "a sample dialplan would look like:\n\n"
5094 "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
5095 "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
5100 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE
, global_tracefile
, BUFFERSIZE
);
5102 /* start the l1 watchers */
5104 for (port
= misdn_cfg_get_next_port(0); port
>= 0; port
= misdn_cfg_get_next_port(port
)) {
5106 misdn_cfg_get(port
, MISDN_CFG_L1_TIMEOUT
, &l1timeout
, sizeof(l1timeout
));
5108 chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port
, l1timeout
);
5109 misdn_tasks_add(l1timeout
* 1000, misdn_l1_task
, &misdn_ports
[port
]);
5113 chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
5120 static int reload(void)
5127 /*** SOME APPS ;)***/
5129 static int misdn_facility_exec(struct ast_channel
*chan
, void *data
)
5131 struct chan_list
*ch
= MISDN_ASTERISK_TECH_PVT(chan
);
5134 chan_misdn_log(0,0,"TYPE: %s\n",chan
->tech
->type
);
5136 if (strcasecmp(chan
->tech
->type
,"mISDN")) {
5137 ast_log(LOG_WARNING
, "misdn_facility makes only sense with chan_misdn channels!\n");
5141 if (ast_strlen_zero((char *)data
)) {
5142 ast_log(LOG_WARNING
, "misdn_facility Requires arguments\n");
5146 tok
=strtok_r((char*)data
,"|", &tokb
) ;
5149 ast_log(LOG_WARNING
, "misdn_facility Requires arguments\n");
5153 if (!strcasecmp(tok
,"calldeflect")) {
5154 tok
=strtok_r(NULL
,"|", &tokb
) ;
5157 ast_log(LOG_WARNING
, "Facility: Call Defl Requires arguments\n");
5160 if (strlen(tok
) >= sizeof(ch
->bc
->fac_out
.u
.CDeflection
.DeflectedToNumber
)) {
5161 ast_log(LOG_WARNING
, "Facility: Number argument too long (up to 15 digits are allowed). Ignoring.\n");
5164 ch
->bc
->fac_out
.Function
= Fac_CD
;
5165 strncpy((char *)ch
->bc
->fac_out
.u
.CDeflection
.DeflectedToNumber
, tok
, sizeof(ch
->bc
->fac_out
.u
.CDeflection
.DeflectedToNumber
));
5166 misdn_lib_send_event(ch
->bc
, EVENT_FACILITY
);
5168 chan_misdn_log(1, ch
->bc
->port
, "Unknown Facility: %s\n",tok
);
5175 static int misdn_check_l2l1(struct ast_channel
*chan
, void *data
)
5177 char group
[BUFFERSIZE
+1];
5184 AST_DECLARE_APP_ARGS(args
,
5185 AST_APP_ARG(grouppar
);
5186 AST_APP_ARG(timeout
);
5189 if (ast_strlen_zero((char *)data
)) {
5190 ast_log(LOG_WARNING
, "misdn_check_l2l1 Requires arguments\n");
5194 AST_STANDARD_APP_ARGS(args
, data
);
5196 if (args
.argc
!= 2) {
5197 ast_log(LOG_WARNING
, "Wrong argument count\n");
5201 /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
5202 timeout
=atoi(args
.timeout
);
5203 port_str
=args
.grouppar
;
5204 if (port_str
[0]=='g' && port_str
[1]==':' ) {
5205 /* We make a group call lets checkout which ports are in my group */
5207 strncpy(group
, port_str
, BUFFERSIZE
);
5208 group
[BUFFERSIZE
-1] = 0;
5209 chan_misdn_log(2, 0, "Checking Ports in group: %s\n",group
);
5211 for ( port
= misdn_cfg_get_next_port(port
);
5213 port
= misdn_cfg_get_next_port(port
))
5215 char cfg_group
[BUFFERSIZE
+1];
5217 chan_misdn_log(2,0,"trying port %d\n",port
);
5219 misdn_cfg_get(port
, MISDN_CFG_GROUPNAME
, cfg_group
, BUFFERSIZE
);
5221 if (!strcasecmp(cfg_group
, group
)) {
5222 port_up
= misdn_lib_port_up(port
, 1);
5225 chan_misdn_log(2, 0, " --> port '%d'\n", port
);
5226 misdn_lib_get_port_up(port
);
5233 port
= atoi(port_str
);
5234 chan_misdn_log(2, 0, "Checking Port: %d\n",port
);
5235 port_up
= misdn_lib_port_up(port
, 1);
5237 misdn_lib_get_port_up(port
);
5244 chan_misdn_log(2, 0, "Waiting for '%d' seconds\n",timeout
);
5251 static int misdn_set_opt_exec(struct ast_channel
*chan
, void *data
)
5253 struct chan_list
*ch
= MISDN_ASTERISK_TECH_PVT(chan
);
5258 int change_jitter
=0;
5260 if (strcasecmp(chan
->tech
->type
,"mISDN")) {
5261 ast_log(LOG_WARNING
, "misdn_set_opt makes only sense with chan_misdn channels!\n");
5265 if (ast_strlen_zero((char *)data
)) {
5266 ast_log(LOG_WARNING
, "misdn_set_opt Requires arguments\n");
5270 for (tok
=strtok_r((char*)data
, ":",&tokb
);
5272 tok
=strtok_r(NULL
,":",&tokb
) ) {
5278 if (tok
[0] == '!' ) {
5286 ast_copy_string(ch
->bc
->display
,++tok
,84);
5287 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: Display:%s\n",ch
->bc
->display
);
5291 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: No DSP\n");
5296 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: jitter\n");
5302 ch
->jb_len
=atoi(++tok
);
5303 chan_misdn_log(1, ch
->bc
->port
, " --> buffer_len:%d\n",ch
->jb_len
);
5306 ch
->jb_upper_threshold
=atoi(++tok
);
5307 chan_misdn_log(1, ch
->bc
->port
, " --> upper_threshold:%d\n",ch
->jb_upper_threshold
);
5312 chan_misdn_log(1, ch
->bc
->port
, " --> nojitter\n");
5317 ch
->jb_upper_threshold
=0;
5318 chan_misdn_log(1, ch
->bc
->port
, " --> buffer_len:%d (default)\n",ch
->jb_len
);
5319 chan_misdn_log(1, ch
->bc
->port
, " --> upper_threshold:%d (default)\n",ch
->jb_upper_threshold
);
5330 if (rxgain
<-8) rxgain
=-8;
5331 if (rxgain
>8) rxgain
=8;
5332 ch
->bc
->rxgain
=rxgain
;
5333 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: Volume:%d\n",rxgain
);
5337 if (txgain
<-8) txgain
=-8;
5338 if (txgain
>8) txgain
=8;
5339 ch
->bc
->txgain
=txgain
;
5340 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: Volume:%d\n",txgain
);
5348 misdn_cfg_get( 0, MISDN_GEN_CRYPT_KEYS
, keys
, sizeof(keys
));
5352 for (i
=0; i
<keyidx
; i
++) {
5353 key
=strsep(&tmp
,",");
5357 ast_copy_string(ch
->bc
->crypt_key
, key
, sizeof(ch
->bc
->crypt_key
));
5360 chan_misdn_log(0, ch
->bc
->port
, "SETOPT: crypt with key:%s\n",ch
->bc
->crypt_key
);
5364 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: EchoCancel\n");
5367 chan_misdn_log(1, ch
->bc
->port
, " --> disabled\n");
5369 *ch
->bc
->pipeline
=0;
5371 ch
->bc
->ec_enable
=0;
5375 update_pipeline_config(ch
->bc
);
5377 ch
->bc
->ec_enable
=1;
5378 ch
->bc
->orig
=ch
->originator
;
5381 ch
->bc
->ec_deftaps
=atoi(tok
);
5389 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: Digital\n");
5391 if (strlen(tok
) > 1 && tok
[1]=='1') {
5392 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: HDLC \n");
5393 if (!ch
->bc
->hdlc
) {
5397 ch
->bc
->capability
=INFO_CAPABILITY_DIGITAL_UNRESTRICTED
;
5401 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: Send DTMF\n");
5402 ch
->bc
->send_dtmf
=1;
5406 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: Faxdetect\n");
5408 misdn_cfg_get(ch
->bc
->port
, MISDN_CFG_FAXDETECT_TIMEOUT
, &ch
->faxdetect_timeout
, sizeof(ch
->faxdetect_timeout
));
5412 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: AST_DSP (for DTMF)\n");
5417 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: callerpres: %s\n",&tok
[1]);
5418 /* CRICH: callingpres!!! */
5419 if (strstr(tok
,"allowed") ) {
5421 } else if (strstr(tok
,"not_screened")) {
5426 chan_misdn_log(1, ch
->bc
->port
, "Ignoring dtmf tones, just use them inband\n");
5435 config_jitterbuffer(ch
);
5438 if (ch
->faxdetect
|| ch
->ast_dsp
) {
5439 if (!ch
->dsp
) ch
->dsp
= ast_dsp_new();
5440 if (ch
->dsp
) ast_dsp_set_features(ch
->dsp
, DSP_FEATURE_DTMF_DETECT
| DSP_FEATURE_FAX_DETECT
);
5441 if (!ch
->trans
) ch
->trans
=ast_translator_build_path(AST_FORMAT_SLINEAR
, AST_FORMAT_ALAW
);
5445 chan_misdn_log(1,ch
->bc
->port
,"SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
5454 int chan_misdn_jb_empty ( struct misdn_bchannel
*bc
, char *buf
, int len
)
5456 struct chan_list
*ch
=find_chan_by_bc(cl_te
, bc
);
5459 return misdn_jb_empty(ch
->jb
, buf
, len
);
5467 /*******************************************************/
5468 /***************** JITTERBUFFER ************************/
5469 /*******************************************************/
5472 /* allocates the jb-structure and initialise the elements*/
5473 struct misdn_jb
*misdn_jb_init(int size
, int upper_threshold
)
5476 struct misdn_jb
*jb
= (struct misdn_jb
*) malloc(sizeof(struct misdn_jb
));
5478 jb
->upper_threshold
= upper_threshold
;
5482 jb
->state_empty
= 0;
5483 jb
->bytes_wrote
= 0;
5484 jb
->samples
= (char *)malloc(size
*sizeof(char));
5487 chan_misdn_log(-1,0,"No free Mem for jb->samples\n");
5491 jb
->ok
= (char *)malloc(size
*sizeof(char));
5494 chan_misdn_log(-1,0,"No free Mem for jb->ok\n");
5498 for(i
=0; i
<size
; i
++)
5501 ast_mutex_init(&jb
->mutexjb
);
5506 /* frees the data and destroys the given jitterbuffer struct */
5507 void misdn_jb_destroy(struct misdn_jb
*jb
)
5509 ast_mutex_destroy(&jb
->mutexjb
);
5515 /* fills the jitterbuffer with len data returns < 0 if there was an
5516 error (bufferoverflow). */
5517 int misdn_jb_fill(struct misdn_jb
*jb
, const char *data
, int len
)
5521 if (!jb
|| ! data
) return 0;
5523 ast_mutex_lock (&jb
->mutexjb
);
5528 for(i
=0; i
<len
; i
++)
5530 jb
->samples
[wp
]=data
[i
];
5532 wp
= (wp
!=jb
->size
-1 ? wp
+1 : 0);
5539 jb
->state_buffer
=wp
-rp
;
5541 jb
->state_buffer
= jb
->size
-rp
+wp
;
5542 chan_misdn_log(9,0,"misdn_jb_fill: written:%d | Bufferstatus:%d p:%x\n",len
,jb
->state_buffer
,jb
);
5549 for(j
=0; j
<jb
->upper_threshold
; j
++)
5550 rp
= (rp
!=0 ? rp
-1 : jb
->size
-1);
5555 ast_mutex_unlock (&jb
->mutexjb
);
5560 if(!jb
->state_empty
)
5562 jb
->bytes_wrote
+=len
;
5563 if(jb
->bytes_wrote
>=jb
->upper_threshold
)
5571 ast_mutex_unlock (&jb
->mutexjb
);
5576 /* gets len bytes out of the jitterbuffer if available, else only the
5577 available data is returned and the return value indicates the number
5579 int misdn_jb_empty(struct misdn_jb
*jb
, char *data
, int len
)
5581 int i
, wp
, rp
, read
=0;
5583 ast_mutex_lock (&jb
->mutexjb
);
5590 for(i
=0; i
<len
; i
++)
5597 ast_mutex_unlock (&jb
->mutexjb
);
5605 data
[i
]=jb
->samples
[rp
];
5607 rp
=(rp
!=jb
->size
-1 ? rp
+1 : 0);
5614 jb
->state_buffer
=wp
-rp
;
5616 jb
->state_buffer
= jb
->size
-rp
+wp
;
5617 chan_misdn_log(9,0,"misdn_jb_empty: read:%d | Bufferstatus:%d p:%x\n",len
,jb
->state_buffer
,jb
);
5622 chan_misdn_log(9,0,"misdn_jb_empty: Wait...requested:%d p:%x\n",len
,jb
);
5624 ast_mutex_unlock (&jb
->mutexjb
);
5632 /*******************************************************/
5633 /*************** JITTERBUFFER END *********************/
5634 /*******************************************************/
5639 void chan_misdn_log(int level
, int port
, char *tmpl
, ...)
5645 if (! ((0 <= port
) && (port
<= max_ports
))) {
5646 ast_log(LOG_WARNING
, "cb_log called with out-of-range port number! (%d)\n", port
);
5651 sprintf(port_buf
,"P[%2d] ",port
);
5654 vsnprintf( buf
, 1023, tmpl
, ap
);
5658 ast_log(LOG_WARNING
, buf
);
5660 else if (misdn_debug_only
[port
] ?
5661 (level
==1 && misdn_debug
[port
]) || (level
==misdn_debug
[port
])
5662 : level
<= misdn_debug
[port
]) {
5664 ast_console_puts(port_buf
);
5665 ast_console_puts(buf
);
5668 if ((level
<= misdn_debug
[0]) && !ast_strlen_zero(global_tracefile
) ) {
5669 time_t tm
= time(NULL
);
5670 char *tmp
=ctime(&tm
),*p
;
5672 FILE *fp
= fopen(global_tracefile
, "a+");
5678 ast_console_puts("Error opening Tracefile: [ ");
5679 ast_console_puts(global_tracefile
);
5680 ast_console_puts(" ] ");
5682 ast_console_puts(strerror(errno
));
5683 ast_console_puts("\n");
5697 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_DEFAULT
, "Channel driver for mISDN Support (BRI/PRI)",
5698 .load
= load_module
,
5699 .unload
= unload_module
,