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"
79 #include "chan_misdn_config.h"
82 char global_tracefile[BUFFERSIZE+1];
84 static int g_config_initialized=0;
100 /*! \brief allocates the jb-structure and initialise the elements*/
101 struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
103 /*! \brief frees the data and destroys the given jitterbuffer struct */
104 void misdn_jb_destroy(struct misdn_jb *jb);
106 /*! \brief fills the jitterbuffer with len data returns < 0 if there was an
107 error (bufferoverun). */
108 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);
110 /*! \brief gets len bytes out of the jitterbuffer if available, else only the
111 available data is returned and the return value indicates the number
113 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len);
116 enum misdn_chan_state {
117 MISDN_NOTHING=0, /*!< at beginning */
118 MISDN_WAITING4DIGS, /*!< when waiting for infos */
119 MISDN_EXTCANTMATCH, /*!< when asterisk couldnt match our ext */
120 MISDN_INCOMING_SETUP, /*!< for incoming setups*/
121 MISDN_DIALING, /*!< when pbx_start */
122 MISDN_PROGRESS, /*!< we got a progress */
123 MISDN_PROCEEDING, /*!< we got a progress */
124 MISDN_CALLING, /*!< when misdn_call is called */
125 MISDN_CALLING_ACKNOWLEDGE, /*!< when we get SETUP_ACK */
126 MISDN_ALERTING, /*!< when Alerting */
127 MISDN_BUSY, /*!< when BUSY */
128 MISDN_CONNECTED, /*!< when connected */
129 MISDN_PRECONNECTED, /*!< when connected */
130 MISDN_DISCONNECTED, /*!< when connected */
131 MISDN_RELEASED, /*!< when connected */
132 MISDN_BRIDGED, /*!< when bridged */
133 MISDN_CLEANING, /*!< when hangup from * but we were connected before */
134 MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP cam from misdn */
135 MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of */
137 MISDN_HOLDED, /*!< if this chan is holded */
138 MISDN_HOLD_DISCONNECT, /*!< if this chan is holded */
152 char allowed_bearers[BUFFERSIZE+1];
154 enum misdn_chan_state state;
155 int need_queue_hangup;
160 int noautorespond_on_setup;
167 int incoming_early_audio;
172 char ast_rd_buf[4096];
173 struct ast_frame frame;
175 int faxdetect; /*!< 0:no 1:yes 2:yes+nojump */
176 int faxdetect_timeout;
177 struct timeval faxdetect_tv;
183 int jb_upper_threshold;
187 struct ast_trans_pvt *trans;
189 struct ast_channel * ast;
193 struct misdn_bchannel *bc;
195 struct hold_info hold_info;
200 char context[BUFFERSIZE];
203 int dropped_frame_cnt;
210 struct chan_list *other_ch;
212 const struct ind_tone_zone_sound *ts;
215 int overlap_dial_task;
216 ast_mutex_t overlap_tv_lock;
217 struct timeval overlap_tv;
219 struct chan_list *peer;
220 struct chan_list *next;
221 struct chan_list *prev;
222 struct chan_list *first;
227 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
228 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
234 struct robin_list *next;
235 struct robin_list *prev;
237 static struct robin_list *robin = NULL;
241 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
245 static inline void free_robin_list_r (struct robin_list *r)
248 if (r->next) free_robin_list_r(r->next);
249 if (r->group) free(r->group);
254 static void free_robin_list ( void )
256 free_robin_list_r(robin);
260 static struct robin_list* get_robin_position (char *group)
262 struct robin_list *iter = robin;
263 for (; iter; iter = iter->next) {
264 if (!strcasecmp(iter->group, group))
267 struct robin_list *new = (struct robin_list *)calloc(1, sizeof(struct robin_list));
268 new->group = strndup(group, strlen(group));
279 /*! \brief the main schedule context for stuff like l1 watcher, overlap dial, ... */
280 static struct sched_context *misdn_tasks = NULL;
281 static pthread_t misdn_tasks_thread;
283 static int *misdn_ports;
285 static void chan_misdn_log(int level, int port, char *tmpl, ...);
287 static struct ast_channel *misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, int format, int port, int c);
288 static void send_digit_to_chan(struct chan_list *cl, char digit );
290 static void hangup_chan(struct chan_list *ch);
291 static int pbx_start_chan(struct chan_list *ch);
293 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
294 #define MISDN_ASTERISK_PVT(ast) 1
296 #include <asterisk/strings.h>
298 /* #define MISDN_DEBUG 1 */
300 static const char misdn_type[] = "mISDN";
302 static int tracing = 0 ;
304 /*! \brief Only alaw and mulaw is allowed for now */
305 static int prefformat = AST_FORMAT_ALAW ; /* AST_FORMAT_SLINEAR ; AST_FORMAT_ULAW | */
307 static int *misdn_debug;
308 static int *misdn_debug_only;
309 static int max_ports;
311 static int *misdn_in_calls;
312 static int *misdn_out_calls;
315 struct chan_list dummy_cl;
317 struct chan_list *cl_te=NULL;
318 ast_mutex_t cl_te_lock;
320 static enum event_response_e
321 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
323 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch);
325 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan);
326 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);
327 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);
328 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid);
332 static int dialtone_indicate(struct chan_list *cl);
333 static int hanguptone_indicate(struct chan_list *cl);
334 static int stop_indicate(struct chan_list *cl);
336 static int start_bc_tones(struct chan_list *cl);
337 static int stop_bc_tones(struct chan_list *cl);
338 static void release_chan(struct misdn_bchannel *bc);
340 static int misdn_check_l2l1(struct ast_channel *chan, void *data);
341 static int misdn_set_opt_exec(struct ast_channel *chan, void *data);
342 static int misdn_facility_exec(struct ast_channel *chan, void *data);
344 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
347 void debug_numplan(int port, int numplan, char *type);
350 int add_out_calls(int port);
351 int add_in_calls(int port);
355 static int update_pipeline_config(struct misdn_bchannel *bc);
357 static int update_ec_config(struct misdn_bchannel *bc);
365 int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len);
367 /*************** Helpers *****************/
369 static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
371 struct chan_list *tmp;
373 for (tmp=cl_te; tmp; tmp = tmp->next) {
374 if ( tmp->ast == ast ) return tmp;
380 static struct chan_list * get_chan_by_ast_name(char *name)
382 struct chan_list *tmp;
384 for (tmp=cl_te; tmp; tmp = tmp->next) {
385 if ( tmp->ast && strcmp(tmp->ast->name,name) == 0) return tmp;
393 struct allowed_bearers {
399 struct allowed_bearers allowed_bearers_array[]={
400 {INFO_CAPABILITY_SPEECH,1,"speech"},
401 {INFO_CAPABILITY_AUDIO_3_1K,2,"3_1khz"},
402 {INFO_CAPABILITY_DIGITAL_UNRESTRICTED,4,"digital_unrestricted"},
403 {INFO_CAPABILITY_DIGITAL_RESTRICTED,8,"digital_restriced"},
404 {INFO_CAPABILITY_VIDEO,16,"video"}
407 static char *bearer2str(int cap) {
408 static char *bearers[]={
418 case INFO_CAPABILITY_SPEECH:
421 case INFO_CAPABILITY_AUDIO_3_1K:
424 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
427 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
430 case INFO_CAPABILITY_VIDEO:
440 static void print_facility(struct FacParm *fac, struct misdn_bchannel *bc)
442 switch (fac->Function) {
444 chan_misdn_log(1,bc->port," --> calldeflect to: %s, screened: %s\n", fac->u.CDeflection.DeflectedToNumber,
445 fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
447 case Fac_AOCDCurrency:
448 if (fac->u.AOCDcur.chargeNotAvailable)
449 chan_misdn_log(1,bc->port," --> AOCD currency: charge not available\n");
450 else if (fac->u.AOCDcur.freeOfCharge)
451 chan_misdn_log(1,bc->port," --> AOCD currency: free of charge\n");
452 else if (fac->u.AOCDchu.billingId >= 0)
453 chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d billingId:%d\n",
454 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
455 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
457 chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d\n",
458 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
459 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
461 case Fac_AOCDChargingUnit:
462 if (fac->u.AOCDchu.chargeNotAvailable)
463 chan_misdn_log(1,bc->port," --> AOCD charging unit: charge not available\n");
464 else if (fac->u.AOCDchu.freeOfCharge)
465 chan_misdn_log(1,bc->port," --> AOCD charging unit: free of charge\n");
466 else if (fac->u.AOCDchu.billingId >= 0)
467 chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
468 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
470 chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
471 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
474 chan_misdn_log(1,bc->port," --> unknown\n");
478 static void print_bearer(struct misdn_bchannel *bc)
481 chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
484 case INFO_CODEC_ALAW:
485 chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
487 case INFO_CODEC_ULAW:
488 chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
493 static void export_aoc_vars(int originator, struct ast_channel *ast, struct misdn_bchannel *bc)
497 if (!bc->AOCD_need_export || !ast)
500 if (originator == ORG_AST) {
501 ast = ast_bridged_channel(ast);
506 switch (bc->AOCDtype) {
507 case Fac_AOCDCurrency:
508 pbx_builtin_setvar_helper(ast, "AOCD_Type", "currency");
509 if (bc->AOCD.currency.chargeNotAvailable)
510 pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
512 pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
513 if (bc->AOCD.currency.freeOfCharge)
514 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
516 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
517 if (snprintf(buf, sizeof(buf), "%d %s", bc->AOCD.currency.currencyAmount * bc->AOCD.currency.multiplier, bc->AOCD.currency.currency) < sizeof(buf)) {
518 pbx_builtin_setvar_helper(ast, "AOCD_Amount", buf);
519 if (bc->AOCD.currency.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.currency.billingId) < sizeof(buf))
520 pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
525 case Fac_AOCDChargingUnit:
526 pbx_builtin_setvar_helper(ast, "AOCD_Type", "charging_unit");
527 if (bc->AOCD.chargingUnit.chargeNotAvailable)
528 pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
530 pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
531 if (bc->AOCD.chargingUnit.freeOfCharge)
532 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
534 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
535 if (snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.recordedUnits) < sizeof(buf)) {
536 pbx_builtin_setvar_helper(ast, "AOCD_RecordedUnits", buf);
537 if (bc->AOCD.chargingUnit.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.billingId) < sizeof(buf))
538 pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
547 bc->AOCD_need_export = 0;
550 /*************** Helpers END *************/
552 static void sighandler(int sig)
555 static void* misdn_tasks_thread_func (void *data)
560 sa.sa_handler = sighandler;
561 sa.sa_flags = SA_NODEFER;
562 sigemptyset(&sa.sa_mask);
563 sigaddset(&sa.sa_mask, SIGUSR1);
564 sigaction(SIGUSR1, &sa, NULL);
566 sem_post((sem_t *)data);
569 wait = ast_sched_wait(misdn_tasks);
572 if (poll(NULL, 0, wait) < 0)
573 chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
574 ast_sched_runq(misdn_tasks);
579 static void misdn_tasks_init (void)
584 if (sem_init(&blocker, 0, 0)) {
585 perror("chan_misdn: Failed to initialize semaphore!");
589 chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
591 misdn_tasks = sched_context_create();
592 pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker);
594 while (sem_wait(&blocker) && --i);
595 sem_destroy(&blocker);
598 static void misdn_tasks_destroy (void)
601 chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
602 if ( pthread_cancel(misdn_tasks_thread) == 0 ) {
603 cb_log(4, 0, "Joining misdn_tasks thread\n");
604 pthread_join(misdn_tasks_thread, NULL);
606 sched_context_destroy(misdn_tasks);
610 static inline void misdn_tasks_wakeup (void)
612 pthread_kill(misdn_tasks_thread, SIGUSR1);
615 static inline int _misdn_tasks_add_variable (int timeout, ast_sched_cb callback, void *data, int variable)
622 task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
623 misdn_tasks_wakeup();
628 static int misdn_tasks_add (int timeout, ast_sched_cb callback, void *data)
630 return _misdn_tasks_add_variable(timeout, callback, data, 0);
633 static int misdn_tasks_add_variable (int timeout, ast_sched_cb callback, void *data)
635 return _misdn_tasks_add_variable(timeout, callback, data, 1);
638 static void misdn_tasks_remove (int task_id)
640 ast_sched_del(misdn_tasks, task_id);
643 static int misdn_l1_task (void *data)
645 misdn_lib_isdn_l1watcher(*(int *)data);
646 chan_misdn_log(5, *(int *)data, "L1watcher timeout\n");
650 static int misdn_overlap_dial_task (void *data)
652 struct timeval tv_end, tv_now;
654 struct chan_list *ch = (struct chan_list *)data;
656 chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state);
658 if (ch->state != MISDN_WAITING4DIGS) {
659 ch->overlap_dial_task = -1;
663 ast_mutex_lock(&ch->overlap_tv_lock);
664 tv_end = ch->overlap_tv;
665 ast_mutex_unlock(&ch->overlap_tv_lock);
667 tv_end.tv_sec += ch->overlap_dial;
668 tv_now = ast_tvnow();
670 diff = ast_tvdiff_ms(tv_end, tv_now);
673 /* if we are 100ms near the timeout, we are satisfied.. */
675 if (ast_exists_extension(ch->ast, ch->context, ch->bc->dad, 1, ch->bc->oad)) {
676 ch->state=MISDN_DIALING;
677 if (pbx_start_chan(ch) < 0) {
678 chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
679 goto misdn_overlap_dial_task_disconnect;
682 misdn_overlap_dial_task_disconnect:
683 hanguptone_indicate(ch);
685 misdn_lib_send_event(ch->bc, EVENT_RELEASE_COMPLETE );
687 misdn_lib_send_event(ch->bc, EVENT_RELEASE);
689 ch->overlap_dial_task = -1;
695 static void send_digit_to_chan(struct chan_list *cl, char digit )
697 static const char* dtmf_tones[] = {
698 "!941+1336/100,!0/100", /* 0 */
699 "!697+1209/100,!0/100", /* 1 */
700 "!697+1336/100,!0/100", /* 2 */
701 "!697+1477/100,!0/100", /* 3 */
702 "!770+1209/100,!0/100", /* 4 */
703 "!770+1336/100,!0/100", /* 5 */
704 "!770+1477/100,!0/100", /* 6 */
705 "!852+1209/100,!0/100", /* 7 */
706 "!852+1336/100,!0/100", /* 8 */
707 "!852+1477/100,!0/100", /* 9 */
708 "!697+1633/100,!0/100", /* A */
709 "!770+1633/100,!0/100", /* B */
710 "!852+1633/100,!0/100", /* C */
711 "!941+1633/100,!0/100", /* D */
712 "!941+1209/100,!0/100", /* * */
713 "!941+1477/100,!0/100" }; /* # */
714 struct ast_channel *chan=cl->ast;
716 if (digit >= '0' && digit <='9')
717 ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
718 else if (digit >= 'A' && digit <= 'D')
719 ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
720 else if (digit == '*')
721 ast_playtones_start(chan,0,dtmf_tones[14], 0);
722 else if (digit == '#')
723 ast_playtones_start(chan,0,dtmf_tones[15], 0);
727 ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
730 /*** CLI HANDLING ***/
731 static int misdn_set_debug(int fd, int argc, char *argv[])
733 if (argc != 4 && argc != 5 && argc != 6 && argc != 7)
734 return RESULT_SHOWUSAGE;
736 int level = atoi(argv[3]);
743 if (strncasecmp(argv[4], "only", strlen(argv[4])))
744 return RESULT_SHOWUSAGE;
749 for (i=0; i<=max_ports; i++) {
750 misdn_debug[i] = level;
751 misdn_debug_only[i] = only;
753 ast_cli(fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
758 if (strncasecmp(argv[4], "port", strlen(argv[4])))
759 return RESULT_SHOWUSAGE;
760 int port = atoi(argv[5]);
761 if (port <= 0 || port > max_ports) {
764 ast_cli(fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
767 ast_cli(fd, "port number not valid! only port 1 is availble.\n");
770 ast_cli(fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
775 if (strncasecmp(argv[6], "only", strlen(argv[6])))
776 return RESULT_SHOWUSAGE;
778 misdn_debug_only[port] = 1;
780 misdn_debug_only[port] = 0;
781 misdn_debug[port] = level;
782 ast_cli(fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
788 static int misdn_set_crypt_debug(int fd, int argc, char *argv[])
790 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);
983 struct state_struct {
984 enum misdn_chan_state state;
988 static struct state_struct state_array[] = {
989 {MISDN_NOTHING,"NOTHING"}, /* at beginning */
990 {MISDN_WAITING4DIGS,"WAITING4DIGS"}, /* when waiting for infos */
991 {MISDN_EXTCANTMATCH,"EXTCANTMATCH"}, /* when asterisk couldnt match our ext */
992 {MISDN_INCOMING_SETUP,"INCOMING SETUP"}, /* when pbx_start */
993 {MISDN_DIALING,"DIALING"}, /* when pbx_start */
994 {MISDN_PROGRESS,"PROGRESS"}, /* when pbx_start */
995 {MISDN_PROCEEDING,"PROCEEDING"}, /* when pbx_start */
996 {MISDN_CALLING,"CALLING"}, /* when misdn_call is called */
997 {MISDN_CALLING_ACKNOWLEDGE,"CALLING_ACKNOWLEDGE"}, /* when misdn_call is called */
998 {MISDN_ALERTING,"ALERTING"}, /* when Alerting */
999 {MISDN_BUSY,"BUSY"}, /* when BUSY */
1000 {MISDN_CONNECTED,"CONNECTED"}, /* when connected */
1001 {MISDN_PRECONNECTED,"PRECONNECTED"}, /* when connected */
1002 {MISDN_DISCONNECTED,"DISCONNECTED"}, /* when connected */
1003 {MISDN_RELEASED,"RELEASED"}, /* when connected */
1004 {MISDN_BRIDGED,"BRIDGED"}, /* when bridged */
1005 {MISDN_CLEANING,"CLEANING"}, /* when hangup from * but we were connected before */
1006 {MISDN_HUNGUP_FROM_MISDN,"HUNGUP_FROM_MISDN"}, /* when DISCONNECT/RELEASE/REL_COMP cam from misdn */
1007 {MISDN_HOLDED,"HOLDED"}, /* when DISCONNECT/RELEASE/REL_COMP cam from misdn */
1008 {MISDN_HOLD_DISCONNECT,"HOLD_DISCONNECT"}, /* when DISCONNECT/RELEASE/REL_COMP cam from misdn */
1009 {MISDN_HUNGUP_FROM_AST,"HUNGUP_FROM_AST"} /* when DISCONNECT/RELEASE/REL_COMP came out of */
1013 static 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) return state_array[i].txt;
1024 sprintf(state,"%d",p->state) ;
1031 static void reload_config(void)
1035 if (!g_config_initialized) {
1036 ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
1042 misdn_cfg_update_ptp();
1043 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
1044 misdn_cfg_get( 0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(int));
1046 for (i = 0; i <= max_ports; i++) {
1047 misdn_debug[i] = cfg_debug;
1048 misdn_debug_only[i] = 0;
1052 static int misdn_reload (int fd, int argc, char *argv[])
1054 ast_cli(fd, "Reloading mISDN Config\n");
1059 static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel* bc)
1061 struct ast_channel *ast=help->ast;
1063 "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
1065 bc->pid, bc->port, bc->channel,
1067 help->originator == ORG_AST?"*":"I",
1068 ast?ast->exten:NULL,
1069 ast?ast->cid.cid_num:NULL,
1071 ast?ast->context:NULL,
1072 misdn_get_ch_state(help)
1074 if (misdn_debug[bc->port] > 0)
1076 " --> astname: %s\n"
1077 " --> ch_l3id: %x\n"
1078 " --> ch_addr: %x\n"
1079 " --> bc_addr: %x\n"
1080 " --> bc_l3id: %x\n"
1081 " --> display: %s\n"
1082 " --> activated: %d\n"
1084 " --> capability: %s\n"
1086 " --> pipeline: %s\n"
1088 " --> echo_cancel: %d\n"
1090 " --> notone : rx %d tx:%d\n"
1091 " --> bc_hold: %d\n",
1100 bc_state2str(bc->bc_state),
1101 bearer2str(bc->capability),
1108 help->norxtone,help->notxtone,
1114 static int misdn_show_cls (int fd, int argc, char *argv[])
1116 struct chan_list *help=cl_te;
1118 ast_cli(fd,"Chan List: %p\n",cl_te);
1120 for (;help; help=help->next) {
1121 struct misdn_bchannel *bc=help->bc;
1122 struct ast_channel *ast=help->ast;
1123 if (misdn_debug[0] > 2) ast_cli(fd, "Bc:%p Ast:%p\n", bc, ast);
1125 print_bc_info(fd, help, bc);
1127 if (help->state == MISDN_HOLDED) {
1128 ast_cli(fd, "ITS A HOLDED BC:\n");
1129 ast_cli(fd, " --> l3_id: %x\n"
1130 " --> dad:%s oad:%s\n"
1131 " --> hold_port: %d\n"
1132 " --> hold_channel: %d\n"
1137 ,help->hold_info.port
1138 ,help->hold_info.channel
1141 ast_cli(fd,"* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, ast->cid.cid_num);
1150 static int misdn_show_cl (int fd, int argc, char *argv[])
1152 struct chan_list *help=cl_te;
1155 return RESULT_SHOWUSAGE;
1157 for (;help; help=help->next) {
1158 struct misdn_bchannel *bc=help->bc;
1159 struct ast_channel *ast=help->ast;
1162 if (!strcasecmp(ast->name,argv[3])) {
1163 print_bc_info(fd, help, bc);
1176 static int misdn_set_tics (int fd, int argc, char *argv[])
1179 return RESULT_SHOWUSAGE;
1181 MAXTICS=atoi(argv[3]);
1186 static int misdn_show_stacks (int fd, int argc, char *argv[])
1190 ast_cli(fd, "BEGIN STACK_LIST:\n");
1192 for (port=misdn_cfg_get_next_port(0); port > 0;
1193 port=misdn_cfg_get_next_port(port)) {
1195 get_show_stack_details(port,buf);
1196 ast_cli(fd," %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
1203 static int misdn_show_ports_stats (int fd, int argc, char *argv[])
1207 ast_cli(fd, "Port\tin_calls\tout_calls\n");
1209 for (port=misdn_cfg_get_next_port(0); port > 0;
1210 port=misdn_cfg_get_next_port(port)) {
1211 ast_cli(fd,"%d\t%d\t\t%d\n",port,misdn_in_calls[port],misdn_out_calls[port]);
1220 static int misdn_show_port (int fd, int argc, char *argv[])
1225 return RESULT_SHOWUSAGE;
1227 port = atoi(argv[3]);
1229 ast_cli(fd, "BEGIN STACK_LIST:\n");
1232 get_show_stack_details(port,buf);
1233 ast_cli(fd," %s Debug:%d%s\n",buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
1239 static int misdn_send_cd (int fd, int argc, char *argv[])
1245 return RESULT_SHOWUSAGE;
1250 ast_cli(fd, "Sending Calldeflection (%s) to %s\n",nr, channame);
1253 struct chan_list *tmp=get_chan_by_ast_name(channame);
1256 ast_cli(fd, "Sending CD with nr %s to %s failed: Channel does not exist.\n",nr, channame);
1259 if (strlen(nr) >= 15) {
1260 ast_cli(fd, "Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n",nr, channame);
1263 tmp->bc->fac_out.Function = Fac_CD;
1264 strncpy((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber));
1265 misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
1272 static int misdn_send_digit (int fd, int argc, char *argv[])
1278 return RESULT_SHOWUSAGE;
1283 ast_cli(fd, "Sending %s to %s\n",msg, channame);
1286 struct chan_list *tmp=get_chan_by_ast_name(channame);
1289 ast_cli(fd, "Sending %s to %s failed Channel does not exist\n",msg, channame);
1294 int msglen = strlen(msg);
1295 for (i=0; i<msglen; i++) {
1296 ast_cli(fd, "Sending: %c\n",msg[i]);
1297 send_digit_to_chan(tmp, msg[i]);
1298 /* res = ast_safe_sleep(tmp->ast, 250); */
1300 /* res = ast_waitfor(tmp->ast,100); */
1304 res = ast_dtmf_stream(tmp->ast,NULL,msg,250);
1312 static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
1317 return RESULT_SHOWUSAGE;
1321 ast_cli(fd, "Toggling EchoCancel on %s\n", channame);
1324 struct chan_list *tmp=get_chan_by_ast_name(channame);
1327 ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
1331 tmp->toggle_ec=tmp->toggle_ec?0:1;
1333 if (tmp->toggle_ec) {
1335 update_pipeline_config(tmp->bc);
1337 update_ec_config(tmp->bc);
1339 manager_ec_enable(tmp->bc);
1341 manager_ec_disable(tmp->bc);
1349 static int misdn_send_display (int fd, int argc, char *argv[])
1355 return RESULT_SHOWUSAGE;
1360 ast_cli(fd, "Sending %s to %s\n",msg, channame);
1362 struct chan_list *tmp;
1363 tmp=get_chan_by_ast_name(channame);
1365 if (tmp && tmp->bc) {
1366 ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
1367 misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
1369 ast_cli(fd,"No such channel %s\n",channame);
1370 return RESULT_FAILURE;
1374 return RESULT_SUCCESS ;
1377 static char *complete_ch_helper(const char *line, const char *word, int pos, int state, int rpos)
1379 struct ast_channel *c;
1384 c = ast_channel_walk_locked(NULL);
1386 if (!strncasecmp(word, c->name, strlen(word))) {
1387 if (++which > state)
1390 ast_mutex_unlock(&c->lock);
1391 c = ast_channel_walk_locked(c);
1394 ret = strdup(c->name);
1395 ast_mutex_unlock(&c->lock);
1401 static char *complete_ch(const char *line, const char *word, int pos, int state)
1403 return complete_ch_helper(line, word, pos, state, 3);
1406 static char *complete_debug_port (const char *line, const char *word, int pos, int state)
1412 case 4: if (*word == 'p')
1413 return strdup("port");
1414 else if (*word == 'o')
1415 return strdup("only");
1417 case 6: if (*word == 'o')
1418 return strdup("only");
1424 static char *complete_show_config (const char *line, const char *word, int pos, int state)
1426 char buffer[BUFFERSIZE];
1427 enum misdn_cfg_elements elem;
1428 int wordlen = strlen(word);
1433 case 3: if ((!strncmp(word, "description", wordlen)) && (++which > state))
1434 return strdup("description");
1435 if ((!strncmp(word, "descriptions", wordlen)) && (++which > state))
1436 return strdup("descriptions");
1437 if ((!strncmp(word, "0", wordlen)) && (++which > state))
1439 while ((port = misdn_cfg_get_next_port(port)) != -1) {
1440 snprintf(buffer, sizeof(buffer), "%d", port);
1441 if ((!strncmp(word, buffer, wordlen)) && (++which > state)) {
1442 return strdup(buffer);
1447 if (strstr(line, "description ")) {
1448 for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
1449 if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST))
1451 misdn_cfg_get_name(elem, buffer, BUFFERSIZE);
1452 if (!wordlen || !strncmp(word, buffer, wordlen)) {
1453 if (++which > state)
1454 return strdup(buffer);
1457 } else if (strstr(line, "descriptions ")) {
1458 if ((!wordlen || !strncmp(word, "general", wordlen)) && (++which > state))
1459 return strdup("general");
1460 if ((!wordlen || !strncmp(word, "ports", wordlen)) && (++which > state))
1461 return strdup("ports");
1468 static struct ast_cli_entry chan_misdn_clis[] = {
1469 { {"misdn","send","calldeflect", NULL}, misdn_send_cd, "Sends CallDeflection to mISDN Channel",
1470 "Usage: misdn send calldeflect <channel> \"<nr>\" \n", complete_ch },
1471 { {"misdn","send","digit", NULL}, misdn_send_digit, "Sends DTMF Digit to mISDN Channel",
1472 "Usage: misdn send digit <channel> \"<msg>\" \n"
1473 " Send <digit> to <channel> as DTMF Tone\n"
1474 " when channel is a mISDN channel\n", complete_ch },
1475 { {"misdn","toggle","echocancel", NULL}, misdn_toggle_echocancel, "Toggles EchoCancel on mISDN Channel",
1476 "Usage: misdn toggle echocancel <channel>\n", complete_ch },
1477 { {"misdn","send","display", NULL}, misdn_send_display, "Sends Text to mISDN Channel",
1478 "Usage: misdn send display <channel> \"<msg>\" \n"
1479 " Send <msg> to <channel> as Display Message\n"
1480 " when channel is a mISDN channel\n", complete_ch },
1481 { {"misdn","show","config", NULL}, misdn_show_config, "Shows internal mISDN config, read from cfg-file",
1482 "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
1483 " Use 0 for <port> to only print the general config.\n", complete_show_config },
1484 { {"misdn","reload", NULL}, misdn_reload, "Reloads internal mISDN config, read from cfg-file",
1485 "Usage: misdn reload\n" },
1486 { {"misdn","set","tics", NULL}, misdn_set_tics, "",
1488 { {"misdn","show","channels", NULL}, misdn_show_cls, "Shows internal mISDN chan_list",
1489 "Usage: misdn show channels\n" },
1490 { {"misdn","show","channel", NULL}, misdn_show_cl, "Shows internal mISDN chan_list",
1491 "Usage: misdn show channels\n", complete_ch },
1492 { {"misdn","port","block", NULL}, misdn_port_block, "Blocks the given port",
1493 "Usage: misdn port block\n" },
1494 { {"misdn","port","unblock", NULL}, misdn_port_unblock, "Unblocks the given port",
1495 "Usage: misdn port unblock\n" },
1496 { {"misdn","restart","port", NULL}, misdn_restart_port, "Restarts the given port",
1497 "Usage: misdn restart port\n" },
1498 { {"misdn","restart","pid", NULL}, misdn_restart_pid, "Restarts the given pid",
1499 "Usage: misdn restart pid\n" },
1500 { {"misdn","port","up", NULL}, misdn_port_up, "Tries to establish L1 on the given port",
1501 "Usage: misdn port up <port>\n" },
1502 { {"misdn","port","down", NULL}, misdn_port_down, "Tries to deacivate the L1 on the given port",
1503 "Usage: misdn port down <port>\n" },
1504 { {"misdn","show","stacks", NULL}, misdn_show_stacks, "Shows internal mISDN stack_list",
1505 "Usage: misdn show stacks\n" },
1506 { {"misdn","show","ports","stats", NULL}, misdn_show_ports_stats, "Shows chan_misdns call statistics per port",
1507 "Usage: misdn show port stats\n" },
1508 { {"misdn","show","port", NULL}, misdn_show_port, "Shows detailed information for given port",
1509 "Usage: misdn show port <port>\n" },
1510 { {"misdn","set","debug", NULL}, misdn_set_debug, "Sets Debuglevel of chan_misdn",
1511 "Usage: misdn set debug <level> [only] | [port <port> [only]]\n", complete_debug_port },
1512 { {"misdn","set","crypt","debug", NULL}, misdn_set_crypt_debug, "Sets CryptDebuglevel of chan_misdn, at the moment, level={1,2}",
1513 "Usage: misdn set crypt debug <level>\n" }
1516 static int update_config (struct chan_list *ch, int orig)
1519 ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
1523 struct ast_channel *ast=ch->ast;
1524 struct misdn_bchannel *bc=ch->bc;
1525 if (! ast || ! bc ) {
1526 ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
1532 chan_misdn_log(7,port,"update_config: Getting Config\n");
1535 misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
1538 switch (bc->capability) {
1539 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
1540 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
1541 chan_misdn_log(1,bc->port," --> CONF HDLC\n");
1551 misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int));
1552 misdn_cfg_get( port, MISDN_CFG_SCREEN, &screen, sizeof(int));
1553 chan_misdn_log(2,port," --> pres: %d screen: %d\n",pres, screen);
1555 if ( (pres + screen) < 0 ) {
1557 chan_misdn_log(2,port," --> pres: %x\n", ast->cid.cid_pres);
1559 switch (ast->cid.cid_pres & 0x60){
1561 case AST_PRES_RESTRICTED:
1563 chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
1567 case AST_PRES_UNAVAILABLE:
1569 chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
1574 chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
1577 switch (ast->cid.cid_pres & 0x3){
1579 case AST_PRES_USER_NUMBER_UNSCREENED:
1581 chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
1584 case AST_PRES_USER_NUMBER_PASSED_SCREEN:
1586 chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
1588 case AST_PRES_USER_NUMBER_FAILED_SCREEN:
1590 chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
1593 case AST_PRES_NETWORK_NUMBER:
1595 chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
1600 chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
1616 static void config_jitterbuffer(struct chan_list *ch)
1618 struct misdn_bchannel *bc=ch->bc;
1619 int len=ch->jb_len, threshold=ch->jb_upper_threshold;
1621 chan_misdn_log(5,bc->port, "config_jb: Called\n");
1624 chan_misdn_log(1,bc->port, "config_jb: Deactivating Jitterbuffer\n");
1628 if (len <=100 || len > 8000) {
1629 chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
1633 if ( threshold > len ) {
1634 chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
1638 cb_log(0,bc->port,"config_jb: We've got a Jitterbuffer Already on this port.\n");
1639 misdn_jb_destroy(ch->jb);
1643 ch->jb=misdn_jb_init(len, threshold);
1651 void debug_numplan(int port, int numplan, char *type)
1654 case NUMPLAN_INTERNATIONAL:
1655 chan_misdn_log(2, port, " --> %s: International\n",type);
1657 case NUMPLAN_NATIONAL:
1658 chan_misdn_log(2, port, " --> %s: National\n",type);
1660 case NUMPLAN_SUBSCRIBER:
1661 chan_misdn_log(2, port, " --> %s: Subscriber\n",type);
1663 case NUMPLAN_UNKNOWN:
1664 chan_misdn_log(2, port, " --> %s: Unknown\n",type);
1666 /* Maybe we should cut off the prefix if present ? */
1668 chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
1677 static int update_pipeline_config(struct misdn_bchannel *bc)
1681 misdn_cfg_get(bc->port, MISDN_CFG_PIPELINE, bc->pipeline, sizeof(bc->pipeline));
1686 misdn_cfg_get(bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
1688 snprintf(bc->pipeline, sizeof(bc->pipeline) - 1, "mg2ec");
1690 snprintf(bc->pipeline, sizeof(bc->pipeline) - 1, "mg2ec(deftaps=%d)", ec);
1695 static int update_ec_config(struct misdn_bchannel *bc)
1700 misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
1704 } else if ( ec > 1 ) {
1714 static int read_config(struct chan_list *ch, int orig) {
1717 ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
1721 struct ast_channel *ast=ch->ast;
1722 struct misdn_bchannel *bc=ch->bc;
1723 if (! ast || ! bc ) {
1724 ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
1730 chan_misdn_log(1,port,"read_config: Getting Config\n");
1732 char lang[BUFFERSIZE+1];
1735 misdn_cfg_get( port, MISDN_CFG_LANGUAGE, lang, BUFFERSIZE);
1736 ast_string_field_set(ast, language, lang);
1738 char localmusicclass[BUFFERSIZE+1];
1740 misdn_cfg_get( port, MISDN_CFG_MUSICCLASS, localmusicclass, BUFFERSIZE);
1741 ast_string_field_set(ast, musicclass, localmusicclass);
1744 misdn_cfg_get( port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(int));
1745 misdn_cfg_get( port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(int));
1747 misdn_cfg_get( port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(int));
1749 misdn_cfg_get( port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(int));
1751 misdn_cfg_get( port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(int));
1752 misdn_cfg_get( port, MISDN_CFG_NTTIMEOUT, &ch->nttimeout, sizeof(int));
1754 misdn_cfg_get( port, MISDN_CFG_NOAUTORESPOND_ON_SETUP, &ch->noautorespond_on_setup, sizeof(int));
1756 misdn_cfg_get( port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(int));
1758 misdn_cfg_get( port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, BUFFERSIZE);
1760 char faxdetect[BUFFERSIZE+1];
1761 misdn_cfg_get( port, MISDN_CFG_FAXDETECT, faxdetect, BUFFERSIZE);
1764 misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
1767 switch (bc->capability) {
1768 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
1769 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
1770 chan_misdn_log(1,bc->port," --> CONF HDLC\n");
1776 /*Initialize new Jitterbuffer*/
1778 misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(int));
1779 misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(int));
1781 config_jitterbuffer(ch);
1784 misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
1786 ast_copy_string (ast->context,ch->context,sizeof(ast->context));
1789 update_pipeline_config(bc);
1791 update_ec_config(bc);
1797 misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
1798 bc->early_bconnect=eb3;
1807 misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
1808 misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
1810 chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
1811 ast->pickupgroup=pg;
1815 if ( orig == ORG_AST) {
1816 misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(int));
1818 if (strstr(faxdetect, "outgoing") || strstr(faxdetect, "both")) {
1819 if (strstr(faxdetect, "nojump"))
1826 char callerid[BUFFERSIZE+1];
1827 misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
1828 if ( ! ast_strlen_zero(callerid) ) {
1829 chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
1831 int l = sizeof(bc->oad);
1832 strncpy(bc->oad,callerid, l);
1839 misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(int));
1840 misdn_cfg_get( port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(int));
1841 misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
1842 debug_numplan(port, bc->dnumplan,"TON");
1843 debug_numplan(port, bc->onumplan,"LTON");
1844 debug_numplan(port, bc->cpnnumplan,"CTON");
1847 ch->overlap_dial = 0;
1848 } else { /** ORIGINATOR MISDN **/
1849 if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
1850 if (strstr(faxdetect, "nojump"))
1856 misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
1857 debug_numplan(port, bc->cpnnumplan,"CTON");
1859 char prefix[BUFFERSIZE+1]="";
1860 switch( bc->onumplan ) {
1861 case NUMPLAN_INTERNATIONAL:
1862 misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
1865 case NUMPLAN_NATIONAL:
1866 misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
1873 int l = strlen(prefix) + strlen(bc->oad);
1876 strcat(tmp,bc->oad);
1877 strcpy(bc->oad,tmp);
1880 if (!ast_strlen_zero(bc->dad)) {
1881 ast_copy_string(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
1884 if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
1885 ast_copy_string(bc->dad,bc->keypad, sizeof(bc->dad));
1890 switch( bc->dnumplan ) {
1891 case NUMPLAN_INTERNATIONAL:
1892 misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
1894 case NUMPLAN_NATIONAL:
1895 misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
1902 int l = strlen(prefix) + strlen(bc->dad);
1905 strcat(tmp,bc->dad);
1906 strcpy(bc->dad,tmp);
1909 if ( strcmp(bc->dad,ast->exten)) {
1910 ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
1913 ast_set_callerid(ast, bc->oad, NULL, bc->oad);
1915 if ( !ast_strlen_zero(bc->rad) ) {
1916 if (ast->cid.cid_rdnis)
1917 free(ast->cid.cid_rdnis);
1918 ast->cid.cid_rdnis = strdup(bc->rad);
1921 misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
1922 ast_mutex_init(&ch->overlap_tv_lock);
1923 } /* ORIG MISDN END */
1925 ch->overlap_dial_task = -1;
1927 if (ch->faxdetect) {
1928 misdn_cfg_get( port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
1930 ch->dsp = ast_dsp_new();
1932 ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT | DSP_FEATURE_FAX_DETECT);
1934 ch->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
1937 /* AOCD initialization */
1938 bc->AOCDtype = Fac_None;
1944 /*****************************/
1945 /*** AST Indications Start ***/
1946 /*****************************/
1948 static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
1952 struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
1953 struct misdn_bchannel *newbc;
1954 char *opts=NULL, *ext,*tokb;
1958 strncpy(dest_cp,dest,sizeof(dest_cp)-1);
1959 dest_cp[sizeof(dest_cp)]=0;
1961 ext=strtok_r(dest_cp,"/",&tokb);
1964 ext=strtok_r(NULL,"/",&tokb);
1966 opts=strtok_r(NULL,"/",&tokb);
1968 chan_misdn_log(0,0,"misdn_call: No Extension given!\n");
1975 ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
1979 if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest ) {
1980 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1981 ast->hangupcause=41;
1982 ast_setstate(ast, AST_STATE_DOWN);
1987 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1988 ast->hangupcause=41;
1989 ast_setstate(ast, AST_STATE_DOWN);
1996 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1997 ast->hangupcause=41;
1998 ast_setstate(ast, AST_STATE_DOWN);
2006 if ((exceed=add_out_calls(port))) {
2008 sprintf(tmp,"%d",exceed);
2009 pbx_builtin_setvar_helper(ast,"MAX_OVERFLOW",tmp);
2013 chan_misdn_log(1, port, "* CALL: %s\n",dest);
2015 chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
2017 chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten);
2019 int l = sizeof(newbc->dad);
2020 strncpy(ast->exten,ext,sizeof(ast->exten));
2022 strncpy(newbc->dad,ext,l);
2024 newbc->dad[l-1] = 0;
2027 if (ast->cid.cid_rdnis)
2028 strcpy(newbc->rad, ast->cid.cid_rdnis);
2032 chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",ast->cid.cid_num);
2033 if (ast_strlen_zero(newbc->oad) && ast->cid.cid_num ) {
2035 if (ast->cid.cid_num) {
2036 int l = sizeof(newbc->oad);
2037 strncpy(newbc->oad,ast->cid.cid_num, l);
2038 newbc->oad[l-1] = 0;
2043 struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
2044 if (!ch) { ast_verbose("No chan_list in misdn_call\n"); return -1;}
2046 newbc->capability=ast->transfercapability;
2047 pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability));
2048 if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
2049 chan_misdn_log(2, port, " --> * Call with flag Digital\n");
2053 /* update screening and presentation */
2054 update_config(ch,ORG_AST);
2056 /* fill in some ies from channel vary*/
2057 import_ch(ast, newbc, ch);
2059 /* Finally The Options Override Everything */
2061 misdn_set_opt_exec(ast,opts);
2063 chan_misdn_log(2,port,"NO OPTS GIVEN\n");
2065 /*check for bridging*/
2067 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
2068 if (bridging && ch->other_ch) {
2070 chan_misdn_log(1, port, "Disabling EC (aka Pipeline) on both Sides\n");
2071 *ch->bc->pipeline=0;
2072 *ch->other_ch->bc->pipeline=0;
2074 chan_misdn_log(1, port, "Disabling EC on both Sides\n");
2075 ch->bc->ec_enable=0;
2076 ch->other_ch->bc->ec_enable=0;
2080 r=misdn_lib_send_event( newbc, EVENT_SETUP );
2082 /** we should have l3id after sending setup **/
2083 ch->l3id=newbc->l3_id;
2086 if ( r == -ENOCHAN ) {
2087 chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
2088 chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n",newbc?newbc->pid:-1);
2089 ast->hangupcause=34;
2090 ast_setstate(ast, AST_STATE_DOWN);
2094 chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
2096 ast_setstate(ast, AST_STATE_DIALING);
2097 ast->hangupcause=16;
2099 if (newbc->nt) stop_bc_tones(ch);
2101 ch->state=MISDN_CALLING;
2107 static int misdn_answer(struct ast_channel *ast)
2109 struct chan_list *p;
2112 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
2114 chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n");
2117 ast_log(LOG_WARNING, " --> Channel not connected ??\n");
2118 ast_queue_hangup(ast);
2122 chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n");
2124 ast_queue_hangup(ast);
2128 const char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
2131 chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
2133 int l = sizeof(p->bc->crypt_key);
2134 strncpy(p->bc->crypt_key,tmp_key, l);
2135 p->bc->crypt_key[l-1] = 0;
2138 chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
2144 const char *nodsp=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
2146 chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
2153 p->state = MISDN_CONNECTED;
2156 if ( ast_strlen_zero(p->bc->cad) ) {
2157 chan_misdn_log(2,p->bc->port," --> empty cad using dad\n");
2158 ast_copy_string(p->bc->cad,p->bc->dad,sizeof(p->bc->cad));
2161 misdn_lib_send_event( p->bc, EVENT_CONNECT);
2167 static int misdn_digit_begin(struct ast_channel *chan, char digit)
2169 /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
2173 static int misdn_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
2175 struct chan_list *p;
2177 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) return -1;
2179 struct misdn_bchannel *bc=p->bc;
2180 chan_misdn_log(1, bc?bc->port:0, "* IND : Digit %c\n",digit);
2183 ast_log(LOG_WARNING, " --> !! Got Digit Event withut having bchannel Object\n");
2187 switch (p->state ) {
2195 int l = sizeof(bc->infos_pending);
2196 strncat(bc->infos_pending,buf,l);
2197 bc->infos_pending[l-1] = 0;
2200 case MISDN_CALLING_ACKNOWLEDGE:
2202 bc->info_dad[0]=digit;
2206 int l = sizeof(bc->dad);
2207 strncat(bc->dad,bc->info_dad, l - strlen(bc->dad));
2211 int l = sizeof(p->ast->exten);
2212 strncpy(p->ast->exten, bc->dad, l);
2213 p->ast->exten[l-1] = 0;
2216 misdn_lib_send_event( bc, EVENT_INFORMATION);
2221 if ( bc->send_dtmf ) {
2222 send_digit_to_chan(p,digit);
2231 static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
2233 struct chan_list *p;
2235 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
2237 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);
2246 static int misdn_indication(struct ast_channel *ast, int cond, const void *data, size_t datalen)
2248 struct chan_list *p;
2251 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
2252 ast_log(LOG_WARNING, "Returnded -1 in misdn_indication\n");
2257 chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten);
2258 ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
2262 chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] from %s\n",cond, ast->exten);
2265 case AST_CONTROL_BUSY:
2266 chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n",p->bc?p->bc->pid:-1);
2267 ast_setstate(ast,AST_STATE_BUSY);
2269 p->bc->out_cause=17;
2270 if (p->state != MISDN_CONNECTED) {
2272 misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
2274 chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name);
2278 case AST_CONTROL_RING:
2279 chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
2283 case AST_CONTROL_RINGING:
2284 chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
2286 case MISDN_ALERTING:
2287 chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoreing it\n",p->bc?p->bc->pid:-1);
2289 case MISDN_CONNECTED:
2290 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);
2294 p->state=MISDN_ALERTING;
2295 chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
2296 misdn_lib_send_event( p->bc, EVENT_ALERTING);
2298 if (p->other_ch && p->other_ch->bc) {
2299 if (misdn_inband_avail(p->other_ch->bc)) {
2300 chan_misdn_log(2,p->bc->port, " --> other End is mISDN and has inband info available\n");
2304 if (!p->other_ch->bc->nt) {
2305 chan_misdn_log(2,p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
2310 chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
2311 ast_setstate(ast,AST_STATE_RINGING);
2313 if ( !p->bc->nt && (p->originator==ORG_MISDN) && !p->incoming_early_audio )
2314 chan_misdn_log(2,p->bc->port, " --> incoming_early_audio off\n");
2319 case AST_CONTROL_ANSWER:
2320 chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1);
2323 case AST_CONTROL_TAKEOFFHOOK:
2324 chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1);
2327 case AST_CONTROL_OFFHOOK:
2328 chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1);
2331 case AST_CONTROL_FLASH:
2332 chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1);
2334 case AST_CONTROL_PROGRESS:
2335 chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n",p->bc?p->bc->pid:-1);
2336 misdn_lib_send_event( p->bc, EVENT_PROGRESS);
2338 case AST_CONTROL_PROCEEDING:
2339 chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n",p->bc?p->bc->pid:-1);
2340 misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
2342 case AST_CONTROL_CONGESTION:
2343 chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n",p->bc?p->bc->pid:-1);
2345 p->bc->out_cause=42;
2347 misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
2350 hanguptone_indicate(p);
2354 chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n",p->bc?p->bc->pid:-1);
2358 if (p->state == MISDN_CONNECTED)
2363 case AST_CONTROL_HOLD:
2364 chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n",p->bc?p->bc->pid:-1);
2366 case AST_CONTROL_UNHOLD:
2367 chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1);
2370 chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
2376 static int misdn_hangup(struct ast_channel *ast)
2378 struct chan_list *p;
2379 struct misdn_bchannel *bc=NULL;
2382 ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
2384 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
2387 chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
2393 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
2396 if (ast->_state == AST_STATE_RESERVED ||
2397 p->state == MISDN_NOTHING ||
2398 p->state == MISDN_HOLDED ||
2399 p->state == MISDN_HOLD_DISCONNECT ) {
2402 /* between request and call */
2404 ast_log(LOG_DEBUG, "State Reserved (or nothing) => chanIsAvail\n");
2405 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
2407 cl_dequeue_chan(&cl_te, p);
2413 misdn_lib_release(bc);
2419 ast_log(LOG_WARNING,"Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p), p->l3id);
2425 p->need_queue_hangup=0;
2434 const char *varcause=NULL;
2435 bc->out_cause=ast->hangupcause?ast->hangupcause:16;
2437 if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
2438 (varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
2439 int tmpcause=atoi(varcause);
2440 bc->out_cause=tmpcause?tmpcause:16;
2443 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));
2444 chan_misdn_log(3, bc->port, " --> l3id:%x\n",p->l3id);
2445 chan_misdn_log(3, bc->port, " --> cause:%d\n",bc->cause);
2446 chan_misdn_log(2, bc->port, " --> out_cause:%d\n",bc->out_cause);
2447 chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
2450 case MISDN_INCOMING_SETUP:
2452 p->state=MISDN_CLEANING;
2453 misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
2458 hanguptone_indicate(p);
2460 if (bc->need_disconnect)
2461 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2464 case MISDN_CALLING_ACKNOWLEDGE:
2466 hanguptone_indicate(p);
2468 if (bc->need_disconnect)
2469 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2472 case MISDN_ALERTING:
2473 case MISDN_PROGRESS:
2474 case MISDN_PROCEEDING:
2475 if (p->originator != ORG_AST)
2476 hanguptone_indicate(p);
2478 /*p->state=MISDN_CLEANING;*/
2479 if (bc->need_disconnect)
2480 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2482 case MISDN_CONNECTED:
2483 case MISDN_PRECONNECTED:
2484 /* Alerting or Disconect */
2487 hanguptone_indicate(p);
2488 p->bc->progress_indicator=8;
2490 if (bc->need_disconnect)
2491 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2493 /*p->state=MISDN_CLEANING;*/
2495 case MISDN_DISCONNECTED:
2496 misdn_lib_send_event( bc, EVENT_RELEASE);
2497 p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
2500 case MISDN_RELEASED:
2501 case MISDN_CLEANING:
2502 p->state=MISDN_CLEANING;
2508 case MISDN_HOLD_DISCONNECT:
2509 /* need to send release here */
2510 chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause);
2511 chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause);
2514 misdn_lib_send_event(bc,EVENT_RELEASE);
2515 p->state=MISDN_CLEANING;
2520 misdn_lib_send_event(bc, EVENT_RELEASE);
2521 p->state=MISDN_CLEANING;
2523 if (bc->need_disconnect)
2524 misdn_lib_send_event(bc, EVENT_DISCONNECT);
2528 p->state=MISDN_CLEANING;
2533 chan_misdn_log(3, bc->port, " --> Channel: %s hanguped new state:%s\n",ast->name,misdn_get_ch_state(p));
2539 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
2541 struct ast_frame *f,*f2;
2544 f2 = ast_translate(tmp->trans, frame, 0);
2545 f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
2547 chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
2552 if (!f || (f->frametype != AST_FRAME_DTMF))
2556 ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c\n", f->subclass);
2558 if (tmp->faxdetect && (f->subclass == 'f')) {
2559 /* Fax tone -- Handle and return NULL */
2560 if (!tmp->faxhandled) {
2561 struct ast_channel *ast = tmp->ast;
2563 chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast->name);
2564 tmp->bc->rxgain = 0;
2565 isdn_lib_update_rxgain(tmp->bc);
2566 tmp->bc->txgain = 0;
2567 isdn_lib_update_txgain(tmp->bc);
2569 *tmp->bc->pipeline = 0;
2571 tmp->bc->ec_enable = 0;
2573 isdn_lib_update_ec(tmp->bc);
2574 isdn_lib_stop_dtmf(tmp->bc);
2575 switch (tmp->faxdetect) {
2577 if (strcmp(ast->exten, "fax")) {
2579 char context_tmp[BUFFERSIZE];
2580 misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
2581 context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp;
2582 if (ast_exists_extension(ast, context, "fax", 1, ast->cid.cid_num)) {
2583 if (option_verbose > 2)
2584 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
2585 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
2586 pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
2587 if (ast_async_goto(ast, context, "fax", 1))
2588 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
2590 ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten);
2593 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
2597 ast_verbose(VERBOSE_PREFIX_3 "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
2602 ast_log(LOG_DEBUG, "Fax already handled\n");
2606 if (tmp->ast_dsp && (f->subclass != 'f')) {
2607 chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass);
2614 static struct ast_frame *misdn_read(struct ast_channel *ast)
2616 struct chan_list *tmp;
2620 chan_misdn_log(1,0,"misdn_read called without ast\n");
2623 if (!(tmp=MISDN_ASTERISK_TECH_PVT(ast))) {
2624 chan_misdn_log(1,0,"misdn_read called without ast->pvt\n");
2628 if (!tmp->bc && !(tmp->state==MISDN_HOLDED)) {
2629 chan_misdn_log(1,0,"misdn_read called without bc\n");
2633 len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
2636 /* we hangup here, since our pipe is closed */
2637 chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
2641 tmp->frame.frametype = AST_FRAME_VOICE;
2642 tmp->frame.subclass = AST_FORMAT_ALAW;
2643 tmp->frame.datalen = len;
2644 tmp->frame.samples = len;
2645 tmp->frame.mallocd = 0;
2646 tmp->frame.offset = 0;
2647 tmp->frame.delivery= ast_tv(0,0) ;
2648 tmp->frame.src = NULL;
2649 tmp->frame.data = tmp->ast_rd_buf;
2651 if (tmp->faxdetect && !tmp->faxhandled) {
2652 if (tmp->faxdetect_timeout) {
2653 if (ast_tvzero(tmp->faxdetect_tv)) {
2654 tmp->faxdetect_tv = ast_tvnow();
2655 chan_misdn_log(2,tmp->bc->port,"faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
2656 return process_ast_dsp(tmp, &tmp->frame);
2658 struct timeval tv_now = ast_tvnow();
2659 int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
2660 if (diff <= (tmp->faxdetect_timeout * 1000)) {
2661 chan_misdn_log(5,tmp->bc->port,"faxdetect: detecting ...\n");
2662 return process_ast_dsp(tmp, &tmp->frame);
2664 chan_misdn_log(2,tmp->bc->port,"faxdetect: stopping detection (time ran out) ...\n");
2670 chan_misdn_log(5,tmp->bc->port,"faxdetect: detecting ... (no timeout)\n");
2671 return process_ast_dsp(tmp, &tmp->frame);
2675 return process_ast_dsp(tmp, &tmp->frame);
2682 static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
2684 struct chan_list *ch;
2687 if (!ast || ! (ch=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
2689 if (ch->state == MISDN_HOLDED) {
2690 chan_misdn_log(7, 0, "misdn_write: Returning because holded\n");
2695 ast_log(LOG_WARNING, "private but no bc\n");
2700 chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxone\n");
2705 if ( !frame->subclass) {
2706 chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
2710 if ( !(frame->subclass & prefformat)) {
2712 chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
2717 if ( !frame->samples ) {
2718 chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
2720 if (!strcmp(frame->src,"ast_prod")) {
2721 chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
2724 chan_misdn_log(4,ch->bc->port,"Starting Playtones\n");
2725 misdn_lib_tone_generator_start(ch->bc);
2733 if ( ! ch->bc->addr ) {
2734 chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
2740 int i, max=5>frame->samples?frame->samples:5;
2742 printf("write2mISDN %p %d bytes: ", p, frame->samples);
2744 for (i=0; i< max ; i++) printf("%2.2x ",((char*) frame->data)[i]);
2750 switch (ch->bc->bc_state) {
2751 case BCHAN_ACTIVATED:
2755 if (!ch->dropped_frame_cnt)
2756 chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n",frame->samples,ch->bc->addr, ast->exten, ast->cid.cid_num,misdn_get_ch_state( ch), ch->bc->bc_state, ch->bc->l3_id);
2758 ch->dropped_frame_cnt++;
2759 if (ch->dropped_frame_cnt > 100) {
2760 ch->dropped_frame_cnt=0;
2761 chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x dropped > 100 frames!\n",frame->samples,ch->bc->addr);
2768 chan_misdn_log(9, ch->bc->port, "Sending :%d bytes 2 MISDN\n",frame->samples);
2769 if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
2770 /* Buffered Transmit (triggert by read from isdn side)*/
2771 if (misdn_jb_fill(ch->jb,frame->data,frame->samples) < 0) {
2773 cb_log(0,ch->bc->port,"Misdn Jitterbuffer Overflow.\n");
2777 /*transmit without jitterbuffer*/
2778 i=misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples);
2789 static enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
2790 struct ast_channel *c1, int flags,
2791 struct ast_frame **fo,
2792 struct ast_channel **rc,
2796 struct chan_list *ch1,*ch2;
2797 struct ast_channel *carr[2], *who;
2799 struct ast_frame *f;
2801 ch1=get_chan_by_ast(c0);
2802 ch2=get_chan_by_ast(c1);
2812 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
2814 /* trying to make a mISDN_dsp conference */
2815 chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid +1);
2816 misdn_lib_bridge(ch1->bc,ch2->bc);
2819 if (option_verbose > 2)
2820 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
2822 chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
2824 if (! (flags&AST_BRIDGE_DTMF_CHANNEL_0) )
2827 if (! (flags&AST_BRIDGE_DTMF_CHANNEL_1) )
2832 who = ast_waitfor_n(carr, 2, &to);
2835 ast_log(LOG_NOTICE,"misdn_bridge: empty read, breaking out\n");
2840 if (!f || f->frametype == AST_FRAME_CONTROL) {
2844 chan_misdn_log(4,ch1->bc->port,"Read Null Frame\n");
2846 chan_misdn_log(4,ch1->bc->port,"Read Frame Controll class:%d\n",f->subclass);
2854 if ( f->frametype == AST_FRAME_DTMF ) {
2855 chan_misdn_log(1,0,"Read DTMF %d from %s\n",f->subclass, who->exten);
2863 if (f->frametype == AST_FRAME_VOICE) {
2864 chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
2879 chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
2881 misdn_lib_split_bridge(ch1->bc,ch2->bc);
2884 return AST_BRIDGE_COMPLETE;
2887 /** AST INDICATIONS END **/
2889 static int dialtone_indicate(struct chan_list *cl)
2891 const struct ind_tone_zone_sound *ts= NULL;
2892 struct ast_channel *ast=cl->ast;
2895 chan_misdn_log(0,cl->bc->port,"No Ast in dialtone_indicate\n");
2900 misdn_cfg_get( cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
2903 chan_misdn_log(1,cl->bc->port,"Not sending Dialtone, because config wants it\n");
2907 chan_misdn_log(3,cl->bc->port," --> Dial\n");
2908 ts=ast_get_indication_tone(ast->zone,"dial");
2914 /* This prods us in misdn_write */
2915 ast_playtones_start(ast,0, ts->data, 0);
2921 static int hanguptone_indicate(struct chan_list *cl)
2923 misdn_lib_send_tone(cl->bc,TONE_HANGUP);
2927 static int stop_indicate(struct chan_list *cl)
2929 struct ast_channel *ast=cl->ast;
2932 chan_misdn_log(0,cl->bc->port,"No Ast in stop_indicate\n");
2936 chan_misdn_log(3,cl->bc->port," --> None\n");
2937 misdn_lib_tone_generator_stop(cl->bc);
2938 ast_playtones_stop(ast);
2939 /*ast_deactivate_generator(ast);*/
2945 static int start_bc_tones(struct chan_list* cl)
2947 misdn_lib_tone_generator_stop(cl->bc);
2953 static int stop_bc_tones(struct chan_list *cl)
2964 static struct chan_list *init_chan_list(int orig)
2966 struct chan_list *cl=malloc(sizeof(struct chan_list));
2969 chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
2973 memset(cl,0,sizeof(struct chan_list));
2975 cl->originator=orig;
2976 cl->need_queue_hangup=1;
2979 cl->overlap_dial_task=-1;
2985 static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
2988 struct ast_channel *tmp = NULL;
2989 char group[BUFFERSIZE+1]="";
2991 char buf2[128], *ext=NULL, *port_str;
2992 char *tokb=NULL, *p=NULL;
2993 int channel=0, port=0;
2994 struct misdn_bchannel *newbc = NULL;
2997 struct chan_list *cl=init_chan_list(ORG_AST);
2999 sprintf(buf,"%s/%s",misdn_type,(char*)data);
3000 ast_copy_string(buf2,data, 128);
3002 port_str=strtok_r(buf2,"/", &tokb);
3004 ext=strtok_r(NULL,"/", &tokb);
3007 if (port_str[0]=='g' && port_str[1]==':' ) {
3008 /* We make a group call lets checkout which ports are in my group */
3010 strncpy(group, port_str, BUFFERSIZE);
3012 chan_misdn_log(2, 0, " --> Group Call group: %s\n",group);
3014 else if ((p = strchr(port_str, ':'))) {
3015 /* we have a preselected channel */
3017 channel = atoi(++p);
3018 port = atoi(port_str);
3019 chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
3022 port = atoi(port_str);
3025 ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extension.conf\n",ext);
3029 if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
3030 chan_misdn_log(4, port, " --> STARTING STANDARDDEC...\n");
3034 if (!ast_strlen_zero(group)) {
3036 char cfg_group[BUFFERSIZE+1];
3037 struct robin_list *rr = NULL;
3039 if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
3040 chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
3041 rr = get_robin_position(group);
3046 int robin_channel = rr->channel;
3052 for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start;
3053 port = misdn_cfg_get_next_port_spin(port)) {
3058 if (port >= port_start)
3061 if (port <= port_start && next_chan) {
3062 int maxbchans=misdn_lib_get_maxchans(port);
3063 if (++robin_channel >= maxbchans) {
3069 misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
3071 if (!strcasecmp(cfg_group, group)) {
3074 misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
3075 port_up = misdn_lib_port_up(port, check);
3077 if (check && !port_up)
3078 chan_misdn_log(1,port,"L1 is not Up on this Port\n");
3080 if (check && port_up<0) {
3081 ast_log(LOG_WARNING,"This port (%d) is blocked\n", port);
3086 newbc = misdn_lib_get_free_bc(port, robin_channel,0, 0);
3088 chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
3090 chan_misdn_log(4, port, "portup:%d\n", port_up);
3091 rr->port = newbc->port;
3092 rr->channel = newbc->channel;
3098 } while (!newbc && robin_channel != rr->channel);
3101 for (port=misdn_cfg_get_next_port(0); port > 0;
3102 port=misdn_cfg_get_next_port(port)) {
3104 misdn_cfg_get( port, MISDN_CFG_GROUPNA