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
25 * \author Christian Richter <crich@beronet.com>
27 * \extref MISDN http://www.misdn.org/
29 * \ingroup channel_drivers
33 <depend>isdnnet</depend>
34 <depend>misdn</depend>
35 <depend>suppserv</depend>
39 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
44 #include <sys/socket.h>
49 #include <arpa/inet.h>
51 #include <sys/ioctl.h>
54 #include <semaphore.h>
56 #include "asterisk/channel.h"
57 #include "asterisk/config.h"
58 #include "asterisk/logger.h"
59 #include "asterisk/module.h"
60 #include "asterisk/pbx.h"
61 #include "asterisk/options.h"
62 #include "asterisk/io.h"
63 #include "asterisk/frame.h"
64 #include "asterisk/translate.h"
65 #include "asterisk/cli.h"
66 #include "asterisk/musiconhold.h"
67 #include "asterisk/dsp.h"
68 #include "asterisk/translate.h"
69 #include "asterisk/config.h"
70 #include "asterisk/file.h"
71 #include "asterisk/callerid.h"
72 #include "asterisk/indications.h"
73 #include "asterisk/app.h"
74 #include "asterisk/features.h"
75 #include "asterisk/term.h"
76 #include "asterisk/sched.h"
77 #include "asterisk/stringfields.h"
78 #include "asterisk/causes.h"
80 #include "chan_misdn_config.h"
83 char global_tracefile
[BUFFERSIZE
+ 1];
85 static int g_config_initialized
= 0;
101 /*! \brief allocates the jb-structure and initialize the elements */
102 struct misdn_jb
*misdn_jb_init(int size
, int upper_threshold
);
104 /*! \brief frees the data and destroys the given jitterbuffer struct */
105 void misdn_jb_destroy(struct misdn_jb
*jb
);
107 /*! \brief fills the jitterbuffer with len data returns < 0 if there was an
108 error (buffer overrun). */
109 int misdn_jb_fill(struct misdn_jb
*jb
, const char *data
, int len
);
111 /*! \brief gets len bytes out of the jitterbuffer if available, else only the
112 available data is returned and the return value indicates the number
114 int misdn_jb_empty(struct misdn_jb
*jb
, char *data
, int len
);
117 /* BEGIN: chan_misdn.h */
119 ast_mutex_t release_lock
;
121 enum misdn_chan_state
{
122 MISDN_NOTHING
=0, /*!< at beginning */
123 MISDN_WAITING4DIGS
, /*!< when waiting for infos */
124 MISDN_EXTCANTMATCH
, /*!< when asterisk couldn't match our ext */
125 MISDN_INCOMING_SETUP
, /*!< for incoming setups*/
126 MISDN_DIALING
, /*!< when pbx_start */
127 MISDN_PROGRESS
, /*!< we got a progress */
128 MISDN_PROCEEDING
, /*!< we got a progress */
129 MISDN_CALLING
, /*!< when misdn_call is called */
130 MISDN_CALLING_ACKNOWLEDGE
, /*!< when we get SETUP_ACK */
131 MISDN_ALERTING
, /*!< when Alerting */
132 MISDN_BUSY
, /*!< when BUSY */
133 MISDN_CONNECTED
, /*!< when connected */
134 MISDN_PRECONNECTED
, /*!< when connected */
135 MISDN_DISCONNECTED
, /*!< when connected */
136 MISDN_RELEASED
, /*!< when connected */
137 MISDN_BRIDGED
, /*!< when bridged */
138 MISDN_CLEANING
, /*!< when hangup from * but we were connected before */
139 MISDN_HUNGUP_FROM_MISDN
, /*!< when DISCONNECT/RELEASE/REL_COMP came from misdn */
140 MISDN_HUNGUP_FROM_AST
, /*!< when DISCONNECT/RELEASE/REL_COMP came out of misdn_hangup */
141 MISDN_HOLDED
, /*!< if this chan is holded */
142 MISDN_HOLD_DISCONNECT
, /*!< if this chan is holded */
156 char allowed_bearers
[BUFFERSIZE
+ 1];
158 enum misdn_chan_state state
;
159 int need_queue_hangup
;
164 int noautorespond_on_setup
;
171 int incoming_early_audio
;
176 char ast_rd_buf
[4096];
177 struct ast_frame frame
;
179 int faxdetect
; /*!< 0:no 1:yes 2:yes+nojump */
180 int faxdetect_timeout
;
181 struct timeval faxdetect_tv
;
187 int jb_upper_threshold
;
191 struct ast_trans_pvt
*trans
;
193 struct ast_channel
* ast
;
197 struct misdn_bchannel
*bc
;
199 struct hold_info hold_info
;
204 char context
[BUFFERSIZE
];
207 int dropped_frame_cnt
;
214 struct chan_list
*other_ch
;
216 const struct ind_tone_zone_sound
*ts
;
219 int overlap_dial_task
;
220 ast_mutex_t overlap_tv_lock
;
221 struct timeval overlap_tv
;
223 struct chan_list
*peer
;
224 struct chan_list
*next
;
225 struct chan_list
*prev
;
226 struct chan_list
*first
;
231 void export_ch(struct ast_channel
*chan
, struct misdn_bchannel
*bc
, struct chan_list
*ch
);
232 void import_ch(struct ast_channel
*chan
, struct misdn_bchannel
*bc
, struct chan_list
*ch
);
238 struct robin_list
*next
;
239 struct robin_list
*prev
;
241 static struct robin_list
*robin
= NULL
;
245 static struct ast_frame
*process_ast_dsp(struct chan_list
*tmp
, struct ast_frame
*frame
);
249 static inline void free_robin_list_r (struct robin_list
*r
)
253 free_robin_list_r(r
->next
);
260 static void free_robin_list ( void )
262 free_robin_list_r(robin
);
266 static struct robin_list
* get_robin_position (char *group
)
268 struct robin_list
*new;
269 struct robin_list
*iter
= robin
;
270 for (; iter
; iter
= iter
->next
) {
271 if (!strcasecmp(iter
->group
, group
))
274 new = (struct robin_list
*) calloc(1, sizeof(struct robin_list
));
275 new->group
= strndup(group
, strlen(group
));
287 /*! \brief the main schedule context for stuff like l1 watcher, overlap dial, ... */
288 static struct sched_context
*misdn_tasks
= NULL
;
289 static pthread_t misdn_tasks_thread
;
291 static int *misdn_ports
;
293 static void chan_misdn_log(int level
, int port
, char *tmpl
, ...)
294 __attribute__ ((format (printf
, 3, 4)));
296 static struct ast_channel
*misdn_new(struct chan_list
*cl
, int state
, char *exten
, char *callerid
, int format
, int port
, int c
);
297 static void send_digit_to_chan(struct chan_list
*cl
, char digit
);
299 static void hangup_chan(struct chan_list
*ch
);
300 static int pbx_start_chan(struct chan_list
*ch
);
302 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
303 #define MISDN_ASTERISK_PVT(ast) 1
305 #include "asterisk/strings.h"
307 /* #define MISDN_DEBUG 1 */
309 static const char misdn_type
[] = "mISDN";
311 static int tracing
= 0 ;
313 /*! \brief Only alaw and mulaw is allowed for now */
314 static int prefformat
= AST_FORMAT_ALAW
; /* AST_FORMAT_SLINEAR ; AST_FORMAT_ULAW | */
316 static int *misdn_debug
;
317 static int *misdn_debug_only
;
318 static int max_ports
;
320 static int *misdn_in_calls
;
321 static int *misdn_out_calls
;
324 struct chan_list dummy_cl
;
326 struct chan_list
*cl_te
=NULL
;
327 ast_mutex_t cl_te_lock
;
329 static enum event_response_e
330 cb_events(enum event_e event
, struct misdn_bchannel
*bc
, void *user_data
);
332 static void send_cause2ast(struct ast_channel
*ast
, struct misdn_bchannel
*bc
, struct chan_list
*ch
);
334 static void cl_queue_chan(struct chan_list
**list
, struct chan_list
*chan
);
335 static void cl_dequeue_chan(struct chan_list
**list
, struct chan_list
*chan
);
336 static struct chan_list
*find_chan_by_bc(struct chan_list
*list
, struct misdn_bchannel
*bc
);
337 static struct chan_list
*find_chan_by_pid(struct chan_list
*list
, int pid
);
341 static int dialtone_indicate(struct chan_list
*cl
);
342 static int hanguptone_indicate(struct chan_list
*cl
);
343 static int stop_indicate(struct chan_list
*cl
);
345 static int start_bc_tones(struct chan_list
*cl
);
346 static int stop_bc_tones(struct chan_list
*cl
);
347 static void release_chan(struct misdn_bchannel
*bc
);
349 static int misdn_check_l2l1(struct ast_channel
*chan
, void *data
);
350 static int misdn_set_opt_exec(struct ast_channel
*chan
, void *data
);
351 static int misdn_facility_exec(struct ast_channel
*chan
, void *data
);
353 int chan_misdn_jb_empty(struct misdn_bchannel
*bc
, char *buf
, int len
);
356 void debug_numplan(int port
, int numplan
, char *type
);
359 int add_out_calls(int port
);
360 int add_in_calls(int port
);
364 static int update_pipeline_config(struct misdn_bchannel
*bc
);
366 static int update_ec_config(struct misdn_bchannel
*bc
);
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
{
398 char *name
; /*!< Bearer capability name string used in /etc/misdn.conf allowed_bearers */
399 char *display
; /*!< Bearer capability displayable name */
400 int cap
; /*!< SETUP message bearer capability field code value */
401 int deprecated
; /*!< TRUE if this entry is deprecated. (Misspelled or bad name to use) */
405 static const struct allowed_bearers allowed_bearers_array
[]= {
406 /* Name, Displayable Name Bearer Capability, Deprecated */
407 { "speech", "Speech", INFO_CAPABILITY_SPEECH
, 0 },
408 { "3_1khz", "3.1KHz Audio", INFO_CAPABILITY_AUDIO_3_1K
, 0 },
409 { "digital_unrestricted", "Unrestricted Digital", INFO_CAPABILITY_DIGITAL_UNRESTRICTED
, 0 },
410 { "digital_restricted", "Restricted Digital", INFO_CAPABILITY_DIGITAL_RESTRICTED
, 0 },
411 { "digital_restriced", "Restricted Digital", INFO_CAPABILITY_DIGITAL_RESTRICTED
, 1 }, /* Allow misspelling for backwards compatibility */
412 { "video", "Video", INFO_CAPABILITY_VIDEO
, 0 }
416 static const char *bearer2str(int cap
)
420 for (index
= 0; index
< ARRAY_LEN(allowed_bearers_array
); ++index
) {
421 if (allowed_bearers_array
[index
].cap
== cap
) {
422 return allowed_bearers_array
[index
].display
;
426 return "Unknown Bearer";
430 static void print_facility(struct FacParm
*fac
, struct misdn_bchannel
*bc
)
432 switch (fac
->Function
) {
434 chan_misdn_log(1,bc
->port
," --> calldeflect to: %s, screened: %s\n", fac
->u
.CDeflection
.DeflectedToNumber
,
435 fac
->u
.CDeflection
.PresentationAllowed
? "yes" : "no");
437 case Fac_AOCDCurrency
:
438 if (fac
->u
.AOCDcur
.chargeNotAvailable
)
439 chan_misdn_log(1,bc
->port
," --> AOCD currency: charge not available\n");
440 else if (fac
->u
.AOCDcur
.freeOfCharge
)
441 chan_misdn_log(1,bc
->port
," --> AOCD currency: free of charge\n");
442 else if (fac
->u
.AOCDchu
.billingId
>= 0)
443 chan_misdn_log(1,bc
->port
," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s billingId:%d\n",
444 fac
->u
.AOCDcur
.currency
, fac
->u
.AOCDcur
.currencyAmount
, fac
->u
.AOCDcur
.multiplier
,
445 (fac
->u
.AOCDcur
.typeOfChargingInfo
== 0) ? "subTotal" : "total", fac
->u
.AOCDcur
.billingId
);
447 chan_misdn_log(1,bc
->port
," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s\n",
448 fac
->u
.AOCDcur
.currency
, fac
->u
.AOCDcur
.currencyAmount
, fac
->u
.AOCDcur
.multiplier
,
449 (fac
->u
.AOCDcur
.typeOfChargingInfo
== 0) ? "subTotal" : "total");
451 case Fac_AOCDChargingUnit
:
452 if (fac
->u
.AOCDchu
.chargeNotAvailable
)
453 chan_misdn_log(1,bc
->port
," --> AOCD charging unit: charge not available\n");
454 else if (fac
->u
.AOCDchu
.freeOfCharge
)
455 chan_misdn_log(1,bc
->port
," --> AOCD charging unit: free of charge\n");
456 else if (fac
->u
.AOCDchu
.billingId
>= 0)
457 chan_misdn_log(1,bc
->port
," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
458 fac
->u
.AOCDchu
.recordedUnits
, (fac
->u
.AOCDchu
.typeOfChargingInfo
== 0) ? "subTotal" : "total", fac
->u
.AOCDchu
.billingId
);
460 chan_misdn_log(1,bc
->port
," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
461 fac
->u
.AOCDchu
.recordedUnits
, (fac
->u
.AOCDchu
.typeOfChargingInfo
== 0) ? "subTotal" : "total");
464 chan_misdn_log(1,bc
->port
," --> unknown facility\n");
469 static void print_bearer(struct misdn_bchannel
*bc
)
472 chan_misdn_log(2, bc
->port
, " --> Bearer: %s\n",bearer2str(bc
->capability
));
475 case INFO_CODEC_ALAW
:
476 chan_misdn_log(2, bc
->port
, " --> Codec: Alaw\n");
478 case INFO_CODEC_ULAW
:
479 chan_misdn_log(2, bc
->port
, " --> Codec: Ulaw\n");
484 static void export_aoc_vars(int originator
, struct ast_channel
*ast
, struct misdn_bchannel
*bc
)
491 if (originator
== ORG_AST
) {
492 ast
= ast_bridged_channel(ast
);
497 switch (bc
->AOCDtype
) {
498 case Fac_AOCDCurrency
:
499 pbx_builtin_setvar_helper(ast
, "AOCD_Type", "currency");
500 if (bc
->AOCD
.currency
.chargeNotAvailable
)
501 pbx_builtin_setvar_helper(ast
, "AOCD_ChargeAvailable", "no");
503 pbx_builtin_setvar_helper(ast
, "AOCD_ChargeAvailable", "yes");
504 if (bc
->AOCD
.currency
.freeOfCharge
)
505 pbx_builtin_setvar_helper(ast
, "AOCD_FreeOfCharge", "yes");
507 pbx_builtin_setvar_helper(ast
, "AOCD_FreeOfCharge", "no");
508 if (snprintf(buf
, sizeof(buf
), "%d %s", bc
->AOCD
.currency
.currencyAmount
* bc
->AOCD
.currency
.multiplier
, bc
->AOCD
.currency
.currency
) < sizeof(buf
)) {
509 pbx_builtin_setvar_helper(ast
, "AOCD_Amount", buf
);
510 if (bc
->AOCD
.currency
.billingId
>= 0 && snprintf(buf
, sizeof(buf
), "%d", bc
->AOCD
.currency
.billingId
) < sizeof(buf
))
511 pbx_builtin_setvar_helper(ast
, "AOCD_BillingId", buf
);
516 case Fac_AOCDChargingUnit
:
517 pbx_builtin_setvar_helper(ast
, "AOCD_Type", "charging_unit");
518 if (bc
->AOCD
.chargingUnit
.chargeNotAvailable
)
519 pbx_builtin_setvar_helper(ast
, "AOCD_ChargeAvailable", "no");
521 pbx_builtin_setvar_helper(ast
, "AOCD_ChargeAvailable", "yes");
522 if (bc
->AOCD
.chargingUnit
.freeOfCharge
)
523 pbx_builtin_setvar_helper(ast
, "AOCD_FreeOfCharge", "yes");
525 pbx_builtin_setvar_helper(ast
, "AOCD_FreeOfCharge", "no");
526 if (snprintf(buf
, sizeof(buf
), "%d", bc
->AOCD
.chargingUnit
.recordedUnits
) < sizeof(buf
)) {
527 pbx_builtin_setvar_helper(ast
, "AOCD_RecordedUnits", buf
);
528 if (bc
->AOCD
.chargingUnit
.billingId
>= 0 && snprintf(buf
, sizeof(buf
), "%d", bc
->AOCD
.chargingUnit
.billingId
) < sizeof(buf
))
529 pbx_builtin_setvar_helper(ast
, "AOCD_BillingId", buf
);
539 /*************** Helpers END *************/
541 static void sighandler(int sig
)
544 static void* misdn_tasks_thread_func (void *data
)
549 sa
.sa_handler
= sighandler
;
550 sa
.sa_flags
= SA_NODEFER
;
551 sigemptyset(&sa
.sa_mask
);
552 sigaddset(&sa
.sa_mask
, SIGUSR1
);
553 sigaction(SIGUSR1
, &sa
, NULL
);
555 sem_post((sem_t
*)data
);
558 wait
= ast_sched_wait(misdn_tasks
);
561 if (poll(NULL
, 0, wait
) < 0)
562 chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
563 ast_sched_runq(misdn_tasks
);
568 static void misdn_tasks_init (void)
573 if (sem_init(&blocker
, 0, 0)) {
574 perror("chan_misdn: Failed to initialize semaphore!");
578 chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
580 misdn_tasks
= sched_context_create();
581 pthread_create(&misdn_tasks_thread
, NULL
, misdn_tasks_thread_func
, &blocker
);
583 while (sem_wait(&blocker
) && --i
);
584 sem_destroy(&blocker
);
587 static void misdn_tasks_destroy (void)
590 chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
591 if ( pthread_cancel(misdn_tasks_thread
) == 0 ) {
592 cb_log(4, 0, "Joining misdn_tasks thread\n");
593 pthread_join(misdn_tasks_thread
, NULL
);
595 sched_context_destroy(misdn_tasks
);
599 static inline void misdn_tasks_wakeup (void)
601 pthread_kill(misdn_tasks_thread
, SIGUSR1
);
604 static inline int _misdn_tasks_add_variable (int timeout
, ast_sched_cb callback
, const void *data
, int variable
)
611 task_id
= ast_sched_add_variable(misdn_tasks
, timeout
, callback
, data
, variable
);
612 misdn_tasks_wakeup();
617 static int misdn_tasks_add (int timeout
, ast_sched_cb callback
, const void *data
)
619 return _misdn_tasks_add_variable(timeout
, callback
, data
, 0);
622 static int misdn_tasks_add_variable (int timeout
, ast_sched_cb callback
, const void *data
)
624 return _misdn_tasks_add_variable(timeout
, callback
, data
, 1);
627 static void misdn_tasks_remove (int task_id
)
629 AST_SCHED_DEL(misdn_tasks
, task_id
);
632 static int misdn_l1_task (const void *data
)
634 misdn_lib_isdn_l1watcher(*(int *)data
);
635 chan_misdn_log(5, *(int *)data
, "L1watcher timeout\n");
639 static int misdn_overlap_dial_task (const void *data
)
641 struct timeval tv_end
, tv_now
;
643 struct chan_list
*ch
= (struct chan_list
*)data
;
645 chan_misdn_log(4, ch
->bc
->port
, "overlap dial task, chan_state: %d\n", ch
->state
);
647 if (ch
->state
!= MISDN_WAITING4DIGS
) {
648 ch
->overlap_dial_task
= -1;
652 ast_mutex_lock(&ch
->overlap_tv_lock
);
653 tv_end
= ch
->overlap_tv
;
654 ast_mutex_unlock(&ch
->overlap_tv_lock
);
656 tv_end
.tv_sec
+= ch
->overlap_dial
;
657 tv_now
= ast_tvnow();
659 diff
= ast_tvdiff_ms(tv_end
, tv_now
);
662 char *dad
=ch
->bc
->dad
, sexten
[]="s";
663 /* if we are 100ms near the timeout, we are satisfied.. */
666 if (ast_strlen_zero(ch
->bc
->dad
)) {
668 strcpy(ch
->ast
->exten
, sexten
);
671 if (ast_exists_extension(ch
->ast
, ch
->context
, dad
, 1, ch
->bc
->oad
)) {
672 ch
->state
=MISDN_DIALING
;
673 if (pbx_start_chan(ch
) < 0) {
674 chan_misdn_log(-1, ch
->bc
->port
, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
675 goto misdn_overlap_dial_task_disconnect
;
678 misdn_overlap_dial_task_disconnect
:
679 hanguptone_indicate(ch
);
680 ch
->bc
->out_cause
= AST_CAUSE_UNALLOCATED
;
681 ch
->state
=MISDN_CLEANING
;
682 misdn_lib_send_event(ch
->bc
, EVENT_DISCONNECT
);
684 ch
->overlap_dial_task
= -1;
690 static void send_digit_to_chan(struct chan_list
*cl
, char digit
)
692 static const char* dtmf_tones
[] = {
693 "!941+1336/100,!0/100", /* 0 */
694 "!697+1209/100,!0/100", /* 1 */
695 "!697+1336/100,!0/100", /* 2 */
696 "!697+1477/100,!0/100", /* 3 */
697 "!770+1209/100,!0/100", /* 4 */
698 "!770+1336/100,!0/100", /* 5 */
699 "!770+1477/100,!0/100", /* 6 */
700 "!852+1209/100,!0/100", /* 7 */
701 "!852+1336/100,!0/100", /* 8 */
702 "!852+1477/100,!0/100", /* 9 */
703 "!697+1633/100,!0/100", /* A */
704 "!770+1633/100,!0/100", /* B */
705 "!852+1633/100,!0/100", /* C */
706 "!941+1633/100,!0/100", /* D */
707 "!941+1209/100,!0/100", /* * */
708 "!941+1477/100,!0/100" }; /* # */
709 struct ast_channel
*chan
=cl
->ast
;
711 if (digit
>= '0' && digit
<='9')
712 ast_playtones_start(chan
,0,dtmf_tones
[digit
-'0'], 0);
713 else if (digit
>= 'A' && digit
<= 'D')
714 ast_playtones_start(chan
,0,dtmf_tones
[digit
-'A'+10], 0);
715 else if (digit
== '*')
716 ast_playtones_start(chan
,0,dtmf_tones
[14], 0);
717 else if (digit
== '#')
718 ast_playtones_start(chan
,0,dtmf_tones
[15], 0);
721 ast_log(LOG_DEBUG
, "Unable to handle DTMF tone '%c' for '%s'\n", digit
, chan
->name
);
725 /*** CLI HANDLING ***/
726 static int misdn_set_debug(int fd
, int argc
, char *argv
[])
730 if (argc
!= 4 && argc
!= 5 && argc
!= 6 && argc
!= 7)
731 return RESULT_SHOWUSAGE
;
733 level
= atoi(argv
[3]);
742 if (strncasecmp(argv
[4], "only", strlen(argv
[4])))
743 return RESULT_SHOWUSAGE
;
748 for (i
= 0; i
<= max_ports
; i
++) {
749 misdn_debug
[i
] = level
;
750 misdn_debug_only
[i
] = only
;
752 ast_cli(fd
, "changing debug level for all ports to %d%s\n",misdn_debug
[0], only
?" (only)":"");
759 if (strncasecmp(argv
[4], "port", strlen(argv
[4])))
760 return RESULT_SHOWUSAGE
;
761 port
= atoi(argv
[5]);
762 if (port
<= 0 || port
> max_ports
) {
765 ast_cli(fd
, "port number not valid! no ports available so you won't get lucky with any number here...\n");
768 ast_cli(fd
, "port number not valid! only port 1 is available.\n");
771 ast_cli(fd
, "port number not valid! only ports 1 to %d are available.\n", max_ports
);
776 if (strncasecmp(argv
[6], "only", strlen(argv
[6])))
777 return RESULT_SHOWUSAGE
;
779 misdn_debug_only
[port
] = 1;
781 misdn_debug_only
[port
] = 0;
782 misdn_debug
[port
] = level
;
783 ast_cli(fd
, "changing debug level to %d%s for port %d\n", misdn_debug
[port
], misdn_debug_only
[port
]?" (only)":"", port
);
789 static int misdn_set_crypt_debug(int fd
, int argc
, char *argv
[])
791 if (argc
!= 5) return RESULT_SHOWUSAGE
;
796 static int misdn_port_block(int fd
, int argc
, char *argv
[])
801 return RESULT_SHOWUSAGE
;
803 port
= atoi(argv
[3]);
805 misdn_lib_port_block(port
);
810 static int misdn_port_unblock(int fd
, int argc
, char *argv
[])
815 return RESULT_SHOWUSAGE
;
817 port
= atoi(argv
[3]);
819 misdn_lib_port_unblock(port
);
825 static int misdn_restart_port (int fd
, int argc
, char *argv
[])
830 return RESULT_SHOWUSAGE
;
832 port
= atoi(argv
[3]);
834 misdn_lib_port_restart(port
);
839 static int misdn_restart_pid (int fd
, int argc
, char *argv
[])
844 return RESULT_SHOWUSAGE
;
848 misdn_lib_pid_restart(pid
);
853 static int misdn_port_up (int fd
, int argc
, char *argv
[])
858 return RESULT_SHOWUSAGE
;
860 port
= atoi(argv
[3]);
862 misdn_lib_get_port_up(port
);
867 static int misdn_port_down (int fd
, int argc
, char *argv
[])
872 return RESULT_SHOWUSAGE
;
874 port
= atoi(argv
[3]);
876 misdn_lib_get_port_down(port
);
881 static inline void show_config_description (int fd
, enum misdn_cfg_elements elem
)
883 char section
[BUFFERSIZE
];
884 char name
[BUFFERSIZE
];
885 char desc
[BUFFERSIZE
];
886 char def
[BUFFERSIZE
];
887 char tmp
[BUFFERSIZE
];
889 misdn_cfg_get_name(elem
, tmp
, sizeof(tmp
));
890 term_color(name
, tmp
, COLOR_BRWHITE
, 0, sizeof(tmp
));
891 misdn_cfg_get_desc(elem
, desc
, sizeof(desc
), def
, sizeof(def
));
893 if (elem
< MISDN_CFG_LAST
)
894 term_color(section
, "PORTS SECTION", COLOR_YELLOW
, 0, sizeof(section
));
896 term_color(section
, "GENERAL SECTION", COLOR_YELLOW
, 0, sizeof(section
));
899 ast_cli(fd
, "[%s] %s (Default: %s)\n\t%s\n", section
, name
, def
, desc
);
901 ast_cli(fd
, "[%s] %s\n\t%s\n", section
, name
, desc
);
904 static int misdn_show_config (int fd
, int argc
, char *argv
[])
906 char buffer
[BUFFERSIZE
];
907 enum misdn_cfg_elements elem
;
913 if (!strcmp(argv
[3], "description")) {
915 enum misdn_cfg_elements elem
= misdn_cfg_get_elem(argv
[4]);
916 if (elem
== MISDN_CFG_FIRST
)
917 ast_cli(fd
, "Unknown element: %s\n", argv
[4]);
919 show_config_description(fd
, elem
);
922 return RESULT_SHOWUSAGE
;
924 if (!strcmp(argv
[3], "descriptions")) {
925 if ((argc
== 4) || ((argc
== 5) && !strcmp(argv
[4], "general"))) {
926 for (elem
= MISDN_GEN_FIRST
+ 1; elem
< MISDN_GEN_LAST
; ++elem
) {
927 show_config_description(fd
, elem
);
932 if ((argc
== 4) || ((argc
== 5) && !strcmp(argv
[4], "ports"))) {
933 for (elem
= MISDN_CFG_FIRST
+ 1; elem
< MISDN_CFG_LAST
- 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem
) {
934 show_config_description(fd
, elem
);
939 return ok
? 0 : RESULT_SHOWUSAGE
;
941 if (!sscanf(argv
[3], "%d", &onlyport
) || onlyport
< 0) {
942 ast_cli(fd
, "Unknown option: %s\n", argv
[3]);
943 return RESULT_SHOWUSAGE
;
947 if (argc
== 3 || onlyport
== 0) {
948 ast_cli(fd
, "Misdn General-Config:\n");
949 for (elem
= MISDN_GEN_FIRST
+ 1, linebreak
= 1; elem
< MISDN_GEN_LAST
; elem
++, linebreak
++) {
950 misdn_cfg_get_config_string(0, elem
, buffer
, BUFFERSIZE
);
951 ast_cli(fd
, "%-36s%s", buffer
, !(linebreak
% 2) ? "\n" : "");
957 int port
= misdn_cfg_get_next_port(0);
958 for (; port
> 0; port
= misdn_cfg_get_next_port(port
)) {
959 ast_cli(fd
, "\n[PORT %d]\n", port
);
960 for (elem
= MISDN_CFG_FIRST
+ 1, linebreak
= 1; elem
< MISDN_CFG_LAST
; elem
++, linebreak
++) {
961 misdn_cfg_get_config_string(port
, elem
, buffer
, BUFFERSIZE
);
962 ast_cli(fd
, "%-36s%s", buffer
, !(linebreak
% 2) ? "\n" : "");
969 if (misdn_cfg_is_port_valid(onlyport
)) {
970 ast_cli(fd
, "[PORT %d]\n", onlyport
);
971 for (elem
= MISDN_CFG_FIRST
+ 1, linebreak
= 1; elem
< MISDN_CFG_LAST
; elem
++, linebreak
++) {
972 misdn_cfg_get_config_string(onlyport
, elem
, buffer
, BUFFERSIZE
);
973 ast_cli(fd
, "%-36s%s", buffer
, !(linebreak
% 2) ? "\n" : "");
977 ast_cli(fd
, "Port %d is not active!\n", onlyport
);
984 struct state_struct
{
985 enum misdn_chan_state state
;
989 static struct state_struct state_array
[] = {
990 {MISDN_NOTHING
,"NOTHING"}, /* at beginning */
991 {MISDN_WAITING4DIGS
,"WAITING4DIGS"}, /* when waiting for infos */
992 {MISDN_EXTCANTMATCH
,"EXTCANTMATCH"}, /* when asterisk couldn't match our ext */
993 {MISDN_INCOMING_SETUP
,"INCOMING SETUP"}, /* when pbx_start */
994 {MISDN_DIALING
,"DIALING"}, /* when pbx_start */
995 {MISDN_PROGRESS
,"PROGRESS"}, /* when pbx_start */
996 {MISDN_PROCEEDING
,"PROCEEDING"}, /* when pbx_start */
997 {MISDN_CALLING
,"CALLING"}, /* when misdn_call is called */
998 {MISDN_CALLING_ACKNOWLEDGE
,"CALLING_ACKNOWLEDGE"}, /* when misdn_call is called */
999 {MISDN_ALERTING
,"ALERTING"}, /* when Alerting */
1000 {MISDN_BUSY
,"BUSY"}, /* when BUSY */
1001 {MISDN_CONNECTED
,"CONNECTED"}, /* when connected */
1002 {MISDN_PRECONNECTED
,"PRECONNECTED"}, /* when connected */
1003 {MISDN_DISCONNECTED
,"DISCONNECTED"}, /* when connected */
1004 {MISDN_RELEASED
,"RELEASED"}, /* when connected */
1005 {MISDN_BRIDGED
,"BRIDGED"}, /* when bridged */
1006 {MISDN_CLEANING
,"CLEANING"}, /* when hangup from * but we were connected before */
1007 {MISDN_HUNGUP_FROM_MISDN
,"HUNGUP_FROM_MISDN"}, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
1008 {MISDN_HOLDED
,"HOLDED"}, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
1009 {MISDN_HOLD_DISCONNECT
,"HOLD_DISCONNECT"}, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
1010 {MISDN_HUNGUP_FROM_AST
,"HUNGUP_FROM_AST"} /* when DISCONNECT/RELEASE/REL_COMP came out of misdn_hangup */
1013 static const char *misdn_get_ch_state(struct chan_list
*p
)
1016 static char state
[8];
1018 if( !p
) return NULL
;
1020 for (i
= 0; i
< sizeof(state_array
) / sizeof(struct state_struct
); i
++) {
1021 if (state_array
[i
].state
== p
->state
)
1022 return state_array
[i
].txt
;
1025 snprintf(state
, sizeof(state
), "%d", p
->state
) ;
1032 static void reload_config(void)
1036 if (!g_config_initialized
) {
1037 ast_log(LOG_WARNING
, "chan_misdn is not initialized properly, still reloading ?\n");
1043 misdn_cfg_update_ptp();
1044 misdn_cfg_get(0, MISDN_GEN_TRACEFILE
, global_tracefile
, BUFFERSIZE
);
1045 misdn_cfg_get(0, MISDN_GEN_DEBUG
, &cfg_debug
, sizeof(int));
1047 for (i
= 0; i
<= max_ports
; i
++) {
1048 misdn_debug
[i
] = cfg_debug
;
1049 misdn_debug_only
[i
] = 0;
1053 static int misdn_reload (int fd
, int argc
, char *argv
[])
1055 ast_cli(fd
, "Reloading mISDN configuration\n");
1060 static void print_bc_info (int fd
, struct chan_list
*help
, struct misdn_bchannel
*bc
)
1062 struct ast_channel
*ast
= help
->ast
;
1064 "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
1066 bc
->pid
, bc
->port
, bc
->channel
,
1067 bc
->nt
? "NT" : "TE",
1068 help
->originator
== ORG_AST
? "*" : "I",
1069 ast
? ast
->exten
: NULL
,
1070 ast
? ast
->cid
.cid_num
: NULL
,
1072 ast
? ast
->context
: NULL
,
1073 misdn_get_ch_state(help
)
1075 if (misdn_debug
[bc
->port
] > 0)
1077 " --> astname: %s\n"
1078 " --> ch_l3id: %x\n"
1079 " --> ch_addr: %x\n"
1080 " --> bc_addr: %x\n"
1081 " --> bc_l3id: %x\n"
1082 " --> display: %s\n"
1083 " --> activated: %d\n"
1085 " --> capability: %s\n"
1087 " --> pipeline: %s\n"
1089 " --> echo_cancel: %d\n"
1091 " --> notone : rx %d tx:%d\n"
1092 " --> bc_hold: %d\n",
1097 bc
? bc
->l3_id
: -1,
1101 bc_state2str(bc
->bc_state
),
1102 bearer2str(bc
->capability
),
1109 help
->norxtone
, help
->notxtone
,
1115 static int misdn_show_cls (int fd
, int argc
, char *argv
[])
1117 struct chan_list
*help
;
1121 ast_cli(fd
, "Channel List: %p\n", cl_te
);
1123 for (; help
; help
= help
->next
) {
1124 struct misdn_bchannel
*bc
= help
->bc
;
1125 struct ast_channel
*ast
= help
->ast
;
1128 ast_cli(fd
, "chan_list obj. with l3id:%x has no bc and no ast Leg\n", help
->l3id
);
1131 ast_cli(fd
, "bc with pid:%d has no Ast Leg\n", bc
->pid
);
1135 if (misdn_debug
[0] > 2)
1136 ast_cli(fd
, "Bc:%p Ast:%p\n", bc
, ast
);
1138 print_bc_info(fd
, help
, bc
);
1140 if (help
->state
== MISDN_HOLDED
) {
1141 ast_cli(fd
, "ITS A HOLDED BC:\n");
1142 ast_cli(fd
, " --> l3_id: %x\n"
1143 " --> dad:%s oad:%s\n"
1144 " --> hold_port: %d\n"
1145 " --> hold_channel: %d\n",
1149 help
->hold_info
.port
,
1150 help
->hold_info
.channel
1153 ast_cli(fd
, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast
->exten
, ast
->cid
.cid_num
);
1158 misdn_dump_chanlist();
1163 static int misdn_show_cl (int fd
, int argc
, char *argv
[])
1165 struct chan_list
*help
;
1168 return RESULT_SHOWUSAGE
;
1172 for (; help
; help
= help
->next
) {
1173 struct misdn_bchannel
*bc
= help
->bc
;
1174 struct ast_channel
*ast
= help
->ast
;
1177 if (!strcasecmp(ast
->name
,argv
[3])) {
1178 print_bc_info(fd
, help
, bc
);
1190 static int misdn_set_tics (int fd
, int argc
, char *argv
[])
1193 return RESULT_SHOWUSAGE
;
1195 MAXTICS
= atoi(argv
[3]);
1200 static int misdn_show_stacks (int fd
, int argc
, char *argv
[])
1204 ast_cli(fd
, "BEGIN STACK_LIST:\n");
1205 for (port
= misdn_cfg_get_next_port(0); port
> 0;
1206 port
= misdn_cfg_get_next_port(port
)) {
1208 get_show_stack_details(port
, buf
);
1209 ast_cli(fd
, " %s Debug:%d%s\n", buf
, misdn_debug
[port
], misdn_debug_only
[port
] ? "(only)" : "");
1215 static int misdn_show_ports_stats (int fd
, int argc
, char *argv
[])
1219 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
]);
1229 static int misdn_show_port (int fd
, int argc
, char *argv
[])
1235 return RESULT_SHOWUSAGE
;
1237 port
= atoi(argv
[3]);
1239 ast_cli(fd
, "BEGIN STACK_LIST:\n");
1240 get_show_stack_details(port
, buf
);
1241 ast_cli(fd
, " %s Debug:%d%s\n", buf
, misdn_debug
[port
], misdn_debug_only
[port
] ? "(only)" : "");
1246 static int misdn_send_cd (int fd
, int argc
, char *argv
[])
1250 struct chan_list
*tmp
;
1253 return RESULT_SHOWUSAGE
;
1260 ast_cli(fd
, "Sending Calldeflection (%s) to %s\n", nr
, channame
);
1261 tmp
= get_chan_by_ast_name(channame
);
1263 ast_cli(fd
, "Sending CD with nr %s to %s failed: Channel does not exist.\n",nr
, channame
);
1267 if (strlen(nr
) >= 15) {
1268 ast_cli(fd
, "Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n",nr
, channame
);
1271 tmp
->bc
->fac_out
.Function
= Fac_CD
;
1272 ast_copy_string((char *)tmp
->bc
->fac_out
.u
.CDeflection
.DeflectedToNumber
, nr
, sizeof(tmp
->bc
->fac_out
.u
.CDeflection
.DeflectedToNumber
));
1273 misdn_lib_send_event(tmp
->bc
, EVENT_FACILITY
);
1279 static int misdn_send_restart(int fd
, int argc
, char *argv
[])
1284 if (argc
< 4 || argc
> 5)
1285 return RESULT_SHOWUSAGE
;
1287 port
= atoi(argv
[3]);
1290 channel
= atoi(argv
[4]);
1291 misdn_lib_send_restart(port
, channel
);
1293 misdn_lib_send_restart(port
, -1);
1299 static int misdn_send_digit (int fd
, int argc
, char *argv
[])
1303 struct chan_list
*tmp
;
1307 return RESULT_SHOWUSAGE
;
1311 msglen
= strlen(msg
);
1313 ast_cli(fd
, "Sending %s to %s\n", msg
, channame
);
1315 tmp
= get_chan_by_ast_name(channame
);
1317 ast_cli(fd
, "Sending %s to %s failed Channel does not exist\n", msg
, channame
);
1321 for (i
= 0; i
< msglen
; i
++) {
1322 ast_cli(fd
, "Sending: %c\n", msg
[i
]);
1323 send_digit_to_chan(tmp
, msg
[i
]);
1324 /* res = ast_safe_sleep(tmp->ast, 250); */
1326 /* res = ast_waitfor(tmp->ast,100); */
1329 ast_dtmf_stream(tmp
->ast
, NULL
, msg
, 250);
1335 static int misdn_toggle_echocancel (int fd
, int argc
, char *argv
[])
1338 struct chan_list
*tmp
;
1341 return RESULT_SHOWUSAGE
;
1345 ast_cli(fd
, "Toggling EchoCancel on %s\n", channame
);
1347 tmp
= get_chan_by_ast_name(channame
);
1349 ast_cli(fd
, "Toggling EchoCancel %s failed Channel does not exist\n", channame
);
1353 tmp
->toggle_ec
= tmp
->toggle_ec
? 0 : 1;
1355 if (tmp
->toggle_ec
) {
1357 update_pipeline_config(tmp
->bc
);
1359 update_ec_config(tmp
->bc
);
1361 manager_ec_enable(tmp
->bc
);
1363 manager_ec_disable(tmp
->bc
);
1369 static int misdn_send_display (int fd
, int argc
, char *argv
[])
1373 struct chan_list
*tmp
;
1376 return RESULT_SHOWUSAGE
;
1381 ast_cli(fd
, "Sending %s to %s\n", msg
, channame
);
1382 tmp
= get_chan_by_ast_name(channame
);
1384 if (tmp
&& tmp
->bc
) {
1385 ast_copy_string(tmp
->bc
->display
, msg
, sizeof(tmp
->bc
->display
));
1386 misdn_lib_send_event(tmp
->bc
, EVENT_INFORMATION
);
1388 ast_cli(fd
, "No such channel %s\n", channame
);
1389 return RESULT_FAILURE
;
1392 return RESULT_SUCCESS
;
1395 static char *complete_ch_helper(const char *line
, const char *word
, int pos
, int state
, int rpos
)
1397 struct ast_channel
*c
;
1402 c
= ast_channel_walk_locked(NULL
);
1404 if (!strncasecmp(word
, c
->name
, strlen(word
))) {
1405 if (++which
> state
)
1408 ast_mutex_unlock(&c
->lock
);
1409 c
= ast_channel_walk_locked(c
);
1412 ret
= strdup(c
->name
);
1413 ast_mutex_unlock(&c
->lock
);
1419 static char *complete_ch(const char *line
, const char *word
, int pos
, int state
)
1421 return complete_ch_helper(line
, word
, pos
, state
, 3);
1424 static char *complete_debug_port (const char *line
, const char *word
, int pos
, int state
)
1432 return strdup("port");
1433 else if (*word
== 'o')
1434 return strdup("only");
1438 return strdup("only");
1444 static char *complete_show_config (const char *line
, const char *word
, int pos
, int state
)
1446 char buffer
[BUFFERSIZE
];
1447 enum misdn_cfg_elements elem
;
1448 int wordlen
= strlen(word
);
1454 if ((!strncmp(word
, "description", wordlen
)) && (++which
> state
))
1455 return strdup("description");
1456 if ((!strncmp(word
, "descriptions", wordlen
)) && (++which
> state
))
1457 return strdup("descriptions");
1458 if ((!strncmp(word
, "0", wordlen
)) && (++which
> state
))
1460 while ((port
= misdn_cfg_get_next_port(port
)) != -1) {
1461 snprintf(buffer
, sizeof(buffer
), "%d", port
);
1462 if ((!strncmp(word
, buffer
, wordlen
)) && (++which
> state
)) {
1463 return strdup(buffer
);
1468 if (strstr(line
, "description ")) {
1469 for (elem
= MISDN_CFG_FIRST
+ 1; elem
< MISDN_GEN_LAST
; ++elem
) {
1470 if ((elem
== MISDN_CFG_LAST
) || (elem
== MISDN_GEN_FIRST
))
1472 misdn_cfg_get_name(elem
, buffer
, BUFFERSIZE
);
1473 if (!wordlen
|| !strncmp(word
, buffer
, wordlen
)) {
1474 if (++which
> state
)
1475 return strdup(buffer
);
1478 } else if (strstr(line
, "descriptions ")) {
1479 if ((!wordlen
|| !strncmp(word
, "general", wordlen
)) && (++which
> state
))
1480 return strdup("general");
1481 if ((!wordlen
|| !strncmp(word
, "ports", wordlen
)) && (++which
> state
))
1482 return strdup("ports");
1489 static struct ast_cli_entry chan_misdn_clis
[] = {
1490 { {"misdn","send","calldeflect", NULL
}, misdn_send_cd
, "Sends CallDeflection to mISDN Channel",
1491 "Usage: misdn send calldeflect <channel> \"<nr>\" \n", complete_ch
},
1492 { {"misdn","send","digit", NULL
}, misdn_send_digit
, "Sends DTMF Digit to mISDN Channel",
1493 "Usage: misdn send digit <channel> \"<msg>\" \n"
1494 " Send <digit> to <channel> as DTMF Tone\n"
1495 " when channel is a mISDN channel\n", complete_ch
},
1496 { {"misdn","toggle","echocancel", NULL
}, misdn_toggle_echocancel
, "Toggles EchoCancel on mISDN Channel",
1497 "Usage: misdn toggle echocancel <channel>\n", complete_ch
},
1498 { {"misdn","send","display", NULL
}, misdn_send_display
, "Sends Text to mISDN Channel",
1499 "Usage: misdn send display <channel> \"<msg>\" \n"
1500 " Send <msg> to <channel> as Display Message\n"
1501 " when channel is a mISDN channel\n", complete_ch
},
1502 { {"misdn","show","config", NULL
}, misdn_show_config
, "Shows internal mISDN config, read from cfg-file",
1503 "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
1504 " Use 0 for <port> to only print the general config.\n", complete_show_config
},
1505 { {"misdn","reload", NULL
}, misdn_reload
, "Reloads internal mISDN config, read from cfg-file",
1506 "Usage: misdn reload\n" },
1507 { {"misdn","set","tics", NULL
}, misdn_set_tics
, "",
1509 { {"misdn","show","channels", NULL
}, misdn_show_cls
, "Shows internal mISDN chan_list",
1510 "Usage: misdn show channels\n" },
1511 { {"misdn","show","channel", NULL
}, misdn_show_cl
, "Shows internal mISDN chan_list",
1512 "Usage: misdn show channels\n", complete_ch
},
1513 { {"misdn","port","block", NULL
}, misdn_port_block
, "Blocks the given port",
1514 "Usage: misdn port block\n" },
1515 { {"misdn","port","unblock", NULL
}, misdn_port_unblock
, "Unblocks the given port",
1516 "Usage: misdn port unblock\n" },
1517 { {"misdn","restart","port", NULL
}, misdn_restart_port
, "Restarts the given port",
1518 "Usage: misdn restart port\n" },
1519 { {"misdn","restart","pid", NULL
}, misdn_restart_pid
, "Restarts the given pid",
1520 "Usage: misdn restart pid\n" },
1521 { {"misdn","send","restart", NULL
}, misdn_send_restart
,
1522 "Sends a restart for every bchannel on the given port",
1523 "Usage: misdn send restart <port>\n"},
1524 { {"misdn","port","up", NULL
}, misdn_port_up
, "Tries to establish L1 on the given port",
1525 "Usage: misdn port up <port>\n" },
1526 { {"misdn","port","down", NULL
}, misdn_port_down
, "Tries to deactivate the L1 on the given port",
1527 "Usage: misdn port down <port>\n" },
1528 { {"misdn","show","stacks", NULL
}, misdn_show_stacks
, "Shows internal mISDN stack_list",
1529 "Usage: misdn show stacks\n" },
1530 { {"misdn","show","ports","stats", NULL
}, misdn_show_ports_stats
, "Shows chan_misdns call statistics per port",
1531 "Usage: misdn show port stats\n" },
1532 { {"misdn","show","port", NULL
}, misdn_show_port
, "Shows detailed information for given port",
1533 "Usage: misdn show port <port>\n" },
1534 { {"misdn","set","debug", NULL
}, misdn_set_debug
, "Sets Debuglevel of chan_misdn",
1535 "Usage: misdn set debug <level> [only] | [port <port> [only]]\n", complete_debug_port
},
1536 { {"misdn","set","crypt","debug", NULL
}, misdn_set_crypt_debug
, "Sets CryptDebuglevel of chan_misdn, at the moment, level={1,2}",
1537 "Usage: misdn set crypt debug <level>\n" }
1540 static int update_config(struct chan_list
*ch
, int orig
)
1542 struct ast_channel
*ast
;
1543 struct misdn_bchannel
*bc
;
1548 ast_log(LOG_WARNING
, "Cannot configure without chanlist\n");
1554 if (! ast
|| ! bc
) {
1555 ast_log(LOG_WARNING
, "Cannot configure without ast || bc\n");
1561 chan_misdn_log(7, port
, "update_config: Getting Config\n");
1563 misdn_cfg_get(port
, MISDN_CFG_HDLC
, &hdlc
, sizeof(int));
1566 switch (bc
->capability
) {
1567 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED
:
1568 case INFO_CAPABILITY_DIGITAL_RESTRICTED
:
1569 chan_misdn_log(1, bc
->port
, " --> CONF HDLC\n");
1576 misdn_cfg_get(port
, MISDN_CFG_PRES
, &pres
, sizeof(pres
));
1577 misdn_cfg_get(port
, MISDN_CFG_SCREEN
, &screen
, sizeof(screen
));
1578 chan_misdn_log(2, port
, " --> pres: %d screen: %d\n", pres
, screen
);
1580 if (pres
< 0 || screen
< 0) {
1581 chan_misdn_log(2, port
, " --> pres: %x\n", ast
->cid
.cid_pres
);
1583 switch (ast
->cid
.cid_pres
& 0x60) {
1584 case AST_PRES_RESTRICTED
:
1586 chan_misdn_log(2, port
, " --> PRES: Restricted (1)\n");
1588 case AST_PRES_UNAVAILABLE
:
1590 chan_misdn_log(2, port
, " --> PRES: Unavailable (2)\n");
1594 chan_misdn_log(2, port
, " --> PRES: Allowed (0)\n");
1598 switch (ast
->cid
.cid_pres
& 0x3) {
1600 case AST_PRES_USER_NUMBER_UNSCREENED
:
1602 chan_misdn_log(2, port
, " --> SCREEN: Unscreened (0)\n");
1604 case AST_PRES_USER_NUMBER_PASSED_SCREEN
:
1606 chan_misdn_log(2, port
, " --> SCREEN: Passed Screen (1)\n");
1608 case AST_PRES_USER_NUMBER_FAILED_SCREEN
:
1610 chan_misdn_log(2, port
, " --> SCREEN: Failed Screen (2)\n");
1612 case AST_PRES_NETWORK_NUMBER
:
1614 chan_misdn_log(2, port
, " --> SCREEN: Network Nr. (3)\n");
1618 bc
->screen
= screen
;
1626 static void config_jitterbuffer(struct chan_list
*ch
)
1628 struct misdn_bchannel
*bc
= ch
->bc
;
1629 int len
= ch
->jb_len
, threshold
= ch
->jb_upper_threshold
;
1631 chan_misdn_log(5, bc
->port
, "config_jb: Called\n");
1634 chan_misdn_log(1, bc
->port
, "config_jb: Deactivating Jitterbuffer\n");
1637 if (len
<= 100 || len
> 8000) {
1638 chan_misdn_log(0, bc
->port
, "config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
1642 if ( threshold
> len
) {
1643 chan_misdn_log(0, bc
->port
, "config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
1647 cb_log(0, bc
->port
, "config_jb: We've got a Jitterbuffer Already on this port.\n");
1648 misdn_jb_destroy(ch
->jb
);
1652 ch
->jb
=misdn_jb_init(len
, threshold
);
1660 void debug_numplan(int port
, int numplan
, char *type
)
1663 case NUMPLAN_INTERNATIONAL
:
1664 chan_misdn_log(2, port
, " --> %s: International\n", type
);
1666 case NUMPLAN_NATIONAL
:
1667 chan_misdn_log(2, port
, " --> %s: National\n", type
);
1669 case NUMPLAN_SUBSCRIBER
:
1670 chan_misdn_log(2, port
, " --> %s: Subscriber\n", type
);
1672 case NUMPLAN_UNKNOWN
:
1673 chan_misdn_log(2, port
, " --> %s: Unknown\n", type
);
1675 /* Maybe we should cut off the prefix if present ? */
1677 chan_misdn_log(0, port
, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
1684 static int update_pipeline_config(struct misdn_bchannel
*bc
)
1688 misdn_cfg_get(bc
->port
, MISDN_CFG_PIPELINE
, bc
->pipeline
, sizeof(bc
->pipeline
));
1693 misdn_cfg_get(bc
->port
, MISDN_CFG_ECHOCANCEL
, &ec
, sizeof(int));
1695 ast_copy_string(bc
->pipeline
, "mg2ec", sizeof(bc
->pipeline
));
1697 snprintf(bc
->pipeline
, sizeof(bc
->pipeline
), "mg2ec(deftaps=%d)", ec
);
1702 static int update_ec_config(struct misdn_bchannel
*bc
)
1705 int port
= bc
->port
;
1707 misdn_cfg_get(port
, MISDN_CFG_ECHOCANCEL
, &ec
, sizeof(int));
1711 } else if (ec
> 1) {
1713 bc
->ec_deftaps
= ec
;
1721 static int read_config(struct chan_list
*ch
, int orig
)
1723 struct ast_channel
*ast
;
1724 struct misdn_bchannel
*bc
;
1727 char lang
[BUFFERSIZE
+ 1];
1728 char localmusicclass
[BUFFERSIZE
+ 1];
1729 char faxdetect
[BUFFERSIZE
+ 1];
1736 ast_log(LOG_WARNING
, "Cannot configure without chanlist\n");
1742 if (! ast
|| ! bc
) {
1743 ast_log(LOG_WARNING
, "Cannot configure without ast || bc\n");
1748 chan_misdn_log(1, port
, "read_config: Getting Config\n");
1750 misdn_cfg_get(port
, MISDN_CFG_LANGUAGE
, lang
, BUFFERSIZE
);
1751 ast_string_field_set(ast
, language
, lang
);
1753 misdn_cfg_get(port
, MISDN_CFG_MUSICCLASS
, localmusicclass
, BUFFERSIZE
);
1754 ast_string_field_set(ast
, musicclass
, localmusicclass
);
1756 misdn_cfg_get(port
, MISDN_CFG_TXGAIN
, &bc
->txgain
, sizeof(int));
1757 misdn_cfg_get(port
, MISDN_CFG_RXGAIN
, &bc
->rxgain
, sizeof(int));
1759 misdn_cfg_get(port
, MISDN_CFG_INCOMING_EARLY_AUDIO
, &ch
->incoming_early_audio
, sizeof(int));
1761 misdn_cfg_get(port
, MISDN_CFG_SENDDTMF
, &bc
->send_dtmf
, sizeof(int));
1763 misdn_cfg_get(port
, MISDN_CFG_ASTDTMF
, &ch
->ast_dsp
, sizeof(int));
1766 ch
->ignore_dtmf
= 1;
1769 misdn_cfg_get(port
, MISDN_CFG_NEED_MORE_INFOS
, &bc
->need_more_infos
, sizeof(int));
1770 misdn_cfg_get(port
, MISDN_CFG_NTTIMEOUT
, &ch
->nttimeout
, sizeof(int));
1772 misdn_cfg_get(port
, MISDN_CFG_NOAUTORESPOND_ON_SETUP
, &ch
->noautorespond_on_setup
, sizeof(int));
1774 misdn_cfg_get(port
, MISDN_CFG_FAR_ALERTING
, &ch
->far_alerting
, sizeof(int));
1776 misdn_cfg_get(port
, MISDN_CFG_ALLOWED_BEARERS
, &ch
->allowed_bearers
, BUFFERSIZE
);
1778 misdn_cfg_get(port
, MISDN_CFG_FAXDETECT
, faxdetect
, BUFFERSIZE
);
1780 misdn_cfg_get(port
, MISDN_CFG_HDLC
, &hdlc
, sizeof(int));
1783 switch (bc
->capability
) {
1784 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED
:
1785 case INFO_CAPABILITY_DIGITAL_RESTRICTED
:
1786 chan_misdn_log(1, bc
->port
, " --> CONF HDLC\n");
1792 /*Initialize new Jitterbuffer*/
1793 misdn_cfg_get(port
, MISDN_CFG_JITTERBUFFER
, &ch
->jb_len
, sizeof(int));
1794 misdn_cfg_get(port
, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD
, &ch
->jb_upper_threshold
, sizeof(int));
1796 config_jitterbuffer(ch
);
1798 misdn_cfg_get(bc
->port
, MISDN_CFG_CONTEXT
, ch
->context
, sizeof(ch
->context
));
1800 ast_copy_string(ast
->context
, ch
->context
, sizeof(ast
->context
));
1803 update_pipeline_config(bc
);
1805 update_ec_config(bc
);
1811 misdn_cfg_get( bc
->port
, MISDN_CFG_EARLY_BCONNECT
, &eb3
, sizeof(int));
1812 bc
->early_bconnect
=eb3
;
1815 misdn_cfg_get(port
, MISDN_CFG_PICKUPGROUP
, &pg
, sizeof(pg
));
1816 misdn_cfg_get(port
, MISDN_CFG_CALLGROUP
, &cg
, sizeof(cg
));
1818 chan_misdn_log(5, port
, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf
, sizeof(buf
), cg
), ast_print_group(buf2
, sizeof(buf2
), pg
));
1819 ast
->pickupgroup
= pg
;
1820 ast
->callgroup
= cg
;
1822 if (orig
== ORG_AST
) {
1823 char callerid
[BUFFERSIZE
+ 1];
1825 misdn_cfg_get(port
, MISDN_CFG_TE_CHOOSE_CHANNEL
, &(bc
->te_choose_channel
), sizeof(int));
1827 if (strstr(faxdetect
, "outgoing") || strstr(faxdetect
, "both")) {
1828 if (strstr(faxdetect
, "nojump"))
1834 misdn_cfg_get(port
, MISDN_CFG_CALLERID
, callerid
, BUFFERSIZE
);
1835 if ( ! ast_strlen_zero(callerid
) ) {
1836 chan_misdn_log(1, port
, " --> * Setting Cid to %s\n", callerid
);
1837 ast_copy_string(bc
->oad
, callerid
, sizeof(bc
->oad
));
1840 misdn_cfg_get(port
, MISDN_CFG_DIALPLAN
, &bc
->dnumplan
, sizeof(int));
1841 misdn_cfg_get(port
, MISDN_CFG_LOCALDIALPLAN
, &bc
->onumplan
, sizeof(int));
1842 misdn_cfg_get(port
, MISDN_CFG_CPNDIALPLAN
, &bc
->cpnnumplan
, sizeof(int));
1843 debug_numplan(port
, bc
->dnumplan
, "TON");
1844 debug_numplan(port
, bc
->onumplan
, "LTON");
1845 debug_numplan(port
, bc
->cpnnumplan
, "CTON");
1847 ch
->overlap_dial
= 0;
1848 } else { /** ORIGINATOR MISDN **/
1849 char prefix
[BUFFERSIZE
+ 1] = "";
1851 if (strstr(faxdetect
, "incoming") || strstr(faxdetect
, "both")) {
1852 if (strstr(faxdetect
, "nojump"))
1858 misdn_cfg_get(port
, MISDN_CFG_CPNDIALPLAN
, &bc
->cpnnumplan
, sizeof(int));
1859 debug_numplan(port
, bc
->cpnnumplan
, "CTON");
1861 switch (bc
->onumplan
) {
1862 case NUMPLAN_INTERNATIONAL
:
1863 misdn_cfg_get(bc
->port
, MISDN_CFG_INTERNATPREFIX
, prefix
, BUFFERSIZE
);
1866 case NUMPLAN_NATIONAL
:
1867 misdn_cfg_get(bc
->port
, MISDN_CFG_NATPREFIX
, prefix
, BUFFERSIZE
);
1873 ast_copy_string(buf
, bc
->oad
, sizeof(buf
));
1874 snprintf(bc
->oad
, sizeof(bc
->oad
), "%s%s", prefix
, buf
);
1876 if (!ast_strlen_zero(bc
->dad
)) {
1877 ast_copy_string(bc
->orig_dad
, bc
->dad
, sizeof(bc
->orig_dad
));
1880 if ( ast_strlen_zero(bc
->dad
) && !ast_strlen_zero(bc
->keypad
)) {
1881 ast_copy_string(bc
->dad
, bc
->keypad
, sizeof(bc
->dad
));
1886 switch (bc
->dnumplan
) {
1887 case NUMPLAN_INTERNATIONAL
:
1888 misdn_cfg_get(bc
->port
, MISDN_CFG_INTERNATPREFIX
, prefix
, BUFFERSIZE
);
1890 case NUMPLAN_NATIONAL
:
1891 misdn_cfg_get(bc
->port
, MISDN_CFG_NATPREFIX
, prefix
, BUFFERSIZE
);
1897 ast_copy_string(buf
, bc
->dad
, sizeof(buf
));
1898 snprintf(bc
->dad
, sizeof(bc
->dad
), "%s%s", prefix
, buf
);
1900 if (strcmp(bc
->dad
, ast
->exten
)) {
1901 ast_copy_string(ast
->exten
, bc
->dad
, sizeof(ast
->exten
));
1904 ast_set_callerid(ast
, bc
->oad
, NULL
, bc
->oad
);
1906 if ( !ast_strlen_zero(bc
->rad
) ) {
1907 if (ast
->cid
.cid_rdnis
)
1908 free(ast
->cid
.cid_rdnis
);
1909 ast
->cid
.cid_rdnis
= strdup(bc
->rad
);
1912 misdn_cfg_get(bc
->port
, MISDN_CFG_OVERLAP_DIAL
, &ch
->overlap_dial
, sizeof(ch
->overlap_dial
));
1913 ast_mutex_init(&ch
->overlap_tv_lock
);
1914 } /* ORIG MISDN END */
1916 ch
->overlap_dial_task
= -1;
1918 if (ch
->faxdetect
|| ch
->ast_dsp
) {
1919 misdn_cfg_get(port
, MISDN_CFG_FAXDETECT_TIMEOUT
, &ch
->faxdetect_timeout
, sizeof(ch
->faxdetect_timeout
));
1921 ch
->dsp
= ast_dsp_new();
1924 ast_dsp_set_features(ch
->dsp
, DSP_FEATURE_DTMF_DETECT
| DSP_FEATURE_FAX_DETECT
);
1926 ast_dsp_set_features(ch
->dsp
, DSP_FEATURE_DTMF_DETECT
);
1929 ch
->trans
= ast_translator_build_path(AST_FORMAT_SLINEAR
, AST_FORMAT_ALAW
);
1932 /* AOCD initialization */
1933 bc
->AOCDtype
= Fac_None
;
1939 /*****************************/
1940 /*** AST Indications Start ***/
1941 /*****************************/
1943 static int misdn_call(struct ast_channel
*ast
, char *dest
, int timeout
)
1949 struct chan_list
*ch
= MISDN_ASTERISK_TECH_PVT(ast
);
1950 struct misdn_bchannel
*newbc
;
1951 char *opts
= NULL
, *ext
, *tokb
;
1952 char *dest_cp
= ast_strdupa(dest
);
1954 ext
= strtok_r(dest_cp
, "/", &tokb
);
1957 ext
= strtok_r(NULL
, "/", &tokb
);
1959 opts
= strtok_r(NULL
, "/", &tokb
);
1961 chan_misdn_log(0, 0, "misdn_call: No Extension given!\n");
1967 ast_log(LOG_WARNING
, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
1971 if (((ast
->_state
!= AST_STATE_DOWN
) && (ast
->_state
!= AST_STATE_RESERVED
)) || !dest
) {
1972 ast_log(LOG_WARNING
, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast
->name
);
1973 ast
->hangupcause
= AST_CAUSE_NORMAL_TEMPORARY_FAILURE
;
1974 ast_setstate(ast
, AST_STATE_DOWN
);
1979 ast_log(LOG_WARNING
, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast
->name
);
1980 ast
->hangupcause
= AST_CAUSE_NORMAL_TEMPORARY_FAILURE
;
1981 ast_setstate(ast
, AST_STATE_DOWN
);
1988 ast_log(LOG_WARNING
, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast
->name
);
1989 ast
->hangupcause
= AST_CAUSE_NORMAL_TEMPORARY_FAILURE
;
1990 ast_setstate(ast
, AST_STATE_DOWN
);
1996 if ((exceed
= add_out_calls(port
))) {
1998 snprintf(tmp
, sizeof(tmp
), "%d", exceed
);
1999 pbx_builtin_setvar_helper(ast
, "MAX_OVERFLOW", tmp
);
2003 chan_misdn_log(1, port
, "* CALL: %s\n", dest
);
2005 chan_misdn_log(2, port
, " --> * dad:%s tech:%s ctx:%s\n", ast
->exten
, ast
->name
, ast
->context
);
2007 chan_misdn_log(3, port
, " --> * adding2newbc ext %s\n", ast
->exten
);
2009 ast_copy_string(ast
->exten
, ext
, sizeof(ast
->exten
));
2010 ast_copy_string(newbc
->dad
, ext
, sizeof(newbc
->dad
));
2013 ast_copy_string(newbc
->rad
, S_OR(ast
->cid
.cid_rdnis
, ""), sizeof(newbc
->rad
));
2015 chan_misdn_log(3, port
, " --> * adding2newbc callerid %s\n", ast
->cid
.cid_num
);
2016 if (ast_strlen_zero(newbc
->oad
) && !ast_strlen_zero(ast
->cid
.cid_num
)) {
2017 ast_copy_string(newbc
->oad
, ast
->cid
.cid_num
, sizeof(newbc
->oad
));
2020 newbc
->capability
= ast
->transfercapability
;
2021 pbx_builtin_setvar_helper(ast
, "TRANSFERCAPABILITY", ast_transfercapability2str(newbc
->capability
));
2022 if ( ast
->transfercapability
== INFO_CAPABILITY_DIGITAL_UNRESTRICTED
) {
2023 chan_misdn_log(2, port
, " --> * Call with flag Digital\n");
2026 /* update screening and presentation */
2027 update_config(ch
, ORG_AST
);
2029 /* fill in some ies from channel vary*/
2030 import_ch(ast
, newbc
, ch
);
2032 /* Finally The Options Override Everything */
2034 misdn_set_opt_exec(ast
, opts
);
2036 chan_misdn_log(2, port
, "NO OPTS GIVEN\n");
2038 /*check for bridging*/
2039 misdn_cfg_get(0, MISDN_GEN_BRIDGING
, &bridging
, sizeof(bridging
));
2040 if (bridging
&& ch
->other_ch
) {
2042 chan_misdn_log(1, port
, "Disabling EC (aka Pipeline) on both Sides\n");
2043 *ch
->bc
->pipeline
= 0;
2044 *ch
->other_ch
->bc
->pipeline
= 0;
2046 chan_misdn_log(1, port
, "Disabling EC on both Sides\n");
2047 ch
->bc
->ec_enable
= 0;
2048 ch
->other_ch
->bc
->ec_enable
= 0;
2052 r
= misdn_lib_send_event( newbc
, EVENT_SETUP
);
2054 /** we should have l3id after sending setup **/
2055 ch
->l3id
= newbc
->l3_id
;
2057 if ( r
== -ENOCHAN
) {
2058 chan_misdn_log(0, port
, " --> * Theres no Channel at the moment .. !\n");
2059 chan_misdn_log(1, port
, " --> * SEND: State Down pid:%d\n", newbc
? newbc
->pid
: -1);
2060 ast
->hangupcause
= AST_CAUSE_NORMAL_CIRCUIT_CONGESTION
;
2061 ast_setstate(ast
, AST_STATE_DOWN
);
2065 chan_misdn_log(2, port
, " --> * SEND: State Dialing pid:%d\n", newbc
? newbc
->pid
: 1);
2067 ast_setstate(ast
, AST_STATE_DIALING
);
2068 ast
->hangupcause
= AST_CAUSE_NORMAL_CLEARING
;
2073 ch
->state
= MISDN_CALLING
;
2079 static int misdn_answer(struct ast_channel
*ast
)
2081 struct chan_list
*p
;
2084 if (!ast
|| !(p
= MISDN_ASTERISK_TECH_PVT(ast
))) return -1;
2086 chan_misdn_log(1, p
? (p
->bc
? p
->bc
->port
: 0) : 0, "* ANSWER:\n");
2089 ast_log(LOG_WARNING
, " --> Channel not connected ??\n");
2090 ast_queue_hangup(ast
);
2094 chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n");
2096 ast_queue_hangup(ast
);
2099 tmp
= pbx_builtin_getvar_helper(p
->ast
, "CRYPT_KEY");
2100 if (!ast_strlen_zero(tmp
)) {
2101 chan_misdn_log(1, p
->bc
->port
, " --> Connection will be BF crypted\n");
2102 ast_copy_string(p
->bc
->crypt_key
, tmp
, sizeof(p
->bc
->crypt_key
));
2104 chan_misdn_log(3, p
->bc
->port
, " --> Connection is without BF encryption\n");
2107 tmp
= pbx_builtin_getvar_helper(ast
, "MISDN_DIGITAL_TRANS");
2108 if (!ast_strlen_zero(tmp
) && ast_true(tmp
)) {
2109 chan_misdn_log(1, p
->bc
->port
, " --> Connection is transparent digital\n");
2112 p
->bc
->nojitter
= 1;
2115 p
->state
= MISDN_CONNECTED
;
2118 if ( ast_strlen_zero(p
->bc
->cad
) ) {
2119 chan_misdn_log(2,p
->bc
->port
," --> empty cad using dad\n");
2120 ast_copy_string(p
->bc
->cad
, p
->bc
->dad
, sizeof(p
->bc
->cad
));
2123 misdn_lib_send_event( p
->bc
, EVENT_CONNECT
);
2129 static int misdn_digit_begin(struct ast_channel
*chan
, char digit
)
2131 /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
2135 static int misdn_digit_end(struct ast_channel
*ast
, char digit
, unsigned int duration
)
2137 struct chan_list
*p
;
2138 struct misdn_bchannel
*bc
;
2140 if (!ast
|| !(p
= MISDN_ASTERISK_TECH_PVT(ast
))) return -1;
2143 chan_misdn_log(1, bc
? bc
->port
: 0, "* IND : Digit %c\n", digit
);
2146 ast_log(LOG_WARNING
, " --> !! Got Digit Event without having bchannel Object\n");
2150 switch (p
->state
) {
2158 l
= sizeof(bc
->infos_pending
);
2159 strncat(bc
->infos_pending
, buf
, l
- strlen(bc
->infos_pending
) - 1);
2162 case MISDN_CALLING_ACKNOWLEDGE
:
2164 bc
->info_dad
[0]=digit
;
2168 int l
= sizeof(bc
->dad
);
2169 strncat(bc
->dad
, bc
->info_dad
, l
- strlen(bc
->dad
) - 1);
2172 int l
= sizeof(p
->ast
->exten
);
2173 strncpy(p
->ast
->exten
, bc
->dad
, l
);
2174 p
->ast
->exten
[l
-1] = 0;
2177 misdn_lib_send_event( bc
, EVENT_INFORMATION
);
2181 /* Do not send Digits in CONNECTED State, when
2182 * the other side is too mISDN. */
2186 if ( bc
->send_dtmf
)
2187 send_digit_to_chan(p
,digit
);
2195 static int misdn_fixup(struct ast_channel
*oldast
, struct ast_channel
*ast
)
2197 struct chan_list
*p
;
2199 if (!ast
|| ! (p
=MISDN_ASTERISK_TECH_PVT(ast
) )) return -1;
2201 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
);
2210 static int misdn_indication(struct ast_channel
*ast
, int cond
, const void *data
, size_t datalen
)
2212 struct chan_list
*p
;
2214 if (!ast
|| ! (p
=MISDN_ASTERISK_TECH_PVT(ast
))) {
2215 ast_log(LOG_WARNING
, "Returned -1 in misdn_indication\n");
2220 chan_misdn_log(1, 0, "* IND : Indication from %s\n", ast
->exten
);
2221 ast_log(LOG_WARNING
, "Private Pointer but no bc ?\n");
2225 chan_misdn_log(5, p
->bc
->port
, "* IND : Indication [%d] from %s\n", cond
, ast
->exten
);
2228 case AST_CONTROL_BUSY
:
2229 chan_misdn_log(1, p
->bc
->port
, "* IND :\tbusy pid:%d\n", p
->bc
? p
->bc
->pid
: -1);
2230 ast_setstate(ast
, AST_STATE_BUSY
);
2232 p
->bc
->out_cause
= AST_CAUSE_USER_BUSY
;
2233 if (p
->state
!= MISDN_CONNECTED
) {
2235 misdn_lib_send_event( p
->bc
, EVENT_DISCONNECT
);
2237 chan_misdn_log(-1, p
->bc
->port
, " --> !! Got Busy in Connected State !?! ast:%s\n", ast
->name
);
2240 case AST_CONTROL_RING
:
2241 chan_misdn_log(1, p
->bc
->port
, "* IND :\tring pid:%d\n", p
->bc
? p
->bc
->pid
: -1);
2243 case AST_CONTROL_RINGING
:
2244 chan_misdn_log(1, p
->bc
->port
, "* IND :\tringing pid:%d\n", p
->bc
? p
->bc
->pid
: -1);
2246 case MISDN_ALERTING
:
2247 chan_misdn_log(2, p
->bc
->port
, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoring it\n", p
->bc
? p
->bc
->pid
: -1);
2249 case MISDN_CONNECTED
:
2250 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);
2253 p
->state
= MISDN_ALERTING
;
2254 chan_misdn_log(2, p
->bc
->port
, " --> * IND :\tringing pid:%d\n", p
->bc
? p
->bc
->pid
: -1);
2255 misdn_lib_send_event( p
->bc
, EVENT_ALERTING
);
2257 if (p
->other_ch
&& p
->other_ch
->bc
) {
2258 if (misdn_inband_avail(p
->other_ch
->bc
)) {
2259 chan_misdn_log(2, p
->bc
->port
, " --> other End is mISDN and has inband info available\n");
2263 if (!p
->other_ch
->bc
->nt
) {
2264 chan_misdn_log(2, p
->bc
->port
, " --> other End is mISDN TE so it has inband info for sure (?)\n");
2269 chan_misdn_log(3, p
->bc
->port
, " --> * SEND: State Ring pid:%d\n", p
->bc
? p
->bc
->pid
: -1);
2270 ast_setstate(ast
, AST_STATE_RINGING
);
2272 if (!p
->bc
->nt
&& (p
->originator
== ORG_MISDN
) && !p
->incoming_early_audio
)
2273 chan_misdn_log(2, p
->bc
->port
, " --> incoming_early_audio off\n");
2278 case AST_CONTROL_ANSWER
:
2279 chan_misdn_log(1, p
->bc
->port
, " --> * IND :\tanswer pid:%d\n", p
->bc
? p
->bc
->pid
: -1);
2282 case AST_CONTROL_TAKEOFFHOOK
:
2283 chan_misdn_log(1, p
->bc
->port
, " --> *\ttakeoffhook pid:%d\n", p
->bc
? p
->bc
->pid
: -1);
2285 case AST_CONTROL_OFFHOOK
:
2286 chan_misdn_log(1, p
->bc
->port
, " --> *\toffhook pid:%d\n", p
->bc
? p
->bc
->pid
: -1);
2288 case AST_CONTROL_FLASH
:
2289 chan_misdn_log(1, p
->bc
->port
, " --> *\tflash pid:%d\n", p
->bc
? p
->bc
->pid
: -1);
2291 case AST_CONTROL_PROGRESS
:
2292 chan_misdn_log(1, p
->bc
->port
, " --> * IND :\tprogress pid:%d\n", p
->bc
? p
->bc
->pid
: -1);
2293 misdn_lib_send_event( p
->bc
, EVENT_PROGRESS
);
2295 case AST_CONTROL_PROCEEDING
:
2296 chan_misdn_log(1, p
->bc
->port
, " --> * IND :\tproceeding pid:%d\n", p
->bc
? p
->bc
->pid
: -1);
2297 misdn_lib_send_event( p
->bc
, EVENT_PROCEEDING
);
2299 case AST_CONTROL_CONGESTION
:
2300 chan_misdn_log(1, p
->bc
->port
, " --> * IND :\tcongestion pid:%d\n", p
->bc
? p
->bc
->pid
: -1);
2302 p
->bc
->out_cause
= AST_CAUSE_SWITCH_CONGESTION
;
2304 misdn_lib_send_event( p
->bc
, EVENT_DISCONNECT
);
2307 hanguptone_indicate(p
);
2311 chan_misdn_log(1, p
->bc
->port
, " --> * IND :\t-1! (stop indication) pid:%d\n", p
->bc
? p
->bc
->pid
: -1);
2315 if (p
->state
== MISDN_CONNECTED
)
2318 case AST_CONTROL_HOLD
:
2319 ast_moh_start(ast
,data
,ast
->musicclass
);
2320 chan_misdn_log(1, p
->bc
->port
, " --> *\tHOLD pid:%d\n", p
->bc
? p
->bc
->pid
: -1);
2322 case AST_CONTROL_UNHOLD
:
2324 chan_misdn_log(1, p
->bc
->port
, " --> *\tUNHOLD pid:%d\n", p
->bc
? p
->bc
->pid
: -1);
2327 chan_misdn_log(1, p
->bc
->port
, " --> * Unknown Indication:%d pid:%d\n", cond
, p
->bc
? p
->bc
->pid
: -1);
2333 static int misdn_hangup(struct ast_channel
*ast
)
2335 struct chan_list
*p
;
2336 struct misdn_bchannel
*bc
= NULL
;
2337 const char *varcause
= NULL
;
2339 ast_log(LOG_DEBUG
, "misdn_hangup(%s)\n", ast
->name
);
2341 if (!ast
|| ! (p
=MISDN_ASTERISK_TECH_PVT(ast
) ) ) return -1;
2344 chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
2351 const char *tmp
=pbx_builtin_getvar_helper(ast
,"MISDN_USERUSER");
2353 ast_log(LOG_NOTICE
, "MISDN_USERUSER: %s\n", tmp
);
2354 strcpy(bc
->uu
, tmp
);
2355 bc
->uulen
=strlen(bc
->uu
);
2359 MISDN_ASTERISK_TECH_PVT(ast
) = NULL
;
2362 if (ast
->_state
== AST_STATE_RESERVED
||
2363 p
->state
== MISDN_NOTHING
||
2364 p
->state
== MISDN_HOLDED
||
2365 p
->state
== MISDN_HOLD_DISCONNECT
) {
2368 /* between request and call */
2369 ast_log(LOG_DEBUG
, "State Reserved (or nothing) => chanIsAvail\n");
2370 MISDN_ASTERISK_TECH_PVT(ast
) = NULL
;
2372 ast_mutex_lock(&release_lock
);
2373 cl_dequeue_chan(&cl_te
, p
);
2377 ast_mutex_unlock(&release_lock
);
2380 misdn_lib_release(bc
);
2386 ast_log(LOG_WARNING
, "Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p
), p
->l3id
);
2392 p
->need_queue_hangup
= 0;
2399 bc
->out_cause
= ast
->hangupcause
? ast
->hangupcause
: AST_CAUSE_NORMAL_CLEARING
;
2401 if ((varcause
= pbx_builtin_getvar_helper(ast
, "HANGUPCAUSE")) ||
2402 (varcause
= pbx_builtin_getvar_helper(ast
, "PRI_CAUSE"))) {
2403 int tmpcause
= atoi(varcause
);
2404 bc
->out_cause
= tmpcause
? tmpcause
: AST_CAUSE_NORMAL_CLEARING
;
2407 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
));
2408 chan_misdn_log(3, bc
->port
, " --> l3id:%x\n", p
->l3id
);
2409 chan_misdn_log(3, bc
->port
, " --> cause:%d\n", bc
->cause
);
2410 chan_misdn_log(2, bc
->port
, " --> out_cause:%d\n", bc
->out_cause
);
2411 chan_misdn_log(2, bc
->port
, " --> state:%s\n", misdn_get_ch_state(p
));
2414 case MISDN_INCOMING_SETUP
:
2416 /* This is the only place in misdn_hangup, where we
2417 * can call release_chan, else it might create lot's of trouble
2419 ast_log(LOG_NOTICE
, "release channel, in CALLING/INCOMING_SETUP state.. no other events happened\n");
2422 p
->state
= MISDN_CLEANING
;
2423 if (bc
->need_release_complete
)
2424 misdn_lib_send_event( bc
, EVENT_RELEASE_COMPLETE
);
2429 hanguptone_indicate(p
);
2431 if (bc
->need_disconnect
)
2432 misdn_lib_send_event( bc
, EVENT_DISCONNECT
);
2434 case MISDN_CALLING_ACKNOWLEDGE
:
2436 hanguptone_indicate(p
);
2438 if (bc
->need_disconnect
)
2439 misdn_lib_send_event( bc
, EVENT_DISCONNECT
);
2442 case MISDN_ALERTING
:
2443 case MISDN_PROGRESS
:
2444 case MISDN_PROCEEDING
:
2445 if (p
->originator
!= ORG_AST
)
2446 hanguptone_indicate(p
);
2448 /*p->state=MISDN_CLEANING;*/
2449 if (bc
->need_disconnect
)
2450 misdn_lib_send_event( bc
, EVENT_DISCONNECT
);
2452 case MISDN_CONNECTED
:
2453 case MISDN_PRECONNECTED
:
2454 /* Alerting or Disconnect */
2457 hanguptone_indicate(p
);
2458 p
->bc
->progress_indicator
= INFO_PI_INBAND_AVAILABLE
;
2460 if (bc
->need_disconnect
)
2461 misdn_lib_send_event( bc
, EVENT_DISCONNECT
);
2463 /*p->state=MISDN_CLEANING;*/
2465 case MISDN_DISCONNECTED
:
2466 if (bc
->need_release
)
2467 misdn_lib_send_event( bc
, EVENT_RELEASE
);
2468 p
->state
= MISDN_CLEANING
; /* MISDN_HUNGUP_FROM_AST; */
2471 case MISDN_RELEASED
:
2472 case MISDN_CLEANING
:
2473 p
->state
= MISDN_CLEANING
;
2479 case MISDN_HOLD_DISCONNECT
:
2480 /* need to send release here */
2481 chan_misdn_log(1, bc
->port
, " --> cause %d\n", bc
->cause
);
2482 chan_misdn_log(1, bc
->port
, " --> out_cause %d\n", bc
->out_cause
);
2485 if (bc
->need_release
)
2486 misdn_lib_send_event(bc
, EVENT_RELEASE
);
2487 p
->state
= MISDN_CLEANING
;
2492 if (bc
->need_release
)
2493 misdn_lib_send_event(bc
, EVENT_RELEASE
);
2494 p
->state
= MISDN_CLEANING
;
2496 if (bc
->need_disconnect
)
2497 misdn_lib_send_event(bc
, EVENT_DISCONNECT
);
2501 p
->state
= MISDN_CLEANING
;
2503 chan_misdn_log(3, bc
->port
, " --> Channel: %s hanguped new state:%s\n", ast
->name
, misdn_get_ch_state(p
));
2509 static struct ast_frame
*process_ast_dsp(struct chan_list
*tmp
, struct ast_frame
*frame
)
2511 struct ast_frame
*f
,*f2
;
2514 f2
= ast_translate(tmp
->trans
, frame
, 0);
2515 f
= ast_dsp_process(tmp
->ast
, tmp
->dsp
, f2
);
2517 chan_misdn_log(0, tmp
->bc
->port
, "No T-Path found\n");
2521 if (!f
|| (f
->frametype
!= AST_FRAME_DTMF
))
2524 ast_log(LOG_DEBUG
, "Detected inband DTMF digit: %c\n", f
->subclass
);
2526 if (tmp
->faxdetect
&& (f
->subclass
== 'f')) {
2527 /* Fax tone -- Handle and return NULL */
2528 if (!tmp
->faxhandled
) {
2529 struct ast_channel
*ast
= tmp
->ast
;
2531 chan_misdn_log(0, tmp
->bc
->port
, "Fax detected, preparing %s for fax transfer.\n", ast
->name
);
2532 tmp
->bc
->rxgain
= 0;
2533 isdn_lib_update_rxgain(tmp
->bc
);
2534 tmp
->bc
->txgain
= 0;
2535 isdn_lib_update_txgain(tmp
->bc
);
2537 *tmp
->bc
->pipeline
= 0;
2539 tmp
->bc
->ec_enable
= 0;
2541 isdn_lib_update_ec(tmp
->bc
);
2542 isdn_lib_stop_dtmf(tmp
->bc
);
2543 switch (tmp
->faxdetect
) {
2545 if (strcmp(ast
->exten
, "fax")) {
2547 char context_tmp
[BUFFERSIZE
];
2548 misdn_cfg_get(tmp
->bc
->port
, MISDN_CFG_FAXDETECT_CONTEXT
, &context_tmp
, sizeof(context_tmp
));
2549 context
= ast_strlen_zero(context_tmp
) ? (ast_strlen_zero(ast
->macrocontext
) ? ast
->context
: ast
->macrocontext
) : context_tmp
;
2550 if (ast_exists_extension(ast
, context
, "fax", 1, ast
->cid
.cid_num
)) {
2551 if (option_verbose
> 2)
2552 ast_verbose(VERBOSE_PREFIX_3
"Redirecting %s to fax extension (context:%s)\n", ast
->name
, context
);
2553 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
2554 pbx_builtin_setvar_helper(ast
,"FAXEXTEN",ast
->exten
);
2555 if (ast_async_goto(ast
, context
, "fax", 1))
2556 ast_log(LOG_WARNING
, "Failed to async goto '%s' into fax of '%s'\n", ast
->name
, context
);
2558 ast_log(LOG_NOTICE
, "Fax detected, but no fax extension ctx:%s exten:%s\n", context
, ast
->exten
);
2560 ast_log(LOG_DEBUG
, "Already in a fax extension, not redirecting\n");
2564 ast_verbose(VERBOSE_PREFIX_3
"Not redirecting %s to fax extension, nojump is set.\n", ast
->name
);
2568 ast_log(LOG_DEBUG
, "Fax already handled\n");
2572 if (tmp
->ast_dsp
&& (f
->subclass
!= 'f')) {
2573 chan_misdn_log(2, tmp
->bc
->port
, " --> * SEND: DTMF (AST_DSP) :%c\n", f
->subclass
);
2580 static struct ast_frame
*misdn_read(struct ast_channel
*ast
)
2582 struct chan_list
*tmp
;
2588 chan_misdn_log(1, 0, "misdn_read called without ast\n");
2591 if (!(tmp
= MISDN_ASTERISK_TECH_PVT(ast
))) {
2592 chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n");
2596 if (!tmp
->bc
&& !(tmp
->state
== MISDN_HOLDED
)) {
2597 chan_misdn_log(1, 0, "misdn_read called without bc\n");
2605 FD_SET(tmp
->pipe
[0],&rrfs
);
2607 t
=select(FD_SETSIZE
,&rrfs
,NULL
, NULL
,&tv
);
2610 chan_misdn_log(3, tmp
->bc
->port
, "read Select Timed out\n");
2615 chan_misdn_log(-1, tmp
->bc
->port
, "Select Error (err=%s)\n",strerror(errno
));
2619 if (FD_ISSET(tmp
->pipe
[0],&rrfs
)) {
2620 len
=read(tmp
->pipe
[0],tmp
->ast_rd_buf
,sizeof(tmp
->ast_rd_buf
));
2623 /* we hangup here, since our pipe is closed */
2624 chan_misdn_log(2,tmp
->bc
->port
,"misdn_read: Pipe closed, hanging up\n");
2632 tmp
->frame
.frametype
= AST_FRAME_VOICE
;
2633 tmp
->frame
.subclass
= AST_FORMAT_ALAW
;
2634 tmp
->frame
.datalen
= len
;
2635 tmp
->frame
.samples
= len
;
2636 tmp
->frame
.mallocd
= 0;
2637 tmp
->frame
.offset
= 0;
2638 tmp
->frame
.delivery
= ast_tv(0,0);
2639 tmp
->frame
.src
= NULL
;
2640 tmp
->frame
.data
= tmp
->ast_rd_buf
;
2642 if (tmp
->faxdetect
&& !tmp
->faxhandled
) {
2643 if (tmp
->faxdetect_timeout
) {
2644 if (ast_tvzero(tmp
->faxdetect_tv
)) {
2645 tmp
->faxdetect_tv
= ast_tvnow();
2646 chan_misdn_log(2, tmp
->bc
->port
, "faxdetect: starting detection with timeout: %ds ...\n", tmp
->faxdetect_timeout
);
2647 return process_ast_dsp(tmp
, &tmp
->frame
);
2649 struct timeval tv_now
= ast_tvnow();
2650 int diff
= ast_tvdiff_ms(tv_now
, tmp
->faxdetect_tv
);
2651 if (diff
<= (tmp
->faxdetect_timeout
* 1000)) {
2652 chan_misdn_log(5, tmp
->bc
->port
, "faxdetect: detecting ...\n");
2653 return process_ast_dsp(tmp
, &tmp
->frame
);
2655 chan_misdn_log(2, tmp
->bc
->port
, "faxdetect: stopping detection (time ran out) ...\n");
2661 chan_misdn_log(5, tmp
->bc
->port
, "faxdetect: detecting ... (no timeout)\n");
2662 return process_ast_dsp(tmp
, &tmp
->frame
);
2666 return process_ast_dsp(tmp
, &tmp
->frame
);
2673 static int misdn_write(struct ast_channel
*ast
, struct ast_frame
*frame
)
2675 struct chan_list
*ch
;
2678 if (!ast
|| ! (ch
= MISDN_ASTERISK_TECH_PVT(ast
)) ) return -1;
2680 if (ch
->state
== MISDN_HOLDED
) {
2681 chan_misdn_log(7, 0, "misdn_write: Returning because holded\n");
2686 ast_log(LOG_WARNING
, "private but no bc\n");
2691 chan_misdn_log(7, ch
->bc
->port
, "misdn_write: Returning because notxtone\n");
2696 if (!frame
->subclass
) {
2697 chan_misdn_log(4, ch
->bc
->port
, "misdn_write: * prods us\n");
2701 if (!(frame
->subclass
& prefformat
)) {
2703 chan_misdn_log(-1, ch
->bc
->port
, "Got Unsupported Frame with Format:%d\n", frame
->subclass
);
2708 if (!frame
->samples
) {
2709 chan_misdn_log(4, ch
->bc
->port
, "misdn_write: zero write\n");
2711 if (!strcmp(frame
->src
,"ast_prod")) {
2712 chan_misdn_log(1, ch
->bc
->port
, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch
));
2715 chan_misdn_log(4, ch
->bc
->port
, "Starting Playtones\n");
2716 misdn_lib_tone_generator_start(ch
->bc
);
2724 if ( ! ch
->bc
->addr
) {
2725 chan_misdn_log(8, ch
->bc
->port
, "misdn_write: no addr for bc dropping:%d\n", frame
->samples
);
2731 int i
, max
= 5 > frame
->samples
? frame
->samples
: 5;
2733 printf("write2mISDN %p %d bytes: ", p
, frame
->samples
);
2735 for (i
= 0; i
< max
; i
++)
2736 printf("%2.2x ", ((char*) frame
->data
)[i
]);
2741 switch (ch
->bc
->bc_state
) {
2742 case BCHAN_ACTIVATED
:
2746 if (!ch
->dropped_frame_cnt
)
2747 chan_misdn_log(5, ch
->bc
->port
, "BC not active (nor bridged) dropping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n", frame
->samples
, ch
->bc
->addr
, ast
->exten
, ast
->cid
.cid_num
, misdn_get_ch_state( ch
), ch
->bc
->bc_state
, ch
->bc
->l3_id
);
2749 ch
->dropped_frame_cnt
++;
2750 if (ch
->dropped_frame_cnt
> 100) {
2751 ch
->dropped_frame_cnt
= 0;
2752 chan_misdn_log(5, ch
->bc
->port
, "BC not active (nor bridged) dropping: %d frames addr:%x dropped > 100 frames!\n", frame
->samples
, ch
->bc
->addr
);
2758 chan_misdn_log(9, ch
->bc
->port
, "Sending :%d bytes to MISDN\n", frame
->samples
);
2759 if ( !ch
->bc
->nojitter
&& misdn_cap_is_speech(ch
->bc
->capability
) ) {
2760 /* Buffered Transmit (triggered by read from isdn side)*/
2761 if (misdn_jb_fill(ch
->jb
, frame
->data
, frame
->samples
) < 0) {
2763 cb_log(0, ch
->bc
->port
, "Misdn Jitterbuffer Overflow.\n");
2767 /*transmit without jitterbuffer*/
2768 i
= misdn_lib_tx2misdn_frm(ch
->bc
, frame
->data
, frame
->samples
);
2777 static enum ast_bridge_result
misdn_bridge (struct ast_channel
*c0
,
2778 struct ast_channel
*c1
, int flags
,
2779 struct ast_frame
**fo
,
2780 struct ast_channel
**rc
,
2784 struct chan_list
*ch1
, *ch2
;
2785 struct ast_channel
*carr
[2], *who
;
2787 struct ast_frame
*f
;
2791 ch1
= get_chan_by_ast(c0
);
2792 ch2
= get_chan_by_ast(c1
);
2800 misdn_cfg_get(ch1
->bc
->port
, MISDN_CFG_BRIDGING
, &p1_b
, sizeof(int));
2801 misdn_cfg_get(ch2
->bc
->port
, MISDN_CFG_BRIDGING
, &p2_b
, sizeof(int));
2803 if (! p1_b
|| ! p2_b
) {
2804 ast_log(LOG_NOTICE
, "Falling back to Asterisk bridging\n");
2805 return AST_BRIDGE_FAILED
;
2808 misdn_cfg_get(0, MISDN_GEN_BRIDGING
, &bridging
, sizeof(int));
2810 /* trying to make a mISDN_dsp conference */
2811 chan_misdn_log(1, ch1
->bc
->port
, "I SEND: Making conference with Number:%d\n", ch1
->bc
->pid
+ 1);
2812 misdn_lib_bridge(ch1
->bc
, ch2
->bc
);
2815 if (option_verbose
> 2)
2816 ast_verbose(VERBOSE_PREFIX_3
"Native bridging %s and %s\n", c0
->name
, c1
->name
);
2818 chan_misdn_log(1, ch1
->bc
->port
, "* Making Native Bridge between %s and %s\n", ch1
->bc
->oad
, ch2
->bc
->oad
);
2820 if (! (flags
& AST_BRIDGE_DTMF_CHANNEL_0
) )
2821 ch1
->ignore_dtmf
= 1;
2823 if (! (flags
& AST_BRIDGE_DTMF_CHANNEL_1
) )
2824 ch2
->ignore_dtmf
= 1;
2828 who
= ast_waitfor_n(carr
, 2, &to
);
2831 ast_log(LOG_NOTICE
, "misdn_bridge: empty read, breaking out\n");
2836 if (!f
|| f
->frametype
== AST_FRAME_CONTROL
) {
2840 chan_misdn_log(4, ch1
->bc
->port
, "Read Null Frame\n");
2842 chan_misdn_log(4, ch1
->bc
->port
, "Read Frame Control class:%d\n", f
->subclass
);
2849 if ( f
->frametype
== AST_FRAME_DTMF
) {
2850 chan_misdn_log(1, 0, "Read DTMF %d from %s\n", f
->subclass
, who
->exten
);
2858 if (f
->frametype
== AST_FRAME_VOICE
) {
2859 chan_misdn_log(1, ch1
->bc
->port
, "I SEND: Splitting conference with Number:%d\n", ch1
->bc
->pid
+1);
2873 chan_misdn_log(1, ch1
->bc
->port
, "I SEND: Splitting conference with Number:%d\n", ch1
->bc
->pid
+ 1);
2875 misdn_lib_split_bridge(ch1
->bc
, ch2
->bc
);
2877 return AST_BRIDGE_COMPLETE
;
2880 /** AST INDICATIONS END **/
2882 static int dialtone_indicate(struct chan_list
*cl
)
2884 const struct ind_tone_zone_sound
*ts
= NULL
;
2885 struct ast_channel
*ast
= cl
->ast
;
2889 chan_misdn_log(0, cl
->bc
->port
, "No Ast in dialtone_indicate\n");
2893 misdn_cfg_get(cl
->bc
->port
, MISDN_CFG_NODIALTONE
, &nd
, sizeof(nd
));
2896 chan_misdn_log(1, cl
->bc
->port
, "Not sending Dialtone, because config wants it\n");
2900 chan_misdn_log(3, cl
->bc
->port
, " --> Dial\n");
2901 ts
= ast_get_indication_tone(ast
->zone
, "dial");
2907 /* This prods us in misdn_write */
2908 ast_playtones_start(ast
, 0, ts
->data
, 0);
2914 static int hanguptone_indicate(struct chan_list
*cl
)
2916 misdn_lib_send_tone(cl
->bc
, TONE_HANGUP
);
2920 static int stop_indicate(struct chan_list
*cl
)
2922 struct ast_channel
*ast
= cl
->ast
;
2925 chan_misdn_log(0, cl
->bc
->port
, "No Ast in stop_indicate\n");
2929 chan_misdn_log(3, cl
->bc
->port
, " --> None\n");
2930 misdn_lib_tone_generator_stop(cl
->bc
);
2931 ast_playtones_stop(ast
);
2934 /*ast_deactivate_generator(ast);*/
2940 static int start_bc_tones(struct chan_list
* cl
)
2942 misdn_lib_tone_generator_stop(cl
->bc
);
2948 static int stop_bc_tones(struct chan_list
*cl
)
2959 static struct chan_list
*init_chan_list(int orig
)
2961 struct chan_list
*cl
;
2963 cl
= calloc(1, sizeof(struct chan_list
));
2965 chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
2969 cl
->originator
= orig
;
2970 cl
->need_queue_hangup
= 1;
2971 cl
->need_hangup
= 1;
2973 cl
->overlap_dial_task
= -1;
2978 static struct ast_channel
*misdn_request(const char *type
, int format
, void *data
, int *cause
)
2980 struct ast_channel
*tmp
= NULL
;
2981 char group
[BUFFERSIZE
+ 1] = "";
2983 char buf2
[128], *ext
= NULL
, *port_str
;
2984 char *tokb
= NULL
, *p
= NULL
;
2985 int channel
= 0, port
= 0;
2986 struct misdn_bchannel
*newbc
= NULL
;
2989 struct chan_list
*cl
= init_chan_list(ORG_AST
);
2991 snprintf(buf
, sizeof(buf
), "%s/%s", misdn_type
, (char*)data
);
2992 ast_copy_string(buf2
, data
, 128);
2994 port_str
= strtok_r(buf2
, "/", &tokb
);
2996 ext
= strtok_r(NULL
, "/", &tokb
);
2999 if (port_str
[0] == 'g' && port_str
[1] == ':' ) {
3000 /* We make a group call lets checkout which ports are in my group */
3002 ast_copy_string(group
, port_str
, sizeof(group
));
3003 chan_misdn_log(2, 0, " --> Group Call group: %s\n", group
);
3004 } else if ((p
= strchr(port_str
, ':'))) {
3005 /* we have a preselected channel */
3007 channel
= atoi(++p
);
3008 port
= atoi(port_str
);
3009 chan_misdn_log(2, port
, " --> Call on preselected Channel (%d).\n", channel
);
3011 port
= atoi(port_str
);
3014 ast_log(LOG_WARNING
, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extensions.conf\n", ext
);
3018 if (misdn_cfg_is_group_method(group
, METHOD_STANDARD_DEC
)) {
3019 chan_misdn_log(4, port
, " --> STARTING STANDARD DEC...\n");
3023 if (!ast_strlen_zero(group
)) {
3024 char cfg_group
[BUFFERSIZE
+ 1];
3025 struct robin_list
*rr
= NULL
;
3027 if (misdn_cfg_is_group_method(group
, METHOD_ROUND_ROBIN
)) {
3028 chan_misdn_log(4, port
, " --> STARTING ROUND ROBIN...\n");
3029 rr
= get_robin_position(group
);
3034 int port_bak
= rr
->port
;
3035 int chan_bak
= rr
->channel
;
3038 rr
->port
= misdn_cfg_get_next_port_spin(rr
->port
);
3040 for (; rr
->port
> 0; rr
->port
= misdn_cfg_get_next_port_spin(rr
->port
)) {
3044 int last_chance
= 0;
3046 misdn_cfg_get(rr
->port
, MISDN_CFG_GROUPNAME
, cfg_group
, BUFFERSIZE
);
3047 if (strcasecmp(cfg_group
, group
))
3050 misdn_cfg_get(rr
->port
, MISDN_CFG_PMP_L1_CHECK
, &check
, sizeof(int));
3051 port_up
= misdn_lib_port_up(rr
->port
, check
);
3053 if (check
&& !port_up
)
3054 chan_misdn_log(1, rr
->port
, "L1 is not Up on this Port\n");
3056 if (check
&& port_up
< 0)
3057 ast_log(LOG_WARNING
,"This port (%d) is blocked\n", rr
->port
);
3059 if ((port_start
== rr
->port
) && (port_up
<= 0))
3063 port_start
= rr
->port
;
3068 max_chan
= misdn_lib_get_maxchans(rr
->port
);
3070 for (++rr
->channel
; !last_chance
&& rr
->channel
<= max_chan
; ++rr
->channel
) {
3071 if (rr
->port
== port_bak
&& rr
->channel
== chan_bak
)
3074 chan_misdn_log(1, 0, "trying port:%d channel:%d\n", rr
->port
, rr
->channel
);
3075 newbc
= misdn_lib_get_free_bc(rr
->port
, rr
->channel
, 0, 0);
3077 chan_misdn_log(4, rr
->port
, " Success! Found port:%d channel:%d\n", newbc
->port
, newbc
->channel
);
3079 chan_misdn_log(4, rr
->port
, "portup:%d\n", port_up
);
3085 if (newbc
|| last_chance
)
3091 rr
->port
= port_bak
;
3092 rr
->channel
= chan_bak
;
3095 for (port
= misdn_cfg_get_next_port(0); port
> 0;
3096 port
= misdn_cfg_get_next_port(port
)) {
3098 misdn_cfg_get(port
, MISDN_CFG_GROUPNAME
, cfg_group
, BUFFERSIZE
);
3100 chan_misdn_log(3, port
, "Group [%s] Port [%d]\n", group
, port
);
3101 if (!strcasecmp(cfg_group
, group
)) {
3104 misdn_cfg_get(port
, MISDN_CFG_PMP_L1_CHECK
, &check
, sizeof(int));
3105 port_up
= misdn_lib_port_up(port
, check
);
3107 chan_misdn_log(4, port
, "portup:%d\n", port_up
);
3110 newbc
= misdn_lib_get_free_bc(port
, 0, 0, dec
);
3118 /* Group dial failed ?*/
3120 ast_log(LOG_WARNING
,
3121 "Could not Dial out on group '%s'.\n"
3122 "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
3123 "\tOr there was no free channel on none of the ports\n\n"
3127 } else { /* 'Normal' Port dial * Port dial */
3129 chan_misdn_log(1, port
, " --> preselected_channel: %d\n", channel
);
3130 newbc
= misdn_lib_get_free_bc(port
, channel
, 0, dec
);
3133 ast_log(LOG_WARNING
, "Could not create channel on port:%d with extensions:%s\n", port
, ext
);
3139 /* create ast_channel and link all the objects together */
3142 tmp
= misdn_new(cl
, AST_STATE_RESERVED
, ext
, NULL
, format
, port
, channel
);
3144 ast_log(LOG_ERROR
,"Could not create Asterisk object\n");
3150 /* register chan in local list */
3151 cl_queue_chan(&cl_te
, cl
) ;
3153 /* fill in the config into the objects */
3154 read_config(cl
, ORG_AST
);
3157 cl
->need_hangup
= 0;
3163 static int misdn_send_text(struct ast_channel
*chan
, const char *text
)
3165 struct chan_list
*tmp
= chan
->tech_pvt
;
3167 if (tmp
&& tmp
->bc
) {
3168 ast_copy_string(tmp
->bc
->display
, text
, sizeof(tmp
->bc
->display
));
3169 misdn_lib_send_event(tmp
->bc
, EVENT_INFORMATION
);
3171 ast_log(LOG_WARNING
, "No chan_list but send_text request?\n");
3178 static struct ast_channel_tech misdn_tech
= {
3180 .description
= "Channel driver for mISDN Support (Bri/Pri)",
3181 .capabilities
= AST_FORMAT_ALAW
,
3182 .requester
= misdn_request
,
3183 .send_digit_begin
= misdn_digit_begin
,
3184 .send_digit_end
= misdn_digit_end
,
3186 .bridge
= misdn_bridge
,
3187 .hangup
= misdn_hangup
,
3188 .answer
= misdn_answer
,
3190 .write
= misdn_write
,
3191 .indicate
= misdn_indication
,
3192 .fixup
= misdn_fixup
,
3193 .send_text
= misdn_send_text
,
3197 static struct ast_channel_tech misdn_tech_wo_bridge
= {
3199 .description
= "Channel driver for mISDN Support (Bri/Pri)",
3200 .capabilities
= AST_FORMAT_ALAW
,
3201 .requester
= misdn_request
,
3202 .send_digit_begin
= misdn_digit_begin
,
3203 .send_digit_end
= misdn_digit_end
,
3205 .hangup
= misdn_hangup
,
3206 .answer
= misdn_answer
,
3208 .write
= misdn_write
,
3209 .indicate
= misdn_indication
,
3210 .fixup
= misdn_fixup
,
3211 .send_text
= misdn_send_text
,
3216 static int glob_channel
= 0;
3218 static void update_name(struct ast_channel
*tmp
, int port
, int c
)
3220 int chan_offset
= 0;
3221 int tmp_port
= misdn_cfg_get_next_port(0);
3222 for (; tmp_port
> 0; tmp_port
= misdn_cfg_get_next_port(tmp_port
)) {
3223 if (tmp_port
== port
)
3225 chan_offset
+= misdn_lib_port_is_pri(tmp_port
) ? 30 : 2;
3230 ast_string_field_build(tmp
, name
, "%s/%d-u%d",
3231 misdn_type
, chan_offset
+ c
, glob_channel
++);
3233 chan_misdn_log(3, port
, " --> updating channel name to [%s]\n", tmp
->name
);
3236 static struct ast_channel
*misdn_new(struct chan_list
*chlist
, int state
, char *exten
, char *callerid
, int format
, int port
, int c
)
3238 struct ast_channel
*tmp
;
3239 char *cid_name
= 0, *cid_num
= 0;
3240 int chan_offset
= 0;
3241 int tmp_port
= misdn_cfg_get_next_port(0);
3244 for (; tmp_port
> 0; tmp_port
= misdn_cfg_get_next_port(tmp_port
)) {
3245 if (tmp_port
== port
)
3247 chan_offset
+= misdn_lib_port_is_pri(tmp_port
) ? 30 : 2;
3253 ast_callerid_parse(callerid
, &cid_name
, &cid_num
);
3256 tmp
= ast_channel_alloc(1, state
, cid_num
, cid_name
, "", exten
, "", 0, "%s/%d-u%d", misdn_type
, chan_offset
+ c
, glob_channel
++);
3258 chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n", exten
, callerid
);
3260 tmp
->nativeformats
= prefformat
;
3262 tmp
->readformat
= format
;
3263 tmp
->rawreadformat
= format
;
3264 tmp
->writeformat
= format
;
3265 tmp
->rawwriteformat
= format
;
3267 tmp
->tech_pvt
= chlist
;
3269 misdn_cfg_get(0, MISDN_GEN_BRIDGING
, &bridging
, sizeof(int));
3272 tmp
->tech
= &misdn_tech
;
3274 tmp
->tech
= &misdn_tech_wo_bridge
;
3276 tmp
->writeformat
= format
;
3277 tmp
->readformat
= format
;
3281 ast_copy_string(tmp
->exten
, exten
, sizeof(tmp
->exten
));
3283 chan_misdn_log(1, 0, "misdn_new: no exten given.\n");
3286 /* Don't use ast_set_callerid() here because it will
3287 * generate a needless NewCallerID event */
3288 tmp
->cid
.cid_ani
= ast_strdup(cid_num
);
3290 if (pipe(chlist
->pipe
) < 0)
3291 perror("Pipe failed\n");
3292 tmp
->fds
[0] = chlist
->pipe
[0];
3294 if (state
== AST_STATE_RING
)
3300 chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
3306 static struct chan_list
*find_chan_by_bc(struct chan_list
*list
, struct misdn_bchannel
*bc
)
3308 struct chan_list
*help
= list
;
3309 for (; help
; help
= help
->next
) {
3310 if (help
->bc
== bc
) return help
;
3313 chan_misdn_log(6, bc
->port
, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc
->oad
, bc
->dad
);
3318 static struct chan_list
*find_chan_by_pid(struct chan_list
*list
, int pid
)
3320 struct chan_list
*help
= list
;
3321 for (; help
; help
= help
->next
) {
3322 if ( help
->bc
&& (help
->bc
->pid
== pid
) ) return help
;
3325 chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n", pid
);
3330 static struct chan_list
*find_holded(struct chan_list
*list
, struct misdn_bchannel
*bc
)
3332 struct chan_list
*help
= list
;
3334 if (bc
->pri
) return NULL
;
3336 chan_misdn_log(6, bc
->port
, "$$$ find_holded: channel:%d oad:%s dad:%s\n", bc
->channel
, bc
->oad
, bc
->dad
);
3337 for (;help
; help
= help
->next
) {
3338 chan_misdn_log(4, bc
->port
, "$$$ find_holded: --> holded:%d channel:%d\n", help
->state
== MISDN_HOLDED
, help
->hold_info
.channel
);
3339 if ((help
->state
== MISDN_HOLDED
) &&
3340 (help
->hold_info
.port
== bc
->port
))
3343 chan_misdn_log(6, bc
->port
, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc
->oad
, bc
->dad
);
3349 static struct chan_list
*find_holded_l3(struct chan_list
*list
, unsigned long l3_id
, int w
)
3351 struct chan_list
*help
= list
;
3353 for (; help
; help
= help
->next
) {
3354 if ( (help
->state
== MISDN_HOLDED
) &&
3355 (help
->l3id
== l3_id
)
3363 static void cl_queue_chan(struct chan_list
**list
, struct chan_list
*chan
)
3365 chan_misdn_log(4, chan
->bc
? chan
->bc
->port
: 0, "* Queuing chan %p\n", chan
);
3367 ast_mutex_lock(&cl_te_lock
);
3371 struct chan_list
*help
= *list
;
3372 for (; help
->next
; help
= help
->next
);
3376 ast_mutex_unlock(&cl_te_lock
);
3379 static void cl_dequeue_chan(struct chan_list
**list
, struct chan_list
*chan
)
3381 struct chan_list
*help
;
3384 ast_dsp_free(chan
->dsp
);
3386 ast_translator_free_path(chan
->trans
);
3388 ast_mutex_lock(&cl_te_lock
);
3390 ast_mutex_unlock(&cl_te_lock
);
3394 if (*list
== chan
) {
3395 *list
= (*list
)->next
;
3396 ast_mutex_unlock(&cl_te_lock
);
3400 for (help
= *list
; help
->next
; help
= help
->next
) {
3401 if (help
->next
== chan
) {
3402 help
->next
= help
->next
->next
;
3403 ast_mutex_unlock(&cl_te_lock
);
3408 ast_mutex_unlock(&cl_te_lock
);
3411 /** Channel Queue End **/
3414 static int pbx_start_chan(struct chan_list
*ch
)
3416 int ret
= ast_pbx_start(ch
->ast
);
3419 ch
->need_hangup
= 0;
3421 ch
->need_hangup
= 1;
3426 static void hangup_chan(struct chan_list
*ch
)
3428 int port
= ch
? (ch
->bc
? ch
->bc
->port
: 0) : 0;
3430 cb_log(1, 0, "Cannot hangup chan, no ch\n");
3434 cb_log(5, port
, "hangup_chan called\n");
3436 if (ch
->need_hangup
) {
3437 cb_log(2, port
, " --> hangup\n");
3438 send_cause2ast(ch
->ast
, ch
->bc
, ch
);
3439 ch
->need_hangup
= 0;
3440 ch
->need_queue_hangup
= 0;
3442 ast_hangup(ch
->ast
);
3446 if (!ch
->need_queue_hangup
) {
3447 cb_log(2, port
, " --> No need to queue hangup\n");
3450 ch
->need_queue_hangup
= 0;
3452 send_cause2ast(ch
->ast
, ch
->bc
, ch
);
3455 ast_queue_hangup(ch
->ast
);
3456 cb_log(2, port
, " --> queue_hangup\n");
3458 cb_log(1, port
, "Cannot hangup chan, no ast\n");
3462 /** Isdn asks us to release channel, pendant to misdn_hangup **/
3463 static void release_chan(struct misdn_bchannel
*bc
) {
3464 struct ast_channel
*ast
= NULL
;
3466 ast_mutex_lock(&release_lock
);
3468 struct chan_list
*ch
=find_chan_by_bc(cl_te
, bc
);
3470 chan_misdn_log(1, bc
->port
, "release_chan: Ch not found!\n");
3471 ast_mutex_unlock(&release_lock
);
3479 chan_misdn_log(5, bc
->port
, "release_chan: bc with l3id: %x\n", bc
->l3_id
);
3481 /*releasing jitterbuffer*/
3483 misdn_jb_destroy(ch
->jb
);
3487 chan_misdn_log(5, bc
->port
, "Jitterbuffer already destroyed.\n");
3490 if (ch
->overlap_dial
) {
3491 if (ch
->overlap_dial_task
!= -1) {
3492 misdn_tasks_remove(ch
->overlap_dial_task
);
3493 ch
->overlap_dial_task
= -1;
3495 ast_mutex_destroy(&ch
->overlap_tv_lock
);
3498 if (ch
->originator
== ORG_AST
) {
3499 misdn_out_calls
[bc
->port
]--;
3501 misdn_in_calls
[bc
->port
]--;
3508 if (ast
&& MISDN_ASTERISK_TECH_PVT(ast
)) {
3509 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
));
3510 chan_misdn_log(3, bc
->port
, " --> * State Down\n");
3511 MISDN_ASTERISK_TECH_PVT(ast
) = NULL
;
3513 if (ast
->_state
!= AST_STATE_RESERVED
) {
3514 chan_misdn_log(3, bc
->port
, " --> Setting AST State to down\n");
3515 ast_setstate(ast
, AST_STATE_DOWN
);
3519 ch
->state
= MISDN_CLEANING
;
3520 cl_dequeue_chan(&cl_te
, ch
);
3524 /* chan is already cleaned, so exiting */
3527 ast_mutex_unlock(&release_lock
);
3528 /*** release end **/
3531 static void misdn_transfer_bc(struct chan_list
*tmp_ch
, struct chan_list
*holded_chan
)
3533 chan_misdn_log(4, 0, "TRANSFERRING %s to %s\n", holded_chan
->ast
->name
, tmp_ch
->ast
->name
);
3535 tmp_ch
->state
= MISDN_HOLD_DISCONNECT
;
3537 ast_moh_stop(ast_bridged_channel(holded_chan
->ast
));
3539 holded_chan
->state
=MISDN_CONNECTED
;
3540 /* misdn_lib_transfer(holded_chan->bc); */
3541 ast_channel_masquerade(holded_chan
->ast
, ast_bridged_channel(tmp_ch
->ast
));
3545 static void do_immediate_setup(struct misdn_bchannel
*bc
, struct chan_list
*ch
, struct ast_channel
*ast
)
3547 char predial
[256]="";
3550 struct ast_frame fr
;
3552 strncpy(predial
, ast
->exten
, sizeof(predial
) -1 );
3554 ch
->state
= MISDN_DIALING
;
3556 if (!ch
->noautorespond_on_setup
) {
3559 ret
= misdn_lib_send_event(bc
, EVENT_SETUP_ACKNOWLEDGE
);
3562 if ( misdn_lib_is_ptp(bc
->port
)) {
3563 ret
= misdn_lib_send_event(bc
, EVENT_SETUP_ACKNOWLEDGE
);
3565 ret
= misdn_lib_send_event(bc
, EVENT_PROCEEDING
);
3569 ch
->state
= MISDN_INCOMING_SETUP
;
3572 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
);
3574 strncpy(ast
->exten
, "s", 2);
3576 if (pbx_start_chan(ch
) < 0) {
3579 hanguptone_indicate(ch
);
3582 misdn_lib_send_event(bc
, EVENT_RELEASE_COMPLETE
);
3584 misdn_lib_send_event(bc
, EVENT_DISCONNECT
);
3588 while (!ast_strlen_zero(p
) ) {
3589 fr
.frametype
= AST_FRAME_DTMF
;
3597 fr
.delivery
= ast_tv(0,0);
3599 if (ch
->ast
&& MISDN_ASTERISK_PVT(ch
->ast
) && MISDN_ASTERISK_TECH_PVT(ch
->ast
)) {
3600 ast_queue_frame(ch
->ast
, &fr
);
3608 static void send_cause2ast(struct ast_channel
*ast
, struct misdn_bchannel
*bc
, struct chan_list
*ch
) {
3610 chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
3614 chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
3618 chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
3622 ast
->hangupcause
= bc
->cause
;
3624 switch (bc
->cause
) {
3626 case AST_CAUSE_UNALLOCATED
:
3627 case AST_CAUSE_NO_ROUTE_TRANSIT_NET
:
3628 case AST_CAUSE_NO_ROUTE_DESTINATION
:
3629 case 4: /* Send special information tone */
3630 case AST_CAUSE_NUMBER_CHANGED
:
3631 case AST_CAUSE_DESTINATION_OUT_OF_ORDER
:
3632 /* Congestion Cases */
3634 * Not Queueing the Congestion anymore, since we want to hear
3635 * the inband message
3637 chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Congestion pid:%d\n", bc ? bc->pid : -1);
3638 ch->state = MISDN_BUSY;
3640 ast_queue_control(ast, AST_CONTROL_CONGESTION);
3644 case AST_CAUSE_CALL_REJECTED
:
3645 case AST_CAUSE_USER_BUSY
:
3646 ch
->state
= MISDN_BUSY
;
3648 if (!ch
->need_busy
) {
3649 chan_misdn_log(1, bc
? bc
->port
: 0, "Queued busy already\n");
3653 chan_misdn_log(1, bc
? bc
->port
: 0, " --> * SEND: Queue Busy pid:%d\n", bc
? bc
->pid
: -1);
3655 ast_queue_control(ast
, AST_CONTROL_BUSY
);
3664 void import_ch(struct ast_channel
*chan
, struct misdn_bchannel
*bc
, struct chan_list
*ch
)
3668 tmp
= pbx_builtin_getvar_helper(chan
, "MISDN_PID");
3670 ch
->other_pid
= atoi(tmp
);
3671 chan_misdn_log(3, bc
->port
, " --> IMPORT_PID: importing pid:%s\n", tmp
);
3672 if (ch
->other_pid
> 0) {
3673 ch
->other_ch
= find_chan_by_pid(cl_te
, ch
->other_pid
);
3675 ch
->other_ch
->other_ch
= ch
;
3679 tmp
= pbx_builtin_getvar_helper(chan
, "MISDN_ADDRESS_COMPLETE");
3680 if (tmp
&& (atoi(tmp
) == 1)) {
3681 bc
->sending_complete
= 1;
3684 tmp
= pbx_builtin_getvar_helper(chan
, "MISDN_USERUSER");
3686 ast_log(LOG_NOTICE
, "MISDN_USERUSER: %s\n", tmp
);
3687 ast_copy_string(bc
->uu
, tmp
, sizeof(bc
->uu
));
3688 bc
->uulen
= strlen(bc
->uu
);
3691 tmp
= pbx_builtin_getvar_helper(chan
, "MISDN_KEYPAD");
3693 ast_copy_string(bc
->keypad
, tmp
, sizeof(bc
->keypad
));
3697 void export_ch(struct ast_channel
*chan
, struct misdn_bchannel
*bc
, struct chan_list
*ch
)
3700 chan_misdn_log(3, bc
->port
, " --> EXPORT_PID: pid:%d\n", bc
->pid
);
3701 snprintf(tmp
, sizeof(tmp
), "%d", bc
->pid
);
3702 pbx_builtin_setvar_helper(chan
, "_MISDN_PID", tmp
);
3704 if (bc
->sending_complete
) {
3705 snprintf(tmp
, sizeof(tmp
), "%d", bc
->sending_complete
);
3706 pbx_builtin_setvar_helper(chan
, "MISDN_ADDRESS_COMPLETE", tmp
);
3710 snprintf(tmp
, sizeof(tmp
), "%d", bc
->urate
);
3711 pbx_builtin_setvar_helper(chan
, "MISDN_URATE", tmp
);
3714 if (bc
->uulen
&& (bc
->uulen
< sizeof(bc
->uu
))) {
3715 bc
->uu
[bc
->uulen
] = 0;
3716 pbx_builtin_setvar_helper(chan
, "MISDN_USERUSER", bc
->uu
);
3719 if (!ast_strlen_zero(bc
->keypad
))
3720 pbx_builtin_setvar_helper(chan
, "MISDN_KEYPAD", bc
->keypad
);
3723 int add_in_calls(int port
)
3727 misdn_cfg_get(port
, MISDN_CFG_MAX_IN
, &max_in_calls
, sizeof(max_in_calls
));
3728 misdn_in_calls
[port
]++;
3730 if (max_in_calls
>= 0 && max_in_calls
< misdn_in_calls
[port
]) {
3731 ast_log(LOG_NOTICE
, "Marking Incoming Call on port[%d]\n", port
);
3732 return misdn_in_calls
[port
] - max_in_calls
;
3738 int add_out_calls(int port
)
3742 misdn_cfg_get(port
, MISDN_CFG_MAX_OUT
, &max_out_calls
, sizeof(max_out_calls
));
3744 if (max_out_calls
>= 0 && max_out_calls
<= misdn_out_calls
[port
]) {
3745 ast_log(LOG_NOTICE
, "Rejecting Outgoing Call on port[%d]\n", port
);
3746 return (misdn_out_calls
[port
] + 1) - max_out_calls
;
3749 misdn_out_calls
[port
]++;
3754 static void start_pbx(struct chan_list
*ch
, struct misdn_bchannel
*bc
, struct ast_channel
*chan
) {
3755 if (pbx_start_chan(ch
) < 0) {
3757 chan_misdn_log(-1, bc
->port
, "ast_pbx_start returned <0 in SETUP\n");
3759 hanguptone_indicate(ch
);
3760 misdn_lib_send_event(bc
, EVENT_RELEASE_COMPLETE
);
3762 misdn_lib_send_event(bc
, EVENT_RELEASE
);
3766 static void wait_for_digits(struct chan_list
*ch
, struct misdn_bchannel
*bc
, struct ast_channel
*chan
) {
3767 ch
->state
=MISDN_WAITING4DIGS
;
3768 misdn_lib_send_event(bc
, EVENT_SETUP_ACKNOWLEDGE
);
3769 if (bc
->nt
&& !bc
->dad
[0])
3770 dialtone_indicate(ch
);
3774 /************************************************************/
3775 /* Receive Events from isdn_lib here */
3776 /************************************************************/
3777 static enum event_response_e
3778 cb_events(enum event_e event
, struct misdn_bchannel
*bc
, void *user_data
)
3781 struct chan_list
*ch
= find_chan_by_bc(cl_te
, bc
);
3783 if (event
!= EVENT_BCHAN_DATA
&& event
!= EVENT_TONE_GENERATE
) { /* Debug Only Non-Bchan */
3785 if ( event
== EVENT_CLEANUP
&& !user_data
)
3788 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");
3789 if (debuglevel
== 1) {
3790 misdn_lib_log_ies(bc
);
3791 chan_misdn_log(4, bc
->port
, " --> bc_state:%s\n", bc_state2str(bc
->bc_state
));
3798 case EVENT_DISCONNECT
:
3799 case EVENT_PORT_ALARM
:
3800 case EVENT_RETRIEVE
:
3802 case EVENT_FACILITY
:
3804 case EVENT_RELEASE_COMPLETE
:
3805 chan_misdn_log(1, bc
->port
, " --> no Ch, so we've already released.\n");
3808 case EVENT_TONE_GENERATE
:
3809 case EVENT_BCHAN_DATA
:
3812 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
);
3819 case EVENT_TONE_GENERATE
:
3821 case EVENT_DISCONNECT
:
3823 case EVENT_RELEASE_COMPLETE
:
3827 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
));
3830 if (!ch
->ast
|| !MISDN_ASTERISK_PVT(ch
->ast
) || !MISDN_ASTERISK_TECH_PVT(ch
->ast
)) {
3831 if (event
!= EVENT_BCHAN_DATA
)
3832 ast_log(LOG_NOTICE
, "No Ast or No private Pointer in Event (%d:%s)\n", event
, manager_isdn_get_info(event
));
3840 case EVENT_PORT_ALARM
:
3843 misdn_cfg_get(bc
->port
, MISDN_CFG_ALARM_BLOCK
, &boa
, sizeof(int));
3845 cb_log(1, bc
->port
, " --> blocking\n");
3846 misdn_lib_port_block(bc
->port
);
3850 case EVENT_BCHAN_ACTIVATED
:
3853 case EVENT_NEW_CHANNEL
:
3854 update_name(ch
->ast
,bc
->port
,bc
->channel
);
3857 case EVENT_NEW_L3ID
:
3864 ch
= find_holded(cl_te
,bc
);
3868 ast_log(LOG_WARNING
, "NEW_BC without chan_list?\n");
3873 ch
->bc
= (struct misdn_bchannel
*)user_data
;
3876 case EVENT_DTMF_TONE
:
3878 /* sending INFOS as DTMF-Frames :) */
3879 struct ast_frame fr
;
3881 memset(&fr
, 0, sizeof(fr
));
3882 fr
.frametype
= AST_FRAME_DTMF
;
3883 fr
.subclass
= bc
->dtmf
;
3890 fr
.delivery
= ast_tv(0,0);
3892 if (!ch
->ignore_dtmf
) {
3893 chan_misdn_log(2, bc
->port
, " --> DTMF:%c\n", bc
->dtmf
);
3894 ast_queue_frame(ch
->ast
, &fr
);
3896 chan_misdn_log(2, bc
->port
, " --> Ignoring DTMF:%c due to bridge flags\n", bc
->dtmf
);
3903 case EVENT_INFORMATION
:
3905 if ( ch
->state
!= MISDN_CONNECTED
)
3911 if (ch
->state
== MISDN_WAITING4DIGS
) {
3912 /* Ok, incomplete Setup, waiting till extension exists */
3913 if (ast_strlen_zero(bc
->info_dad
) && ! ast_strlen_zero(bc
->keypad
)) {
3914 chan_misdn_log(1, bc
->port
, " --> using keypad as info\n");
3915 ast_copy_string(bc
->info_dad
, bc
->keypad
, sizeof(bc
->info_dad
));
3918 strncat(bc
->dad
, bc
->info_dad
, sizeof(bc
->dad
) - strlen(bc
->dad
) - 1);
3919 ast_copy_string(ch
->ast
->exten
, bc
->dad
, sizeof(ch
->ast
->exten
));
3921 /* Check for Pickup Request first */
3922 if (!strcmp(ch
->ast
->exten
, ast_pickup_ext())) {
3923 if (ast_pickup_call(ch
->ast
)) {
3926 struct ast_channel
*chan
= ch
->ast
;
3927 ch
->state
= MISDN_CALLING_ACKNOWLEDGE
;
3928 ast_setstate(chan
, AST_STATE_DOWN
);
3935 if (!ast_canmatch_extension(ch
->ast
, ch
->context
, bc
->dad
, 1, bc
->oad
)) {
3936 if (ast_exists_extension(ch
->ast
, ch
->context
, "i", 1, bc
->oad
)) {
3937 ast_log(LOG_WARNING
, "Extension can never match, So jumping to 'i' extension. port(%d)\n", bc
->port
);
3938 strcpy(ch
->ast
->exten
, "i");
3940 ch
->state
= MISDN_DIALING
;
3941 start_pbx(ch
, bc
, ch
->ast
);
3945 ast_log(LOG_WARNING
, "Extension can never match, so disconnecting on port(%d).\n"
3946 "\tMaybe you want to add an 'i' extension to catch this case.\n",
3950 hanguptone_indicate(ch
);
3951 ch
->state
= MISDN_EXTCANTMATCH
;
3952 bc
->out_cause
= AST_CAUSE_UNALLOCATED
;
3954 misdn_lib_send_event(bc
, EVENT_DISCONNECT
);
3958 if (ch
->overlap_dial
) {
3959 ast_mutex_lock(&ch
->overlap_tv_lock
);
3960 ch
->overlap_tv
= ast_tvnow();
3961 ast_mutex_unlock(&ch
->overlap_tv_lock
);
3962 if (ch
->overlap_dial_task
== -1) {
3963 ch
->overlap_dial_task
=
3964 misdn_tasks_add_variable(ch
->overlap_dial
, misdn_overlap_dial_task
, ch
);
3969 if (ast_exists_extension(ch
->ast
, ch
->context
, bc
->dad
, 1, bc
->oad
)) {
3971 ch
->state
= MISDN_DIALING
;
3972 start_pbx(ch
, bc
, ch
->ast
);
3975 /* sending INFOS as DTMF-Frames :) */
3976 struct ast_frame fr
;
3979 memset(&fr
, 0, sizeof(fr
));
3980 fr
.frametype
= AST_FRAME_DTMF
;
3981 fr
.subclass
= bc
->info_dad
[0] ;
3988 fr
.delivery
= ast_tv(0,0);
3990 misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN
, &digits
, sizeof(int));
3991 if (ch
->state
!= MISDN_CONNECTED
) {
3993 strncat(bc
->dad
, bc
->info_dad
, sizeof(bc
->dad
) - strlen(bc
->dad
) - 1);
3994 ast_copy_string(ch
->ast
->exten
, bc
->dad
, sizeof(ch
->ast
->exten
));
3995 ast_cdr_update(ch
->ast
);
3998 ast_queue_frame(ch
->ast
, &fr
);
4005 struct chan_list
*ch
= find_chan_by_bc(cl_te
, bc
);
4006 struct ast_channel
*chan
;
4013 switch (ch
->state
) {
4018 chan_misdn_log(1, bc
->port
, " --> Ignoring Call we have already one\n");
4019 return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE
; /* Ignore MSNs which are not in our List */
4023 msn_valid
= misdn_cfg_is_msn_valid(bc
->port
, bc
->dad
);
4024 if (!bc
->nt
&& ! msn_valid
) {
4025 chan_misdn_log(1, bc
->port
, " --> Ignoring Call, its not in our MSN List\n");
4026 return RESPONSE_IGNORE_SETUP
; /* Ignore MSNs which are not in our List */
4031 chan_misdn_log(0, bc
->port
, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
4032 misdn_cfg_get(bc
->port
, MISDN_CFG_REJECT_CAUSE
, &cause
, sizeof(cause
));
4033 bc
->out_cause
= cause
? cause
: AST_CAUSE_NORMAL_CLEARING
;
4034 return RESPONSE_RELEASE_SETUP
;
4039 ch
= init_chan_list(ORG_MISDN
);
4042 chan_misdn_log(-1, bc
->port
, "cb_events: malloc for chan_list failed!\n");
4047 ch
->l3id
= bc
->l3_id
;
4048 ch
->addr
= bc
->addr
;
4049 ch
->originator
= ORG_MISDN
;
4051 chan
= misdn_new(ch
, AST_STATE_RESERVED
, bc
->dad
, bc
->oad
, AST_FORMAT_ALAW
, bc
->port
, bc
->channel
);
4054 misdn_lib_send_event(bc
,EVENT_RELEASE_COMPLETE
);
4055 ast_log(LOG_ERROR
, "cb_events: misdn_new failed !\n");
4061 if ((exceed
= add_in_calls(bc
->port
))) {
4063 snprintf(tmp
, sizeof(tmp
), "%d", exceed
);
4064 pbx_builtin_setvar_helper(chan
, "MAX_OVERFLOW", tmp
);
4067 read_config(ch
, ORG_MISDN
);
4069 export_ch(chan
, bc
, ch
);
4072 ast_setstate(ch
->ast
, AST_STATE_RINGING
);
4076 pres
= AST_PRES_RESTRICTED
;
4077 chan_misdn_log(2, bc
->port
, " --> PRES: Restricted (1)\n");
4080 pres
= AST_PRES_UNAVAILABLE
;
4081 chan_misdn_log(2, bc
->port
, " --> PRES: Unavailable (2)\n");
4084 pres
= AST_PRES_ALLOWED
;
4085 chan_misdn_log(2, bc
->port
, " --> PRES: Allowed (%d)\n", bc
->pres
);
4089 switch (bc
->screen
) {
4092 screen
= AST_PRES_USER_NUMBER_UNSCREENED
;
4093 chan_misdn_log(2, bc
->port
, " --> SCREEN: Unscreened (%d)\n", bc
->screen
);
4096 screen
= AST_PRES_USER_NUMBER_PASSED_SCREEN
;
4097 chan_misdn_log(2, bc
->port
, " --> SCREEN: Passed screen (1)\n");
4100 screen
= AST_PRES_USER_NUMBER_FAILED_SCREEN
;
4101 chan_misdn_log(2, bc
->port
, " --> SCREEN: failed screen (2)\n");
4104 screen
= AST_PRES_NETWORK_NUMBER
;
4105 chan_misdn_log(2, bc
->port
, " --> SCREEN: Network Number (3)\n");
4109 chan
->cid
.cid_pres
= pres
| screen
;
4111 pbx_builtin_setvar_helper(chan
, "TRANSFERCAPABILITY", ast_transfercapability2str(bc
->capability
));
4112 chan
->transfercapability
= bc
->capability
;
4114 switch (bc
->capability
) {
4115 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED
:
4116 pbx_builtin_setvar_helper(chan
, "CALLTYPE", "DIGITAL");
4119 pbx_builtin_setvar_helper(chan
, "CALLTYPE", "SPEECH");
4122 /** queue new chan **/
4123 cl_queue_chan(&cl_te
, ch
);
4125 if (!strstr(ch
->allowed_bearers
, "all")) {
4128 for (i
= 0; i
< ARRAY_LEN(allowed_bearers_array
); ++i
) {
4129 if (allowed_bearers_array
[i
].cap
== bc
->capability
) {
4130 if (strstr(ch
->allowed_bearers
, allowed_bearers_array
[i
].name
)) {
4131 /* The bearer capability is allowed */
4132 if (allowed_bearers_array
[i
].deprecated
) {
4133 chan_misdn_log(0, bc
->port
, "%s in allowed_bearers list is deprecated\n",
4134 allowed_bearers_array
[i
].name
);
4140 if (i
== ARRAY_LEN(allowed_bearers_array
)) {
4141 /* We did not find the bearer capability */
4142 chan_misdn_log(0, bc
->port
, "Bearer capability not allowed: %s(%d)\n",
4143 bearer2str(bc
->capability
), bc
->capability
);
4144 bc
->out_cause
= AST_CAUSE_INCOMPATIBLE_DESTINATION
;
4146 ch
->state
= MISDN_EXTCANTMATCH
;
4147 misdn_lib_send_event(bc
, EVENT_RELEASE_COMPLETE
);
4152 /* Check for Pickup Request first */
4153 if (!strcmp(chan
->exten
, ast_pickup_ext())) {
4154 if (!ch
->noautorespond_on_setup
) {
4155 int ret
;/** Sending SETUP_ACK**/
4156 ret
= misdn_lib_send_event(bc
, EVENT_SETUP_ACKNOWLEDGE
);
4158 ch
->state
= MISDN_INCOMING_SETUP
;
4160 if (ast_pickup_call(chan
)) {
4163 ch
->state
= MISDN_CALLING_ACKNOWLEDGE
;
4164 ast_setstate(chan
, AST_STATE_DOWN
);
4172 added support for s extension hope it will help those poor cretains
4173 which haven't overlap dial.
4175 misdn_cfg_get(bc
->port
, MISDN_CFG_ALWAYS_IMMEDIATE
, &ai
, sizeof(ai
));
4177 do_immediate_setup(bc
, ch
, chan
);
4181 /* check if we should jump into s when we have no dad */
4182 misdn_cfg_get(bc
->port
, MISDN_CFG_IMMEDIATE
, &im
, sizeof(im
));
4183 if (im
&& ast_strlen_zero(bc
->dad
)) {
4184 do_immediate_setup(bc
, ch
, chan
);
4188 chan_misdn_log(5, bc
->port
, "CONTEXT:%s\n", ch
->context
);
4189 if(!ast_canmatch_extension(ch
->ast
, ch
->context
, bc
->dad
, 1, bc
->oad
)) {
4190 if (ast_exists_extension(ch
->ast
, ch
->context
, "i", 1, bc
->oad
)) {
4191 ast_log(LOG_WARNING
, "Extension can never match, So jumping to 'i' extension. port(%d)\n", bc
->port
);
4192 strcpy(ch
->ast
->exten
, "i");
4193 misdn_lib_send_event(bc
, EVENT_SETUP_ACKNOWLEDGE
);
4194 ch
->state
= MISDN_DIALING
;
4195 start_pbx(ch
, bc
, chan
);
4199 ast_log(LOG_WARNING
, "Extension can never match, so disconnecting on port(%d).\n"
4200 "\tMaybe you want to add an 'i' extension to catch this case.\n",
4203 hanguptone_indicate(ch
);
4205 ch
->state
= MISDN_EXTCANTMATCH
;
4206 bc
->out_cause
= AST_CAUSE_UNALLOCATED
;
4209 misdn_lib_send_event(bc
, EVENT_RELEASE_COMPLETE
);
4211 misdn_lib_send_event(bc
, EVENT_RELEASE
);
4216 /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely
4217 * jump into the dialplan, when the dialed extension does not exist, the 's' extension
4218 * will be used by Asterisk automatically. */
4219 if (bc
->sending_complete
|| (!bc
->nt
&& !misdn_lib_is_ptp(bc
->port
))) {
4220 if (!ch
->noautorespond_on_setup
) {
4221 ch
->state
=MISDN_DIALING
;
4222 misdn_lib_send_event(bc
, EVENT_PROCEEDING
);
4224 ch
->state
= MISDN_INCOMING_SETUP
;
4226 start_pbx(ch
, bc
, chan
);
4232 * When we are NT and overlapdial is set and if
4233 * the number is empty, we wait for the ISDN timeout
4234 * instead of our own timer.
4236 if (ch
->overlap_dial
&& bc
->nt
&& !bc
->dad
[0] ) {
4237 wait_for_digits(ch
, bc
, chan
);
4242 * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more
4243 * Infos with a Interdigit Timeout.
4245 if (ch
->overlap_dial
) {
4246 ast_mutex_lock(&ch
->overlap_tv_lock
);
4247 ch
->overlap_tv
= ast_tvnow();
4248 ast_mutex_unlock(&ch
->overlap_tv_lock
);
4250 wait_for_digits(ch
, bc
, chan
);
4251 if (ch
->overlap_dial_task
== -1)
4252 ch
->overlap_dial_task
=
4253 misdn_tasks_add_variable(ch
->overlap_dial
, misdn_overlap_dial_task
, ch
);
4258 /* If the extension does not exist and we're not TE_PTMP we wait for more digits
4259 * without interdigit timeout.
4261 if (!ast_exists_extension(ch
->ast
, ch
->context
, bc
->dad
, 1, bc
->oad
)) {
4262 wait_for_digits(ch
, bc
, chan
);
4267 * If the extension exists let's just jump into it.
4269 if (ast_exists_extension(ch
->ast
, ch
->context
, bc
->dad
, 1, bc
->oad
)) {
4270 if (bc
->need_more_infos
)
4271 misdn_lib_send_event(bc
, EVENT_SETUP_ACKNOWLEDGE
);
4273 misdn_lib_send_event(bc
, EVENT_PROCEEDING
);
4275 ch
->state
= MISDN_DIALING
;
4276 start_pbx(ch
, bc
, chan
);
4282 case EVENT_SETUP_ACKNOWLEDGE
:
4284 ch
->state
= MISDN_CALLING_ACKNOWLEDGE
;
4287 update_name(ch
->ast
,bc
->port
,bc
->channel
);
4289 if (!ast_strlen_zero(bc
->infos_pending
)) {
4290 /* TX Pending Infos */
4291 strncat(bc
->dad
, bc
->infos_pending
, sizeof(bc
->dad
) - strlen(bc
->dad
) - 1);
4295 ast_copy_string(ch
->ast
->exten
, bc
->dad
, sizeof(ch
->ast
->exten
));
4296 ast_copy_string(bc
->info_dad
, bc
->infos_pending
, sizeof(bc
->info_dad
));
4297 ast_copy_string(bc
->infos_pending
, "", sizeof(bc
->infos_pending
));
4299 misdn_lib_send_event(bc
, EVENT_INFORMATION
);
4303 case EVENT_PROCEEDING
:
4306 update_name(ch
->ast
, bc
->port
, bc
->channel
);
4308 if (misdn_cap_is_speech(bc
->capability
) &&
4309 misdn_inband_avail(bc
) ) {
4313 ch
->state
= MISDN_PROCEEDING
;
4318 ast_queue_control(ch
->ast
, AST_CONTROL_PROCEEDING
);
4321 case EVENT_PROGRESS
:
4323 update_name(ch
->ast
, bc
->port
, bc
->channel
);
4326 if ( misdn_cap_is_speech(bc
->capability
) &&
4327 misdn_inband_avail(bc
)
4332 ch
->state
= MISDN_PROGRESS
;
4336 ast_queue_control(ch
->ast
, AST_CONTROL_PROGRESS
);
4341 case EVENT_ALERTING
:
4344 update_name(ch
->ast
, bc
->port
, bc
->channel
);
4346 ch
->state
= MISDN_ALERTING
;
4351 ast_queue_control(ch
->ast
, AST_CONTROL_RINGING
);
4352 ast_setstate(ch
->ast
, AST_STATE_RINGING
);
4354 cb_log(7, bc
->port
, " --> Set State Ringing\n");
4356 if (misdn_cap_is_speech(bc
->capability
) && misdn_inband_avail(bc
)) {
4357 cb_log(1, bc
->port
, "Starting Tones, we have inband Data\n");
4360 cb_log(3, bc
->port
, " --> We have no inband Data, the other end must create ringing\n");
4361 if (ch
->far_alerting
) {
4362 cb_log(1, bc
->port
, " --> The other end can not do ringing eh ?.. we must do all ourself..");
4364 /*tone_indicate(ch, TONE_FAR_ALERTING);*/
4371 struct ast_channel
*bridged
;
4373 /*we answer when we've got our very new L3 ID from the NT stack */
4374 misdn_lib_send_event(bc
, EVENT_CONNECT_ACKNOWLEDGE
);
4379 bridged
= ast_bridged_channel(ch
->ast
);
4382 if (bridged
&& !strcasecmp(bridged
->tech
->type
, "mISDN")) {
4383 struct chan_list
*bridged_ch
= MISDN_ASTERISK_TECH_PVT(bridged
);
4385 chan_misdn_log(1, bc
->port
, " --> copying cpndialplan:%d and cad:%s to the A-Channel\n", bc
->cpnnumplan
, bc
->cad
);
4387 bridged_ch
->bc
->cpnnumplan
= bc
->cpnnumplan
;
4388 ast_copy_string(bridged_ch
->bc
->cad
, bc
->cad
, sizeof(bridged_ch
->bc
->cad
));
4397 ch
->state
= MISDN_CONNECTED
;
4399 ast_queue_control(ch
->ast
, AST_CONTROL_ANSWER
);
4401 case EVENT_CONNECT_ACKNOWLEDGE
:
4403 ch
->l3id
= bc
->l3_id
;
4404 ch
->addr
= bc
->addr
;
4408 ch
->state
= MISDN_CONNECTED
;
4411 case EVENT_DISCONNECT
:
4412 /*we might not have an ch->ast ptr here anymore*/
4414 struct chan_list
*holded_ch
= find_holded(cl_te
, bc
);
4416 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
);
4417 if (ch
->originator
== ORG_AST
&& !bc
->nt
&& misdn_inband_avail(bc
) && ch
->state
!= MISDN_CONNECTED
) {
4418 /* If there's inband information available (e.g. a
4419 recorded message saying what was wrong with the
4420 dialled number, or perhaps even giving an
4421 alternative number, then play it instead of
4422 immediately releasing the call */
4423 chan_misdn_log(1, bc
->port
, " --> Inband Info Avail, not sending RELEASE\n");
4425 ch
->state
= MISDN_DISCONNECTED
;
4429 ch
->ast
->hangupcause
= bc
->cause
;
4430 if (bc
->cause
== AST_CAUSE_USER_BUSY
)
4431 ast_queue_control(ch
->ast
, AST_CONTROL_BUSY
);
4437 /*Check for holded channel, to implement transfer*/
4438 if (holded_ch
&& holded_ch
!= ch
&& ch
->ast
&& ch
->state
== MISDN_CONNECTED
) {
4439 cb_log(1, bc
->port
, " --> found holded ch\n");
4440 misdn_transfer_bc(ch
, holded_ch
) ;
4443 bc
->need_disconnect
= 0;
4449 ch
= find_holded_l3(cl_te
, bc
->l3_id
,1);
4456 if (bc
->need_release
)
4457 misdn_lib_send_event(bc
, EVENT_RELEASE
);
4462 bc
->need_disconnect
= 0;
4463 bc
->need_release
= 0;
4469 case EVENT_RELEASE_COMPLETE
:
4471 bc
->need_disconnect
= 0;
4472 bc
->need_release
= 0;
4473 bc
->need_release_complete
= 0;
4479 ch
->state
= MISDN_CLEANING
;
4484 case EVENT_BCHAN_ERROR
:
4489 switch (ch
->state
) {
4491 bc
->cause
= AST_CAUSE_DESTINATION_OUT_OF_ORDER
;
4502 case EVENT_TONE_GENERATE
:
4504 int tone_len
= bc
->tone_cnt
;
4505 struct ast_channel
*ast
= ch
->ast
;
4508 int (*generate
)(struct ast_channel
*chan
, void *tmp
, int datalen
, int samples
);
4510 chan_misdn_log(9, bc
->port
, "TONE_GEN: len:%d\n", tone_len
);
4515 if (!ast
->generator
)
4518 tmp
= ast
->generatordata
;
4519 ast
->generatordata
= NULL
;
4520 generate
= ast
->generator
->generate
;
4522 if (tone_len
< 0 || tone_len
> 512 ) {
4523 ast_log(LOG_NOTICE
, "TONE_GEN: len was %d, set to 128\n", tone_len
);
4527 res
= generate(ast
, tmp
, tone_len
, tone_len
);
4528 ast
->generatordata
= tmp
;
4531 ast_log(LOG_WARNING
, "Auto-deactivating generator\n");
4532 ast_deactivate_generator(ast
);
4539 case EVENT_BCHAN_DATA
:
4541 if (!misdn_cap_is_speech(ch
->bc
->capability
)) {
4542 struct ast_frame frame
;
4543 /*In Data Modes we queue frames*/
4544 frame
.frametype
= AST_FRAME_VOICE
; /*we have no data frames yet*/
4545 frame
.subclass
= AST_FORMAT_ALAW
;
4546 frame
.datalen
= bc
->bframe_len
;
4547 frame
.samples
= bc
->bframe_len
;
4550 frame
.delivery
= ast_tv(0,0);
4552 frame
.data
= bc
->bframe
;
4555 ast_queue_frame(ch
->ast
, &frame
);
4558 struct timeval tv
= { 0, 0 };
4562 FD_SET(ch
->pipe
[1], &wrfs
);
4564 t
= select(FD_SETSIZE
, NULL
, &wrfs
, NULL
, &tv
);
4567 chan_misdn_log(9, bc
->port
, "Select Timed out\n");
4572 chan_misdn_log(-1, bc
->port
, "Select Error (err=%s)\n", strerror(errno
));
4576 if (FD_ISSET(ch
->pipe
[1], &wrfs
)) {
4577 chan_misdn_log(9, bc
->port
, "writing %d bytes to asterisk\n", bc
->bframe_len
);
4578 if (write(ch
->pipe
[1], bc
->bframe
, bc
->bframe_len
) <= 0) {
4579 chan_misdn_log(0, bc
->port
, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno
));
4586 chan_misdn_log(1, bc
->port
, "Write Pipe full!\n");
4594 chan_misdn_log(1, bc
->port
, "--> state: %s\n", misdn_get_ch_state(ch
));
4596 switch (ch
->state
) {
4598 case MISDN_PROGRESS
:
4599 if (bc
->nt
&& !ch
->nttimeout
)
4603 case MISDN_ALERTING
:
4604 case MISDN_PROCEEDING
:
4605 case MISDN_CALLING_ACKNOWLEDGE
:
4607 bc
->progress_indicator
= INFO_PI_INBAND_AVAILABLE
;
4608 hanguptone_indicate(ch
);
4611 bc
->out_cause
= AST_CAUSE_UNALLOCATED
;
4612 misdn_lib_send_event(bc
, EVENT_DISCONNECT
);
4615 case MISDN_WAITING4DIGS
:
4617 bc
->progress_indicator
= INFO_PI_INBAND_AVAILABLE
;
4618 bc
->out_cause
= AST_CAUSE_UNALLOCATED
;
4619 hanguptone_indicate(ch
);
4620 misdn_lib_send_event(bc
, EVENT_DISCONNECT
);
4622 bc
->out_cause
= AST_CAUSE_NORMAL_CLEARING
;
4623 misdn_lib_send_event(bc
, EVENT_RELEASE
);
4628 case MISDN_CLEANING
:
4629 chan_misdn_log(1,bc
->port
," --> in state cleaning .. so ignoring, the stack should clean it for us\n");
4633 misdn_lib_send_event(bc
,EVENT_RELEASE_COMPLETE
);
4639 /****************************/
4640 /** Supplementary Services **/
4641 /****************************/
4642 case EVENT_RETRIEVE
:
4644 struct ast_channel
*hold_ast
;
4647 chan_misdn_log(4, bc
->port
, " --> no CH, searching in holded\n");
4648 ch
= find_holded_l3(cl_te
, bc
->l3_id
, 1);
4652 ast_log(LOG_WARNING
, "Found no Holded channel, cannot Retrieve\n");
4653 misdn_lib_send_event(bc
, EVENT_RETRIEVE_REJECT
);
4657 /*remember the channel again*/
4659 ch
->state
= MISDN_CONNECTED
;
4661 ch
->hold_info
.port
= 0;
4662 ch
->hold_info
.channel
= 0;
4664 hold_ast
= ast_bridged_channel(ch
->ast
);
4667 ast_moh_stop(hold_ast
);
4670 if (misdn_lib_send_event(bc
, EVENT_RETRIEVE_ACKNOWLEDGE
) < 0) {
4671 chan_misdn_log(4, bc
->port
, " --> RETRIEVE_ACK failed\n");
4672 misdn_lib_send_event(bc
, EVENT_RETRIEVE_REJECT
);
4680 struct ast_channel
*bridged
;
4682 misdn_cfg_get(bc
->port
, MISDN_CFG_HOLD_ALLOWED
, &hold_allowed
, sizeof(int));
4684 if (!hold_allowed
) {
4686 chan_misdn_log(-1, bc
->port
, "Hold not allowed this port.\n");
4687 misdn_lib_send_event(bc
, EVENT_HOLD_REJECT
);
4691 bridged
= ast_bridged_channel(ch
->ast
);
4693 chan_misdn_log(2, bc
->port
, "Bridge Partner is of type: %s\n", bridged
->tech
->type
);
4694 ch
->state
= MISDN_HOLDED
;
4695 ch
->l3id
= bc
->l3_id
;
4697 misdn_lib_send_event(bc
, EVENT_HOLD_ACKNOWLEDGE
);
4699 /* XXX This should queue an AST_CONTROL_HOLD frame on this channel
4700 * instead of starting moh on the bridged channel directly */
4701 ast_moh_start(bridged
, NULL
, NULL
);
4703 /*forget the channel now*/
4705 ch
->hold_info
.port
= bc
->port
;
4706 ch
->hold_info
.channel
= bc
->channel
;
4709 misdn_lib_send_event(bc
, EVENT_HOLD_REJECT
);
4710 chan_misdn_log(0, bc
->port
, "We aren't bridged to anybody\n");
4715 case EVENT_FACILITY
:
4717 /* This may come from a call we don't know nothing about, so we ignore it. */
4718 chan_misdn_log(-1, bc
->port
, "Got EVENT_FACILITY but we don't have a ch!\n");
4722 print_facility(&(bc
->fac_in
), bc
);
4724 switch (bc
->fac_in
.Function
) {
4727 struct ast_channel
*bridged
= ast_bridged_channel(ch
->ast
);
4728 struct chan_list
*ch_br
;
4729 if (bridged
&& MISDN_ASTERISK_TECH_PVT(bridged
)) {
4730 ch_br
= MISDN_ASTERISK_TECH_PVT(bridged
);
4731 /*ch->state = MISDN_FACILITY_DEFLECTED;*/
4733 if (ast_exists_extension(bridged
, ch
->context
, (char *)bc
->fac_in
.u
.CDeflection
.DeflectedToNumber
, 1, bc
->oad
)) {
4734 ch_br
->state
= MISDN_DIALING
;
4735 if (pbx_start_chan(ch_br
) < 0) {
4736 chan_misdn_log(-1, ch_br
->bc
->port
, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
4741 misdn_lib_send_event(bc
, EVENT_DISCONNECT
);
4744 case Fac_AOCDCurrency
:
4746 bc
->AOCDtype
= Fac_AOCDCurrency
;
4747 memcpy(&(bc
->AOCD
.currency
), &(bc
->fac_in
.u
.AOCDcur
), sizeof(struct FacAOCDCurrency
));
4748 export_aoc_vars(ch
->originator
, ch
->ast
, bc
);
4751 case Fac_AOCDChargingUnit
:
4753 bc
->AOCDtype
= Fac_AOCDChargingUnit
;
4754 memcpy(&(bc
->AOCD
.chargingUnit
), &(bc
->fac_in
.u
.AOCDchu
), sizeof(struct FacAOCDChargingUnit
));
4755 export_aoc_vars(ch
->originator
, ch
->ast
, bc
);
4759 chan_misdn_log(0, bc
->port
," --> not yet handled: facility type:%d\n", bc
->fac_in
.Function
);
4773 chan_misdn_log(1, 0, "Got Unknown Event\n");
4780 /** TE STUFF END **/
4782 /******************************************
4784 * Asterisk Channel Endpoint END
4787 *******************************************/
4791 static int unload_module(void)
4793 /* First, take us out of the channel loop */
4794 ast_log(LOG_VERBOSE
, "-- Unregistering mISDN Channel Driver --\n");
4796 misdn_tasks_destroy();
4798 if (!g_config_initialized
)
4801 ast_cli_unregister_multiple(chan_misdn_clis
, sizeof(chan_misdn_clis
) / sizeof(struct ast_cli_entry
));
4803 /* ast_unregister_application("misdn_crypt"); */
4804 ast_unregister_application("misdn_set_opt");
4805 ast_unregister_application("misdn_facility");
4806 ast_unregister_application("misdn_check_l2l1");
4808 ast_channel_unregister(&misdn_tech
);
4811 misdn_cfg_destroy();
4812 misdn_lib_destroy();
4816 if (misdn_debug_only
)
4817 free(misdn_debug_only
);
4823 static int load_module(void)
4826 int ntflags
= 0, ntkc
= 0;
4827 char ports
[256] = "";
4828 char tempbuf
[BUFFERSIZE
+ 1];
4829 char ntfile
[BUFFERSIZE
+ 1];
4830 struct misdn_lib_iface iface
= {
4831 .cb_event
= cb_events
,
4832 .cb_log
= chan_misdn_log
,
4833 .cb_jb_empty
= chan_misdn_jb_empty
,
4836 max_ports
= misdn_lib_maxports_get();
4838 if (max_ports
<= 0) {
4839 ast_log(LOG_ERROR
, "Unable to initialize mISDN\n");
4840 return AST_MODULE_LOAD_DECLINE
;
4843 if (misdn_cfg_init(max_ports
)) {
4844 ast_log(LOG_ERROR
, "Unable to initialize misdn_config.\n");
4845 return AST_MODULE_LOAD_DECLINE
;
4847 g_config_initialized
= 1;
4849 misdn_debug
= (int *) malloc(sizeof(int) * (max_ports
+ 1));
4851 ast_log(LOG_ERROR
, "Out of memory for misdn_debug\n");
4852 return AST_MODULE_LOAD_DECLINE
;
4854 misdn_ports
= (int *) malloc(sizeof(int) * (max_ports
+ 1));
4856 ast_log(LOG_ERROR
, "Out of memory for misdn_ports\n");
4857 return AST_MODULE_LOAD_DECLINE
;
4859 misdn_cfg_get(0, MISDN_GEN_DEBUG
, &misdn_debug
[0], sizeof(int));
4860 for (i
= 1; i
<= max_ports
; i
++) {
4861 misdn_debug
[i
] = misdn_debug
[0];
4865 misdn_debug_only
= (int *) calloc(max_ports
+ 1, sizeof(int));
4867 misdn_cfg_get(0, MISDN_GEN_TRACEFILE
, tempbuf
, BUFFERSIZE
);
4868 if (!ast_strlen_zero(tempbuf
))
4871 misdn_in_calls
= (int *) malloc(sizeof(int) * (max_ports
+ 1));
4872 misdn_out_calls
= (int *) malloc(sizeof(int) * (max_ports
+ 1));
4874 for (i
= 1; i
<= max_ports
; i
++) {
4875 misdn_in_calls
[i
] = 0;
4876 misdn_out_calls
[i
] = 0;
4879 ast_mutex_init(&cl_te_lock
);
4880 ast_mutex_init(&release_lock
);
4882 misdn_cfg_update_ptp();
4883 misdn_cfg_get_ports_string(ports
);
4885 if (!ast_strlen_zero(ports
))
4886 chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports
);
4887 if (misdn_lib_init(ports
, &iface
, NULL
))
4888 chan_misdn_log(0, 0, "No te ports initialized\n");
4890 misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS
, &ntflags
, sizeof(int));
4891 misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE
, &ntfile
, BUFFERSIZE
);
4892 misdn_lib_nt_debug_init(ntflags
, ntfile
);
4894 misdn_cfg_get( 0, MISDN_GEN_NTKEEPCALLS
, &ntkc
, sizeof(int));
4895 misdn_lib_nt_keepcalls(ntkc
);
4897 if (ast_channel_register(&misdn_tech
)) {
4898 ast_log(LOG_ERROR
, "Unable to register channel class %s\n", misdn_type
);
4903 ast_cli_register_multiple(chan_misdn_clis
, sizeof(chan_misdn_clis
) / sizeof(struct ast_cli_entry
));
4905 ast_register_application("misdn_set_opt", misdn_set_opt_exec
, "misdn_set_opt",
4906 "misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
4907 "Sets mISDN opts. and optargs\n"
4909 "The available options are:\n"
4910 " a - Have Asterisk detect DTMF tones on called channel\n"
4911 " c - Make crypted outgoing call, optarg is keyindex\n"
4912 " d - Send display text to called phone, text is the optarg\n"
4913 " e - Perform echo cancelation on this channel,\n"
4914 " takes taps as optarg (32,64,128,256)\n"
4915 " e! - Disable echo cancelation on this channel\n"
4916 " f - Enable fax detection\n"
4917 " h - Make digital outgoing call\n"
4918 " h1 - Make HDLC mode digital outgoing call\n"
4919 " i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
4920 " they will be transported inband.\n"
4921 " jb - Set jitter buffer length, optarg is length\n"
4922 " jt - Set jitter buffer upper threshold, optarg is threshold\n"
4923 " jn - Disable jitter buffer\n"
4924 " n - disable DSP on channel, disables: Echocancel, DTMF Detection and Volume Control.\n"
4925 " p - Caller ID presentation,\n"
4926 " optarg is either 'allowed' or 'restricted'\n"
4927 " s - Send Non-inband DTMF as inband\n"
4928 " vr - Rx gain control, optarg is gain\n"
4929 " vt - Tx gain control, optarg is gain\n"
4933 ast_register_application("misdn_facility", misdn_facility_exec
, "misdn_facility",
4934 "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
4935 "Sends the Facility Message FACILITY_TYPE with \n"
4936 "the given Arguments to the current ISDN Channel\n"
4937 "Supported Facilities are:\n"
4939 "type=calldeflect args=Nr where to deflect\n"
4943 ast_register_application("misdn_check_l2l1", misdn_check_l2l1
, "misdn_check_l2l1",
4944 "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
4945 "Checks if the L2 and L1 are up on either the given <port> or\n"
4946 "on the ports in the group with <groupname>\n"
4947 "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
4948 "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
4950 "This application, ensures the L1/L2 state of the Ports in a group\n"
4951 "it is intended to make the pmp_l1_check option redundant and to\n"
4952 "fix a buggy switch config from your provider\n"
4954 "a sample dialplan would look like:\n\n"
4955 "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
4956 "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
4961 misdn_cfg_get(0, MISDN_GEN_TRACEFILE
, global_tracefile
, BUFFERSIZE
);
4963 /* start the l1 watchers */
4965 for (port
= misdn_cfg_get_next_port(0); port
>= 0; port
= misdn_cfg_get_next_port(port
)) {
4967 misdn_cfg_get(port
, MISDN_CFG_L1_TIMEOUT
, &l1timeout
, sizeof(l1timeout
));
4969 chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port
, l1timeout
);
4970 misdn_tasks_add(l1timeout
* 1000, misdn_l1_task
, &misdn_ports
[port
]);
4974 chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
4981 static int reload(void)
4988 /*** SOME APPS ;)***/
4990 static int misdn_facility_exec(struct ast_channel
*chan
, void *data
)
4992 struct chan_list
*ch
= MISDN_ASTERISK_TECH_PVT(chan
);
4995 chan_misdn_log(0, 0, "TYPE: %s\n", chan
->tech
->type
);
4997 if (strcasecmp(chan
->tech
->type
, "mISDN")) {
4998 ast_log(LOG_WARNING
, "misdn_facility makes only sense with chan_misdn channels!\n");
5002 if (ast_strlen_zero((char *)data
)) {
5003 ast_log(LOG_WARNING
, "misdn_facility Requires arguments\n");
5007 tok
= strtok_r((char*) data
, "|", &tokb
) ;
5010 ast_log(LOG_WARNING
, "misdn_facility Requires arguments\n");
5014 if (!strcasecmp(tok
, "calldeflect")) {
5015 tok
= strtok_r(NULL
, "|", &tokb
) ;
5018 ast_log(LOG_WARNING
, "Facility: Call Defl Requires arguments\n");
5021 if (strlen(tok
) >= sizeof(ch
->bc
->fac_out
.u
.CDeflection
.DeflectedToNumber
)) {
5022 ast_log(LOG_WARNING
, "Facility: Number argument too long (up to 15 digits are allowed). Ignoring.\n");
5025 ch
->bc
->fac_out
.Function
= Fac_CD
;
5026 ast_copy_string((char *)ch
->bc
->fac_out
.u
.CDeflection
.DeflectedToNumber
, tok
, sizeof(ch
->bc
->fac_out
.u
.CDeflection
.DeflectedToNumber
));
5027 misdn_lib_send_event(ch
->bc
, EVENT_FACILITY
);
5029 chan_misdn_log(1, ch
->bc
->port
, "Unknown Facility: %s\n", tok
);
5035 static int misdn_check_l2l1(struct ast_channel
*chan
, void *data
)
5037 char group
[BUFFERSIZE
+ 1];
5044 AST_DECLARE_APP_ARGS(args
,
5045 AST_APP_ARG(grouppar
);
5046 AST_APP_ARG(timeout
);
5049 if (ast_strlen_zero((char *)data
)) {
5050 ast_log(LOG_WARNING
, "misdn_check_l2l1 Requires arguments\n");
5054 AST_STANDARD_APP_ARGS(args
, data
);
5056 if (args
.argc
!= 2) {
5057 ast_log(LOG_WARNING
, "Wrong argument count\n");
5061 /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
5062 timeout
= atoi(args
.timeout
);
5063 port_str
= args
.grouppar
;
5065 if (port_str
[0] == 'g' && port_str
[1] == ':' ) {
5066 /* We make a group call lets checkout which ports are in my group */
5068 ast_copy_string(group
, port_str
, sizeof(group
));
5069 chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group
);
5071 for ( port
= misdn_cfg_get_next_port(port
);
5073 port
= misdn_cfg_get_next_port(port
)) {
5074 char cfg_group
[BUFFERSIZE
+ 1];
5076 chan_misdn_log(2, 0, "trying port %d\n", port
);
5078 misdn_cfg_get(port
, MISDN_CFG_GROUPNAME
, cfg_group
, BUFFERSIZE
);
5080 if (!strcasecmp(cfg_group
, group
)) {
5081 port_up
= misdn_lib_port_up(port
, 1);
5084 chan_misdn_log(2, 0, " --> port '%d'\n", port
);
5085 misdn_lib_get_port_up(port
);
5092 port
= atoi(port_str
);
5093 chan_misdn_log(2, 0, "Checking Port: %d\n",port
);
5094 port_up
= misdn_lib_port_up(port
, 1);
5096 misdn_lib_get_port_up(port
);
5102 chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout
);
5109 static int misdn_set_opt_exec(struct ast_channel
*chan
, void *data
)
5111 struct chan_list
*ch
= MISDN_ASTERISK_TECH_PVT(chan
);
5116 int change_jitter
= 0;
5118 if (strcasecmp(chan
->tech
->type
, "mISDN")) {
5119 ast_log(LOG_WARNING
, "misdn_set_opt makes only sense with chan_misdn channels!\n");
5123 if (ast_strlen_zero((char *)data
)) {
5124 ast_log(LOG_WARNING
, "misdn_set_opt Requires arguments\n");
5128 for (tok
= strtok_r((char*) data
, ":", &tokb
);
5130 tok
= strtok_r(NULL
, ":", &tokb
) ) {
5133 if (tok
[0] == '!' ) {
5141 ast_copy_string(ch
->bc
->display
, ++tok
, sizeof(ch
->bc
->display
));
5142 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: Display:%s\n", ch
->bc
->display
);
5146 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: No DSP\n");
5151 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: jitter\n");
5157 ch
->jb_len
= atoi(++tok
);
5158 chan_misdn_log(1, ch
->bc
->port
, " --> buffer_len:%d\n", ch
->jb_len
);
5161 ch
->jb_upper_threshold
= atoi(++tok
);
5162 chan_misdn_log(1, ch
->bc
->port
, " --> upper_threshold:%d\n", ch
->jb_upper_threshold
);
5165 ch
->bc
->nojitter
= 1;
5166 chan_misdn_log(1, ch
->bc
->port
, " --> nojitter\n");
5170 ch
->jb_upper_threshold
= 0;
5171 chan_misdn_log(1, ch
->bc
->port
, " --> buffer_len:%d (default)\n", ch
->jb_len
);
5172 chan_misdn_log(1, ch
->bc
->port
, " --> upper_threshold:%d (default)\n", ch
->jb_upper_threshold
);
5180 rxgain
= atoi(++tok
);
5185 ch
->bc
->rxgain
= rxgain
;
5186 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: Volume:%d\n", rxgain
);
5189 txgain
= atoi(++tok
);
5194 ch
->bc
->txgain
= txgain
;
5195 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: Volume:%d\n", txgain
);
5201 keyidx
= atoi(++tok
);
5204 char *key
= NULL
, *tmp
= keys
;
5206 misdn_cfg_get(0, MISDN_GEN_CRYPT_KEYS
, keys
, sizeof(keys
));
5208 for (i
= 0; i
< keyidx
; i
++) {
5209 key
= strsep(&tmp
, ",");
5213 ast_copy_string(ch
->bc
->crypt_key
, key
, sizeof(ch
->bc
->crypt_key
));
5216 chan_misdn_log(0, ch
->bc
->port
, "SETOPT: crypt with key:%s\n", ch
->bc
->crypt_key
);
5220 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: EchoCancel\n");
5223 chan_misdn_log(1, ch
->bc
->port
, " --> disabled\n");
5225 *ch
->bc
->pipeline
= 0;
5227 ch
->bc
->ec_enable
= 0;
5231 update_pipeline_config(ch
->bc
);
5233 ch
->bc
->ec_enable
= 1;
5234 ch
->bc
->orig
= ch
->originator
;
5237 ch
->bc
->ec_deftaps
= atoi(tok
);
5244 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: Digital\n");
5246 if (strlen(tok
) > 1 && tok
[1] == '1') {
5247 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: HDLC \n");
5248 if (!ch
->bc
->hdlc
) {
5252 ch
->bc
->capability
= INFO_CAPABILITY_DIGITAL_UNRESTRICTED
;
5256 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: Send DTMF\n");
5257 ch
->bc
->send_dtmf
= 1;
5261 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: Faxdetect\n");
5263 misdn_cfg_get(ch
->bc
->port
, MISDN_CFG_FAXDETECT_TIMEOUT
, &ch
->faxdetect_timeout
, sizeof(ch
->faxdetect_timeout
));
5267 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: AST_DSP (for DTMF)\n");
5272 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: callerpres: %s\n", &tok
[1]);
5273 /* CRICH: callingpres!!! */
5274 if (strstr(tok
,"allowed")) {
5276 } else if (strstr(tok
, "restricted")) {
5278 } else if (strstr(tok
, "not_screened")) {
5279 chan_misdn_log(0, ch
->bc
->port
, "SETOPT: callerpres: not_screened is deprecated\n");
5284 chan_misdn_log(1, ch
->bc
->port
, "Ignoring dtmf tones, just use them inband\n");
5293 config_jitterbuffer(ch
);
5295 if (ch
->faxdetect
|| ch
->ast_dsp
) {
5297 ch
->dsp
= ast_dsp_new();
5299 ast_dsp_set_features(ch
->dsp
, DSP_FEATURE_DTMF_DETECT
| DSP_FEATURE_FAX_DETECT
);
5301 ch
->trans
= ast_translator_build_path(AST_FORMAT_SLINEAR
, AST_FORMAT_ALAW
);
5305 chan_misdn_log(1, ch
->bc
->port
, "SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
5307 ch
->bc
->nojitter
= 1;
5314 int chan_misdn_jb_empty ( struct misdn_bchannel
*bc
, char *buf
, int len
)
5316 struct chan_list
*ch
= find_chan_by_bc(cl_te
, bc
);
5319 return misdn_jb_empty(ch
->jb
, buf
, len
);
5327 /*******************************************************/
5328 /***************** JITTERBUFFER ************************/
5329 /*******************************************************/
5332 /* allocates the jb-structure and initialize the elements*/
5333 struct misdn_jb
*misdn_jb_init(int size
, int upper_threshold
)
5336 struct misdn_jb
*jb
;
5338 jb
= malloc(sizeof(struct misdn_jb
));
5340 chan_misdn_log(-1, 0, "No free Mem for jb\n");
5344 jb
->upper_threshold
= upper_threshold
;
5348 jb
->state_empty
= 0;
5349 jb
->bytes_wrote
= 0;
5350 jb
->samples
= malloc(size
* sizeof(char));
5353 chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
5357 jb
->ok
= malloc(size
* sizeof(char));
5361 chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
5365 for (i
= 0; i
< size
; i
++)
5368 ast_mutex_init(&jb
->mutexjb
);
5373 /* frees the data and destroys the given jitterbuffer struct */
5374 void misdn_jb_destroy(struct misdn_jb
*jb
)
5376 ast_mutex_destroy(&jb
->mutexjb
);
5382 /* fills the jitterbuffer with len data returns < 0 if there was an
5383 error (buffer overflow). */
5384 int misdn_jb_fill(struct misdn_jb
*jb
, const char *data
, int len
)
5391 ast_mutex_lock(&jb
->mutexjb
);
5396 for (i
= 0; i
< len
; i
++) {
5397 jb
->samples
[wp
] = data
[i
];
5399 wp
= (wp
!= jb
->size
- 1) ? wp
+ 1 : 0;
5406 jb
->state_buffer
= wp
- rp
;
5408 jb
->state_buffer
= jb
->size
- rp
+ wp
;
5409 chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len
, jb
->state_buffer
, jb
);
5411 if (jb
->state_full
) {
5415 for (j
= 0; j
< jb
->upper_threshold
; j
++)
5416 rp
= (rp
!= 0) ? rp
- 1 : jb
->size
- 1;
5419 jb
->state_empty
= 1;
5421 ast_mutex_unlock(&jb
->mutexjb
);
5426 if (!jb
->state_empty
) {
5427 jb
->bytes_wrote
+= len
;
5428 if (jb
->bytes_wrote
>= jb
->upper_threshold
) {
5429 jb
->state_empty
= 1;
5430 jb
->bytes_wrote
= 0;
5435 ast_mutex_unlock(&jb
->mutexjb
);
5440 /* gets len bytes out of the jitterbuffer if available, else only the
5441 available data is returned and the return value indicates the number
5443 int misdn_jb_empty(struct misdn_jb
*jb
, char *data
, int len
)
5445 int i
, wp
, rp
, read
= 0;
5447 ast_mutex_lock(&jb
->mutexjb
);
5452 if (jb
->state_empty
) {
5453 for (i
= 0; i
< len
; i
++) {
5456 jb
->state_empty
= 0;
5458 ast_mutex_unlock(&jb
->mutexjb
);
5462 if (jb
->ok
[rp
] == 1) {
5463 data
[i
] = jb
->samples
[rp
];
5465 rp
= (rp
!= jb
->size
- 1) ? rp
+ 1 : 0;
5472 jb
->state_buffer
= wp
- rp
;
5474 jb
->state_buffer
= jb
->size
- rp
+ wp
;
5475 chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len
, jb
->state_buffer
, jb
);
5479 chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len
, jb
);
5481 ast_mutex_unlock(&jb
->mutexjb
);
5489 /*******************************************************/
5490 /*************** JITTERBUFFER END *********************/
5491 /*******************************************************/
5496 static void chan_misdn_log(int level
, int port
, char *tmpl
, ...)
5502 if (! ((0 <= port
) && (port
<= max_ports
))) {
5503 ast_log(LOG_WARNING
, "cb_log called with out-of-range port number! (%d)\n", port
);
5508 snprintf(port_buf
, sizeof(port_buf
), "P[%2d] ", port
);
5511 vsnprintf(buf
, sizeof(buf
), tmpl
, ap
);
5515 ast_log(LOG_WARNING
, "%s", buf
);
5517 else if (misdn_debug_only
[port
] ?
5518 (level
== 1 && misdn_debug
[port
]) || (level
== misdn_debug
[port
])
5519 : level
<= misdn_debug
[port
]) {
5521 ast_console_puts(port_buf
);
5522 ast_console_puts(buf
);
5525 if ((level
<= misdn_debug
[0]) && !ast_strlen_zero(global_tracefile
) ) {
5526 time_t tm
= time(NULL
);
5527 char *tmp
= ctime(&tm
), *p
;
5529 FILE *fp
= fopen(global_tracefile
, "a+");
5531 p
= strchr(tmp
, '\n');
5536 ast_console_puts("Error opening Tracefile: [ ");
5537 ast_console_puts(global_tracefile
);
5538 ast_console_puts(" ] ");
5540 ast_console_puts(strerror(errno
));
5541 ast_console_puts("\n");
5547 fputs(port_buf
, fp
);
5555 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_DEFAULT
, "Channel driver for mISDN Support (BRI/PRI)",
5556 .load
= load_module
,
5557 .unload
= unload_module
,