2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2004 - 2006, Christian Richter
6 * Christian Richter <crich@beronet.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
23 * \brief the chan_misdn channel driver for Asterisk
24 * \author Christian Richter <crich@beronet.com>
26 * \ingroup channel_drivers
30 <depend>isdnnet</depend>
31 <depend>misdn</depend>
32 <depend>suppserv</depend>
36 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
41 #include <sys/socket.h>
46 #include <arpa/inet.h>
48 #include <sys/ioctl.h>
51 #include <semaphore.h>
53 #include "asterisk/channel.h"
54 #include "asterisk/config.h"
55 #include "asterisk/logger.h"
56 #include "asterisk/module.h"
57 #include "asterisk/pbx.h"
58 #include "asterisk/options.h"
59 #include "asterisk/io.h"
60 #include "asterisk/frame.h"
61 #include "asterisk/translate.h"
62 #include "asterisk/cli.h"
63 #include "asterisk/musiconhold.h"
64 #include "asterisk/dsp.h"
65 #include "asterisk/translate.h"
66 #include "asterisk/config.h"
67 #include "asterisk/file.h"
68 #include "asterisk/callerid.h"
69 #include "asterisk/indications.h"
70 #include "asterisk/app.h"
71 #include "asterisk/features.h"
72 #include "asterisk/term.h"
73 #include "asterisk/sched.h"
74 #include "asterisk/stringfields.h"
76 #include "chan_misdn_config.h"
79 char global_tracefile[BUFFERSIZE+1];
81 static int g_config_initialized=0;
97 /* allocates the jb-structure and initialise the elements*/
98 struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
100 /* frees the data and destroys the given jitterbuffer struct */
101 void misdn_jb_destroy(struct misdn_jb *jb);
103 /* fills the jitterbuffer with len data returns < 0 if there was an
104 error (bufferoverun). */
105 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);
107 /* gets len bytes out of the jitterbuffer if available, else only the
108 available data is returned and the return value indicates the number
110 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len);
113 enum misdn_chan_state {
114 MISDN_NOTHING=0, /*!< at beginning */
115 MISDN_WAITING4DIGS, /*!< when waiting for infos */
116 MISDN_EXTCANTMATCH, /*!< when asterisk couldnt match our ext */
117 MISDN_DIALING, /*!< when pbx_start */
118 MISDN_PROGRESS, /*!< we got a progress */
119 MISDN_PROCEEDING, /*!< we got a progress */
120 MISDN_CALLING, /*!< when misdn_call is called */
121 MISDN_CALLING_ACKNOWLEDGE, /*!< when we get SETUP_ACK */
122 MISDN_ALERTING, /*!< when Alerting */
123 MISDN_BUSY, /*!< when BUSY */
124 MISDN_CONNECTED, /*!< when connected */
125 MISDN_PRECONNECTED, /*!< when connected */
126 MISDN_DISCONNECTED, /*!< when connected */
127 MISDN_RELEASED, /*!< when connected */
128 MISDN_BRIDGED, /*!< when bridged */
129 MISDN_CLEANING, /*!< when hangup from * but we were connected before */
130 MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP cam from misdn */
131 MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of */
133 MISDN_HOLDED, /*!< if this chan is holded */
134 MISDN_HOLD_DISCONNECT, /*!< if this chan is holded */
148 char allowed_bearers[BUFFERSIZE+1];
150 enum misdn_chan_state state;
151 int need_queue_hangup;
162 int incoming_early_audio;
167 char ast_rd_buf[4096];
168 struct ast_frame frame;
170 int faxdetect; /* 0:no 1:yes 2:yes+nojump */
171 int faxdetect_timeout;
172 struct timeval faxdetect_tv;
178 int jb_upper_threshold;
182 struct ast_trans_pvt *trans;
184 struct ast_channel * ast;
188 struct misdn_bchannel *bc;
190 struct hold_info hold_info;
195 char context[BUFFERSIZE];
198 int dropped_frame_cnt;
205 struct chan_list *other_ch;
207 const struct ind_tone_zone_sound *ts;
210 int overlap_dial_task;
211 ast_mutex_t overlap_tv_lock;
212 struct timeval overlap_tv;
214 struct chan_list *peer;
215 struct chan_list *next;
216 struct chan_list *prev;
217 struct chan_list *first;
222 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
223 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
229 struct robin_list *next;
230 struct robin_list *prev;
232 static struct robin_list *robin = NULL;
236 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
240 static inline void free_robin_list_r (struct robin_list *r)
243 if (r->next) free_robin_list_r(r->next);
244 if (r->group) free(r->group);
249 static void free_robin_list ( void )
251 free_robin_list_r(robin);
255 static struct robin_list* get_robin_position (char *group)
257 struct robin_list *iter = robin;
258 for (; iter; iter = iter->next) {
259 if (!strcasecmp(iter->group, group))
262 struct robin_list *new = (struct robin_list *)calloc(1, sizeof(struct robin_list));
263 new->group = strndup(group, strlen(group));
274 /* the main schedule context for stuff like l1 watcher, overlap dial, ... */
275 static struct sched_context *misdn_tasks = NULL;
276 static pthread_t misdn_tasks_thread;
278 static int *misdn_ports;
280 static void chan_misdn_log(int level, int port, char *tmpl, ...);
282 static struct ast_channel *misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, int format, int port, int c);
283 static void send_digit_to_chan(struct chan_list *cl, char digit );
285 static void hangup_chan(struct chan_list *ch);
286 static int pbx_start_chan(struct chan_list *ch);
289 #define AST_CID_P(ast) ast->cid.cid_num
290 #define AST_BRIDGED_P(ast) ast_bridged_channel(ast)
291 #define AST_LOAD_CFG ast_config_load
292 #define AST_DESTROY_CFG ast_config_destroy
294 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
295 #define MISDN_ASTERISK_PVT(ast) 1
297 #include <asterisk/strings.h>
299 /* #define MISDN_DEBUG 1 */
301 static const char misdn_type[] = "mISDN";
303 static int tracing = 0 ;
305 static char **misdn_key_vector=NULL;
306 static int misdn_key_vector_size=0;
308 /* Only alaw and mulaw is allowed for now */
309 static int prefformat = AST_FORMAT_ALAW ; /* AST_FORMAT_SLINEAR ; AST_FORMAT_ULAW | */
311 static int *misdn_debug;
312 static int *misdn_debug_only;
313 static int max_ports;
315 static int *misdn_in_calls;
316 static int *misdn_out_calls;
319 struct chan_list dummy_cl;
321 struct chan_list *cl_te=NULL;
322 ast_mutex_t cl_te_lock;
324 static enum event_response_e
325 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
327 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch);
329 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan);
330 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);
331 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);
332 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid);
336 static int dialtone_indicate(struct chan_list *cl);
337 static int hanguptone_indicate(struct chan_list *cl);
338 static int stop_indicate(struct chan_list *cl);
340 static int start_bc_tones(struct chan_list *cl);
341 static int stop_bc_tones(struct chan_list *cl);
342 static void release_chan(struct misdn_bchannel *bc);
344 static int misdn_set_opt_exec(struct ast_channel *chan, void *data);
345 static int misdn_facility_exec(struct ast_channel *chan, void *data);
347 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
350 void debug_numplan(int port, int numplan, char *type);
353 int add_out_calls(int port);
354 int add_in_calls(int port);
357 static int update_ec_config(struct misdn_bchannel *bc);
364 int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len);
366 /*************** Helpers *****************/
368 static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
370 struct chan_list *tmp;
372 for (tmp=cl_te; tmp; tmp = tmp->next) {
373 if ( tmp->ast == ast ) return tmp;
379 static struct chan_list * get_chan_by_ast_name(char *name)
381 struct chan_list *tmp;
383 for (tmp=cl_te; tmp; tmp = tmp->next) {
384 if ( tmp->ast && strcmp(tmp->ast->name,name) == 0) return tmp;
392 struct allowed_bearers {
398 struct allowed_bearers allowed_bearers_array[]={
399 {INFO_CAPABILITY_SPEECH,1,"speech"},
400 {INFO_CAPABILITY_AUDIO_3_1K,2,"3_1khz"},
401 {INFO_CAPABILITY_DIGITAL_UNRESTRICTED,4,"digital_unrestricted"},
402 {INFO_CAPABILITY_DIGITAL_RESTRICTED,8,"digital_restriced"},
403 {INFO_CAPABILITY_VIDEO,16,"video"}
406 static char *bearer2str(int cap) {
407 static char *bearers[]={
417 case INFO_CAPABILITY_SPEECH:
420 case INFO_CAPABILITY_AUDIO_3_1K:
423 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
426 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
429 case INFO_CAPABILITY_VIDEO:
439 static void print_facility(struct FacParm *fac, struct misdn_bchannel *bc)
441 switch (fac->Function) {
443 chan_misdn_log(0,bc->port," --> calldeflect to: %s, screened: %s\n", fac->u.CDeflection.DeflectedToNumber,
444 fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
446 case Fac_AOCDCurrency:
447 if (fac->u.AOCDcur.chargeNotAvailable)
448 chan_misdn_log(0,bc->port," --> AOCD currency: charge not available\n");
449 else if (fac->u.AOCDcur.freeOfCharge)
450 chan_misdn_log(0,bc->port," --> AOCD currency: free of charge\n");
451 else if (fac->u.AOCDchu.billingId >= 0)
452 chan_misdn_log(0,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d billingId:%d\n",
453 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
454 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
456 chan_misdn_log(0,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d\n",
457 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
458 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
460 case Fac_AOCDChargingUnit:
461 if (fac->u.AOCDchu.chargeNotAvailable)
462 chan_misdn_log(0,bc->port," --> AOCD charging unit: charge not available\n");
463 else if (fac->u.AOCDchu.freeOfCharge)
464 chan_misdn_log(0,bc->port," --> AOCD charging unit: free of charge\n");
465 else if (fac->u.AOCDchu.billingId >= 0)
466 chan_misdn_log(0,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
467 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
469 chan_misdn_log(0,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
470 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
473 chan_misdn_log(0,bc->port," --> unknown\n");
477 static void print_bearer(struct misdn_bchannel *bc)
480 chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
483 case INFO_CODEC_ALAW:
484 chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
486 case INFO_CODEC_ULAW:
487 chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
491 /*************** Helpers END *************/
493 static void sighandler(int sig)
496 static void* misdn_tasks_thread_func (void *data)
501 sa.sa_handler = sighandler;
502 sa.sa_flags = SA_NODEFER;
503 sigemptyset(&sa.sa_mask);
504 sigaddset(&sa.sa_mask, SIGUSR1);
505 sigaction(SIGUSR1, &sa, NULL);
507 sem_post((sem_t *)data);
510 wait = ast_sched_wait(misdn_tasks);
513 if (poll(NULL, 0, wait) < 0)
514 chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
515 ast_sched_runq(misdn_tasks);
520 static void misdn_tasks_init (void)
525 if (sem_init(&blocker, 0, 0)) {
526 perror("chan_misdn: Failed to initialize semaphore!");
530 chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
532 misdn_tasks = sched_context_create();
533 pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker);
535 while (sem_wait(&blocker) && --i);
536 sem_destroy(&blocker);
539 static void misdn_tasks_destroy (void)
542 chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
543 if ( pthread_cancel(misdn_tasks_thread) == 0 ) {
544 cb_log(4, 0, "Joining misdn_tasks thread\n");
545 pthread_join(misdn_tasks_thread, NULL);
547 sched_context_destroy(misdn_tasks);
551 static inline void misdn_tasks_wakeup (void)
553 pthread_kill(misdn_tasks_thread, SIGUSR1);
556 static inline int _misdn_tasks_add_variable (int timeout, ast_sched_cb callback, void *data, int variable)
563 task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
564 misdn_tasks_wakeup();
569 static int misdn_tasks_add (int timeout, ast_sched_cb callback, void *data)
571 return _misdn_tasks_add_variable(timeout, callback, data, 0);
574 static int misdn_tasks_add_variable (int timeout, ast_sched_cb callback, void *data)
576 return _misdn_tasks_add_variable(timeout, callback, data, 1);
579 static void misdn_tasks_remove (int task_id)
581 ast_sched_del(misdn_tasks, task_id);
584 static int misdn_l1_task (void *data)
586 misdn_lib_isdn_l1watcher(*(int *)data);
587 chan_misdn_log(5, *(int *)data, "L1watcher timeout\n");
591 static int misdn_overlap_dial_task (void *data)
593 struct timeval tv_end, tv_now;
595 struct chan_list *ch = (struct chan_list *)data;
597 chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state);
599 if (ch->state != MISDN_WAITING4DIGS) {
600 ch->overlap_dial_task = -1;
604 ast_mutex_lock(&ch->overlap_tv_lock);
605 tv_end = ch->overlap_tv;
606 ast_mutex_unlock(&ch->overlap_tv_lock);
608 tv_end.tv_sec += ch->overlap_dial;
609 tv_now = ast_tvnow();
611 diff = ast_tvdiff_ms(tv_end, tv_now);
614 /* if we are 100ms near the timeout, we are satisfied.. */
616 if (ast_exists_extension(ch->ast, ch->context, ch->bc->dad, 1, ch->bc->oad)) {
617 ch->state=MISDN_DIALING;
618 if (pbx_start_chan(ch) < 0) {
619 chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
620 goto misdn_overlap_dial_task_disconnect;
623 misdn_overlap_dial_task_disconnect:
624 hanguptone_indicate(ch);
626 misdn_lib_send_event(ch->bc, EVENT_RELEASE_COMPLETE );
628 misdn_lib_send_event(ch->bc, EVENT_RELEASE);
630 ch->overlap_dial_task = -1;
636 static void send_digit_to_chan(struct chan_list *cl, char digit )
638 static const char* dtmf_tones[] = {
639 "!941+1336/100,!0/100", /* 0 */
640 "!697+1209/100,!0/100", /* 1 */
641 "!697+1336/100,!0/100", /* 2 */
642 "!697+1477/100,!0/100", /* 3 */
643 "!770+1209/100,!0/100", /* 4 */
644 "!770+1336/100,!0/100", /* 5 */
645 "!770+1477/100,!0/100", /* 6 */
646 "!852+1209/100,!0/100", /* 7 */
647 "!852+1336/100,!0/100", /* 8 */
648 "!852+1477/100,!0/100", /* 9 */
649 "!697+1633/100,!0/100", /* A */
650 "!770+1633/100,!0/100", /* B */
651 "!852+1633/100,!0/100", /* C */
652 "!941+1633/100,!0/100", /* D */
653 "!941+1209/100,!0/100", /* * */
654 "!941+1477/100,!0/100" }; /* # */
655 struct ast_channel *chan=cl->ast;
657 if (digit >= '0' && digit <='9')
658 ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
659 else if (digit >= 'A' && digit <= 'D')
660 ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
661 else if (digit == '*')
662 ast_playtones_start(chan,0,dtmf_tones[14], 0);
663 else if (digit == '#')
664 ast_playtones_start(chan,0,dtmf_tones[15], 0);
668 ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
671 /*** CLI HANDLING ***/
672 static int misdn_set_debug(int fd, int argc, char *argv[])
674 if (argc != 4 && argc != 5 && argc != 6 && argc != 7)
675 return RESULT_SHOWUSAGE;
677 int level = atoi(argv[3]);
684 if (strncasecmp(argv[4], "only", strlen(argv[4])))
685 return RESULT_SHOWUSAGE;
690 for (i=0; i<=max_ports; i++) {
691 misdn_debug[i] = level;
692 misdn_debug_only[i] = only;
694 ast_cli(fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
699 if (strncasecmp(argv[4], "port", strlen(argv[4])))
700 return RESULT_SHOWUSAGE;
701 int port = atoi(argv[5]);
702 if (port <= 0 || port > max_ports) {
705 ast_cli(fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
708 ast_cli(fd, "port number not valid! only port 1 is availble.\n");
711 ast_cli(fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
716 if (strncasecmp(argv[6], "only", strlen(argv[6])))
717 return RESULT_SHOWUSAGE;
719 misdn_debug_only[port] = 1;
721 misdn_debug_only[port] = 0;
722 misdn_debug[port] = level;
723 ast_cli(fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
729 static int misdn_set_crypt_debug(int fd, int argc, char *argv[])
731 if (argc != 5) return RESULT_SHOWUSAGE;
737 static int misdn_port_block(int fd, int argc, char *argv[])
742 return RESULT_SHOWUSAGE;
744 port = atoi(argv[3]);
746 misdn_lib_port_block(port);
751 static int misdn_port_unblock(int fd, int argc, char *argv[])
756 return RESULT_SHOWUSAGE;
758 port = atoi(argv[3]);
760 misdn_lib_port_unblock(port);
766 static int misdn_restart_port (int fd, int argc, char *argv[])
771 return RESULT_SHOWUSAGE;
773 port = atoi(argv[3]);
775 misdn_lib_port_restart(port);
780 static int misdn_restart_pid (int fd, int argc, char *argv[])
785 return RESULT_SHOWUSAGE;
789 misdn_lib_pid_restart(pid);
794 static int misdn_port_up (int fd, int argc, char *argv[])
799 return RESULT_SHOWUSAGE;
801 port = atoi(argv[3]);
803 misdn_lib_get_port_up(port);
808 static int misdn_port_down (int fd, int argc, char *argv[])
813 return RESULT_SHOWUSAGE;
815 port = atoi(argv[3]);
817 misdn_lib_get_port_down(port);
822 static inline void show_config_description (int fd, enum misdn_cfg_elements elem)
824 char section[BUFFERSIZE];
825 char name[BUFFERSIZE];
826 char desc[BUFFERSIZE];
827 char def[BUFFERSIZE];
828 char tmp[BUFFERSIZE];
830 misdn_cfg_get_name(elem, tmp, sizeof(tmp));
831 term_color(name, tmp, COLOR_BRWHITE, 0, sizeof(tmp));
832 misdn_cfg_get_desc(elem, desc, sizeof(desc), def, sizeof(def));
834 if (elem < MISDN_CFG_LAST)
835 term_color(section, "PORTS SECTION", COLOR_YELLOW, 0, sizeof(section));
837 term_color(section, "GENERAL SECTION", COLOR_YELLOW, 0, sizeof(section));
840 ast_cli(fd, "[%s] %s (Default: %s)\n\t%s\n", section, name, def, desc);
842 ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc);
845 static int misdn_show_config (int fd, int argc, char *argv[])
847 char buffer[BUFFERSIZE];
848 enum misdn_cfg_elements elem;
854 if (!strcmp(argv[3], "description")) {
856 enum misdn_cfg_elements elem = misdn_cfg_get_elem (argv[4]);
857 if (elem == MISDN_CFG_FIRST)
858 ast_cli(fd, "Unknown element: %s\n", argv[4]);
860 show_config_description(fd, elem);
863 return RESULT_SHOWUSAGE;
865 if (!strcmp(argv[3], "descriptions")) {
866 if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "general"))) {
867 for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
868 show_config_description(fd, elem);
873 if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "ports"))) {
874 for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST - 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem) {
875 show_config_description(fd, elem);
880 return ok ? 0 : RESULT_SHOWUSAGE;
882 if (!sscanf(argv[3], "%d", &onlyport) || onlyport < 0) {
883 ast_cli(fd, "Unknown option: %s\n", argv[3]);
884 return RESULT_SHOWUSAGE;
888 if (argc == 3 || onlyport == 0) {
889 ast_cli(fd,"Misdn General-Config: \n");
890 for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
891 misdn_cfg_get_config_string( 0, elem, buffer, BUFFERSIZE);
892 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
898 int port = misdn_cfg_get_next_port(0);
899 for (; port > 0; port = misdn_cfg_get_next_port(port)) {
900 ast_cli(fd, "\n[PORT %d]\n", port);
901 for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
902 misdn_cfg_get_config_string( port, elem, buffer, BUFFERSIZE);
903 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
910 if (misdn_cfg_is_port_valid(onlyport)) {
911 ast_cli(fd, "[PORT %d]\n", onlyport);
912 for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
913 misdn_cfg_get_config_string(onlyport, elem, buffer, BUFFERSIZE);
914 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
918 ast_cli(fd, "Port %d is not active!\n", onlyport);
924 struct state_struct {
925 enum misdn_chan_state state;
929 static struct state_struct state_array[] = {
930 {MISDN_NOTHING,"NOTHING"}, /* at beginning */
931 {MISDN_WAITING4DIGS,"WAITING4DIGS"}, /* when waiting for infos */
932 {MISDN_EXTCANTMATCH,"EXTCANTMATCH"}, /* when asterisk couldnt match our ext */
933 {MISDN_DIALING,"DIALING"}, /* when pbx_start */
934 {MISDN_PROGRESS,"PROGRESS"}, /* when pbx_start */
935 {MISDN_PROCEEDING,"PROCEEDING"}, /* when pbx_start */
936 {MISDN_CALLING,"CALLING"}, /* when misdn_call is called */
937 {MISDN_CALLING_ACKNOWLEDGE,"CALLING_ACKNOWLEDGE"}, /* when misdn_call is called */
938 {MISDN_ALERTING,"ALERTING"}, /* when Alerting */
939 {MISDN_BUSY,"BUSY"}, /* when BUSY */
940 {MISDN_CONNECTED,"CONNECTED"}, /* when connected */
941 {MISDN_PRECONNECTED,"PRECONNECTED"}, /* when connected */
942 {MISDN_DISCONNECTED,"DISCONNECTED"}, /* when connected */
943 {MISDN_RELEASED,"RELEASED"}, /* when connected */
944 {MISDN_BRIDGED,"BRIDGED"}, /* when bridged */
945 {MISDN_CLEANING,"CLEANING"}, /* when hangup from * but we were connected before */
946 {MISDN_HUNGUP_FROM_MISDN,"HUNGUP_FROM_MISDN"}, /* when DISCONNECT/RELEASE/REL_COMP cam from misdn */
947 {MISDN_HOLDED,"HOLDED"}, /* when DISCONNECT/RELEASE/REL_COMP cam from misdn */
948 {MISDN_HOLD_DISCONNECT,"HOLD_DISCONNECT"}, /* when DISCONNECT/RELEASE/REL_COMP cam from misdn */
949 {MISDN_HUNGUP_FROM_AST,"HUNGUP_FROM_AST"} /* when DISCONNECT/RELEASE/REL_COMP came out of */
953 static char *misdn_get_ch_state(struct chan_list *p)
956 static char state[8];
960 for (i=0; i< sizeof(state_array)/sizeof(struct state_struct); i++) {
961 if ( state_array[i].state == p->state) return state_array[i].txt;
964 sprintf(state,"%d",p->state) ;
971 static void reload_config(void)
975 if (!g_config_initialized) {
976 ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
982 misdn_cfg_update_ptp();
983 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
984 misdn_cfg_get( 0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(int));
986 for (i = 0; i <= max_ports; i++) {
987 misdn_debug[i] = cfg_debug;
988 misdn_debug_only[i] = 0;
992 static int misdn_reload (int fd, int argc, char *argv[])
994 ast_cli(fd, "Reloading mISDN Config\n");
999 static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel* bc)
1001 struct ast_channel *ast=help->ast;
1003 "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
1005 bc->pid, bc->port, bc->channel,
1007 help->orginator == ORG_AST?"*":"I",
1008 ast?ast->exten:NULL,
1009 ast?AST_CID_P(ast):NULL,
1011 ast?ast->context:NULL,
1012 misdn_get_ch_state(help)
1014 if (misdn_debug[bc->port] > 0)
1016 " --> astname: %s\n"
1017 " --> ch_l3id: %x\n"
1018 " --> ch_addr: %x\n"
1019 " --> bc_addr: %x\n"
1020 " --> bc_l3id: %x\n"
1021 " --> display: %s\n"
1022 " --> activated: %d\n"
1024 " --> capability: %s\n"
1025 " --> echo_cancel: %d\n"
1026 " --> notone : rx %d tx:%d\n"
1027 " --> bc_hold: %d\n",
1036 bc_state2str(bc->bc_state),
1037 bearer2str(bc->capability),
1040 help->norxtone,help->notxtone,
1046 static int misdn_show_cls (int fd, int argc, char *argv[])
1048 struct chan_list *help=cl_te;
1050 ast_cli(fd,"Chan List: %p\n",cl_te);
1052 for (;help; help=help->next) {
1053 struct misdn_bchannel *bc=help->bc;
1054 struct ast_channel *ast=help->ast;
1055 if (misdn_debug[0] > 2) ast_cli(fd, "Bc:%p Ast:%p\n", bc, ast);
1057 print_bc_info(fd, help, bc);
1059 if (help->state == MISDN_HOLDED) {
1060 chan_misdn_log(2, 0, "ITS A HOLDED BC:\n");
1061 chan_misdn_log(2,0," --> l3_id: %x\n"
1062 " --> dad:%s oad:%s\n"
1063 " --> hold_port: %d\n"
1064 " --> hold_channel: %d\n"
1069 ,help->hold_info.port
1070 ,help->hold_info.channel
1073 ast_cli(fd,"* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, AST_CID_P(ast));
1082 static int misdn_show_cl (int fd, int argc, char *argv[])
1084 struct chan_list *help=cl_te;
1087 return RESULT_SHOWUSAGE;
1089 for (;help; help=help->next) {
1090 struct misdn_bchannel *bc=help->bc;
1091 struct ast_channel *ast=help->ast;
1094 if (!strcasecmp(ast->name,argv[3])) {
1095 print_bc_info(fd, help, bc);
1108 static int misdn_set_tics (int fd, int argc, char *argv[])
1111 return RESULT_SHOWUSAGE;
1113 MAXTICS=atoi(argv[3]);
1118 static int misdn_show_stacks (int fd, int argc, char *argv[])
1122 ast_cli(fd, "BEGIN STACK_LIST:\n");
1124 for (port=misdn_cfg_get_next_port(0); port > 0;
1125 port=misdn_cfg_get_next_port(port)) {
1127 get_show_stack_details(port,buf);
1128 ast_cli(fd," %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
1135 static int misdn_show_ports_stats (int fd, int argc, char *argv[])
1139 ast_cli(fd, "Port\tin_calls\tout_calls\n");
1141 for (port=misdn_cfg_get_next_port(0); port > 0;
1142 port=misdn_cfg_get_next_port(port)) {
1143 ast_cli(fd,"%d\t%d\t\t%d\n",port,misdn_in_calls[port],misdn_out_calls[port]);
1152 static int misdn_show_port (int fd, int argc, char *argv[])
1157 return RESULT_SHOWUSAGE;
1159 port = atoi(argv[3]);
1161 ast_cli(fd, "BEGIN STACK_LIST:\n");
1164 get_show_stack_details(port,buf);
1165 ast_cli(fd," %s Debug:%d%s\n",buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
1171 static int misdn_send_cd (int fd, int argc, char *argv[])
1177 return RESULT_SHOWUSAGE;
1182 ast_cli(fd, "Sending Calldeflection (%s) to %s\n",nr, channame);
1185 struct chan_list *tmp=get_chan_by_ast_name(channame);
1188 ast_cli(fd, "Sending CD with nr %s to %s failed: Channel does not exist.\n",nr, channame);
1191 if (strlen(nr) >= 15) {
1192 ast_cli(fd, "Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n",nr, channame);
1195 tmp->bc->fac_out.Function = Fac_CD;
1196 strncpy((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber));
1197 misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
1204 static int misdn_send_digit (int fd, int argc, char *argv[])
1210 return RESULT_SHOWUSAGE;
1215 ast_cli(fd, "Sending %s to %s\n",msg, channame);
1218 struct chan_list *tmp=get_chan_by_ast_name(channame);
1221 ast_cli(fd, "Sending %s to %s failed Channel does not exist\n",msg, channame);
1226 int msglen = strlen(msg);
1227 for (i=0; i<msglen; i++) {
1228 ast_cli(fd, "Sending: %c\n",msg[i]);
1229 send_digit_to_chan(tmp, msg[i]);
1230 /* res = ast_safe_sleep(tmp->ast, 250); */
1232 /* res = ast_waitfor(tmp->ast,100); */
1236 res = ast_dtmf_stream(tmp->ast,NULL,msg,250);
1244 static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
1249 return RESULT_SHOWUSAGE;
1253 ast_cli(fd, "Toggling EchoCancel on %s\n", channame);
1256 struct chan_list *tmp=get_chan_by_ast_name(channame);
1259 ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
1263 tmp->toggle_ec=tmp->toggle_ec?0:1;
1265 if (tmp->toggle_ec) {
1266 update_ec_config(tmp->bc);
1267 manager_ec_enable(tmp->bc);
1269 manager_ec_disable(tmp->bc);
1277 static int misdn_send_display (int fd, int argc, char *argv[])
1283 return RESULT_SHOWUSAGE;
1288 ast_cli(fd, "Sending %s to %s\n",msg, channame);
1290 struct chan_list *tmp;
1291 tmp=get_chan_by_ast_name(channame);
1293 if (tmp && tmp->bc) {
1294 ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
1295 misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
1297 ast_cli(fd,"No such channel %s\n",channame);
1298 return RESULT_FAILURE;
1302 return RESULT_SUCCESS ;
1305 static char *complete_ch_helper(const char *line, const char *word, int pos, int state, int rpos)
1307 struct ast_channel *c;
1312 c = ast_channel_walk_locked(NULL);
1314 if (!strncasecmp(word, c->name, strlen(word))) {
1315 if (++which > state)
1318 ast_mutex_unlock(&c->lock);
1319 c = ast_channel_walk_locked(c);
1322 ret = strdup(c->name);
1323 ast_mutex_unlock(&c->lock);
1329 static char *complete_ch(const char *line, const char *word, int pos, int state)
1331 return complete_ch_helper(line, word, pos, state, 3);
1334 static char *complete_debug_port (const char *line, const char *word, int pos, int state)
1340 case 4: if (*word == 'p')
1341 return strdup("port");
1342 else if (*word == 'o')
1343 return strdup("only");
1345 case 6: if (*word == 'o')
1346 return strdup("only");
1352 static char *complete_show_config (const char *line, const char *word, int pos, int state)
1354 char buffer[BUFFERSIZE];
1355 enum misdn_cfg_elements elem;
1356 int wordlen = strlen(word);
1361 case 3: if ((!strncmp(word, "description", wordlen)) && (++which > state))
1362 return strdup("description");
1363 if ((!strncmp(word, "descriptions", wordlen)) && (++which > state))
1364 return strdup("descriptions");
1365 if ((!strncmp(word, "0", wordlen)) && (++which > state))
1367 while ((port = misdn_cfg_get_next_port(port)) != -1) {
1368 snprintf(buffer, sizeof(buffer), "%d", port);
1369 if ((!strncmp(word, buffer, wordlen)) && (++which > state)) {
1370 return strdup(buffer);
1375 if (strstr(line, "description ")) {
1376 for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
1377 if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST))
1379 misdn_cfg_get_name(elem, buffer, BUFFERSIZE);
1380 if (!wordlen || !strncmp(word, buffer, wordlen)) {
1381 if (++which > state)
1382 return strdup(buffer);
1385 } else if (strstr(line, "descriptions ")) {
1386 if ((!wordlen || !strncmp(word, "general", wordlen)) && (++which > state))
1387 return strdup("general");
1388 if ((!wordlen || !strncmp(word, "ports", wordlen)) && (++which > state))
1389 return strdup("ports");
1396 static struct ast_cli_entry chan_misdn_clis[] = {
1397 { {"misdn","send","calldeflect", NULL}, misdn_send_cd, "Sends CallDeflection to mISDN Channel",
1398 "Usage: misdn send calldeflect <channel> \"<nr>\" \n", complete_ch },
1399 { {"misdn","send","digit", NULL}, misdn_send_digit, "Sends DTMF Digit to mISDN Channel",
1400 "Usage: misdn send digit <channel> \"<msg>\" \n"
1401 " Send <digit> to <channel> as DTMF Tone\n"
1402 " when channel is a mISDN channel\n", complete_ch },
1403 { {"misdn","toggle","echocancel", NULL}, misdn_toggle_echocancel, "Toggles EchoCancel on mISDN Channel",
1404 "Usage: misdn toggle echocancel <channel>\n", complete_ch },
1405 { {"misdn","send","display", NULL}, misdn_send_display, "Sends Text to mISDN Channel",
1406 "Usage: misdn send display <channel> \"<msg>\" \n"
1407 " Send <msg> to <channel> as Display Message\n"
1408 " when channel is a mISDN channel\n", complete_ch },
1409 { {"misdn","show","config", NULL}, misdn_show_config, "Shows internal mISDN config, read from cfg-file",
1410 "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
1411 " Use 0 for <port> to only print the general config.\n", complete_show_config },
1412 { {"misdn","reload", NULL}, misdn_reload, "Reloads internal mISDN config, read from cfg-file",
1413 "Usage: misdn reload\n" },
1414 { {"misdn","set","tics", NULL}, misdn_set_tics, "",
1416 { {"misdn","show","channels", NULL}, misdn_show_cls, "Shows internal mISDN chan_list",
1417 "Usage: misdn show channels\n" },
1418 { {"misdn","show","channel", NULL}, misdn_show_cl, "Shows internal mISDN chan_list",
1419 "Usage: misdn show channels\n", complete_ch },
1420 { {"misdn","port","block", NULL}, misdn_port_block, "Blocks the given port",
1421 "Usage: misdn port block\n" },
1422 { {"misdn","port","unblock", NULL}, misdn_port_unblock, "Unblocks the given port",
1423 "Usage: misdn port unblock\n" },
1424 { {"misdn","restart","port", NULL}, misdn_restart_port, "Restarts the given port",
1425 "Usage: misdn restart port\n" },
1426 { {"misdn","restart","pid", NULL}, misdn_restart_pid, "Restarts the given pid",
1427 "Usage: misdn restart pid\n" },
1428 { {"misdn","port","up", NULL}, misdn_port_up, "Tries to establish L1 on the given port",
1429 "Usage: misdn port up <port>\n" },
1430 { {"misdn","port","down", NULL}, misdn_port_down, "Tries to deacivate the L1 on the given port",
1431 "Usage: misdn port down <port>\n" },
1432 { {"misdn","show","stacks", NULL}, misdn_show_stacks, "Shows internal mISDN stack_list",
1433 "Usage: misdn show stacks\n" },
1434 { {"misdn","show","ports","stats", NULL}, misdn_show_ports_stats, "Shows chan_misdns call statistics per port",
1435 "Usage: misdn show port stats\n" },
1436 { {"misdn","show","port", NULL}, misdn_show_port, "Shows detailed information for given port",
1437 "Usage: misdn show port <port>\n" },
1438 { {"misdn","set","debug", NULL}, misdn_set_debug, "Sets Debuglevel of chan_misdn",
1439 "Usage: misdn set debug <level> [only] | [port <port> [only]]\n", complete_debug_port },
1440 { {"misdn","set","crypt","debug", NULL}, misdn_set_crypt_debug, "Sets CryptDebuglevel of chan_misdn, at the moment, level={1,2}",
1441 "Usage: misdn set crypt debug <level>\n" }
1444 static int update_config (struct chan_list *ch, int orig)
1447 ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
1451 struct ast_channel *ast=ch->ast;
1452 struct misdn_bchannel *bc=ch->bc;
1453 if (! ast || ! bc ) {
1454 ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
1460 chan_misdn_log(7,port,"update_config: Getting Config\n");
1463 misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
1466 switch (bc->capability) {
1467 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
1468 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
1469 chan_misdn_log(1,bc->port," --> CONF HDLC\n");
1479 misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int));
1480 misdn_cfg_get( port, MISDN_CFG_SCREEN, &screen, sizeof(int));
1481 chan_misdn_log(2,port," --> pres: %d screen: %d\n",pres, screen);
1483 if ( (pres + screen) < 0 ) {
1485 chan_misdn_log(2,port," --> pres: %x\n", ast->cid.cid_pres);
1487 switch (ast->cid.cid_pres & 0x60){
1489 case AST_PRES_RESTRICTED:
1491 chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
1495 case AST_PRES_UNAVAILABLE:
1497 chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
1502 chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
1505 switch (ast->cid.cid_pres & 0x3){
1507 case AST_PRES_USER_NUMBER_UNSCREENED:
1509 chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
1512 case AST_PRES_USER_NUMBER_PASSED_SCREEN:
1514 chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
1516 case AST_PRES_USER_NUMBER_FAILED_SCREEN:
1518 chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
1521 case AST_PRES_NETWORK_NUMBER:
1523 chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
1528 chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
1544 static void config_jitterbuffer(struct chan_list *ch)
1546 struct misdn_bchannel *bc=ch->bc;
1547 int len=ch->jb_len, threshold=ch->jb_upper_threshold;
1549 chan_misdn_log(5,bc->port, "config_jb: Called\n");
1552 chan_misdn_log(1,bc->port, "config_jb: Deactivating Jitterbuffer\n");
1556 if (len <=100 || len > 8000) {
1557 chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
1561 if ( threshold > len ) {
1562 chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
1566 cb_log(0,bc->port,"config_jb: We've got a Jitterbuffer Already on this port.\n");
1567 misdn_jb_destroy(ch->jb);
1571 ch->jb=misdn_jb_init(len, threshold);
1579 void debug_numplan(int port, int numplan, char *type)
1582 case NUMPLAN_INTERNATIONAL:
1583 chan_misdn_log(2, port, " --> %s: International\n",type);
1585 case NUMPLAN_NATIONAL:
1586 chan_misdn_log(2, port, " --> %s: National\n",type);
1588 case NUMPLAN_SUBSCRIBER:
1589 chan_misdn_log(2, port, " --> %s: Subscriber\n",type);
1591 case NUMPLAN_UNKNOWN:
1592 chan_misdn_log(2, port, " --> %s: Unknown\n",type);
1594 /* Maybe we should cut off the prefix if present ? */
1596 chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
1604 static int update_ec_config(struct misdn_bchannel *bc)
1609 misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
1613 } else if ( ec > 1 ) {
1617 #ifdef WITH_ECHOTRAINING
1619 misdn_cfg_get( port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int));
1622 bc->ec_training=ectr;
1630 static int read_config(struct chan_list *ch, int orig) {
1633 ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
1637 struct ast_channel *ast=ch->ast;
1638 struct misdn_bchannel *bc=ch->bc;
1639 if (! ast || ! bc ) {
1640 ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
1646 chan_misdn_log(1,port,"read_config: Getting Config\n");
1648 char lang[BUFFERSIZE+1];
1651 misdn_cfg_get( port, MISDN_CFG_LANGUAGE, lang, BUFFERSIZE);
1652 ast_string_field_set(ast, language, lang);
1654 char localmusicclass[BUFFERSIZE+1];
1656 misdn_cfg_get( port, MISDN_CFG_MUSICCLASS, localmusicclass, BUFFERSIZE);
1657 ast_string_field_set(ast, musicclass, localmusicclass);
1660 misdn_cfg_get( port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(int));
1661 misdn_cfg_get( port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(int));
1663 misdn_cfg_get( port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(int));
1665 misdn_cfg_get( port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(int));
1667 misdn_cfg_get( port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(int));
1668 misdn_cfg_get( port, MISDN_CFG_NTTIMEOUT, &ch->nttimeout, sizeof(int));
1670 misdn_cfg_get( port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(int));
1672 misdn_cfg_get( port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, BUFFERSIZE);
1674 char faxdetect[BUFFERSIZE+1];
1675 misdn_cfg_get( port, MISDN_CFG_FAXDETECT, faxdetect, BUFFERSIZE);
1678 misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
1681 switch (bc->capability) {
1682 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
1683 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
1684 chan_misdn_log(1,bc->port," --> CONF HDLC\n");
1690 /*Initialize new Jitterbuffer*/
1692 misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(int));
1693 misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(int));
1695 config_jitterbuffer(ch);
1698 misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
1700 ast_copy_string (ast->context,ch->context,sizeof(ast->context));
1702 update_ec_config(bc);
1707 misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
1708 bc->early_bconnect=eb3;
1717 misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
1718 misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
1720 chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
1721 ast->pickupgroup=pg;
1725 if ( orig == ORG_AST) {
1726 misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(int));
1728 if (strstr(faxdetect, "outgoing") || strstr(faxdetect, "both")) {
1729 if (strstr(faxdetect, "nojump"))
1736 char callerid[BUFFERSIZE+1];
1737 misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
1738 if ( ! ast_strlen_zero(callerid) ) {
1739 chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
1741 int l = sizeof(bc->oad);
1742 strncpy(bc->oad,callerid, l);
1749 misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(int));
1750 misdn_cfg_get( port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(int));
1751 misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
1752 debug_numplan(port, bc->dnumplan,"TON");
1753 debug_numplan(port, bc->onumplan,"LTON");
1754 debug_numplan(port, bc->cpnnumplan,"CTON");
1757 ch->overlap_dial = 0;
1758 } else { /** ORIGINATOR MISDN **/
1759 if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
1760 if (strstr(faxdetect, "nojump"))
1766 misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
1767 debug_numplan(port, bc->cpnnumplan,"CTON");
1769 char prefix[BUFFERSIZE+1]="";
1770 switch( bc->onumplan ) {
1771 case NUMPLAN_INTERNATIONAL:
1772 misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
1775 case NUMPLAN_NATIONAL:
1776 misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
1783 int l = strlen(prefix) + strlen(bc->oad);
1786 strcat(tmp,bc->oad);
1787 strcpy(bc->oad,tmp);
1790 if (!ast_strlen_zero(bc->dad)) {
1791 ast_copy_string(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
1794 if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
1795 ast_copy_string(bc->dad,bc->keypad, sizeof(bc->dad));
1800 switch( bc->dnumplan ) {
1801 case NUMPLAN_INTERNATIONAL:
1802 misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
1804 case NUMPLAN_NATIONAL:
1805 misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
1812 int l = strlen(prefix) + strlen(bc->dad);
1815 strcat(tmp,bc->dad);
1816 strcpy(bc->dad,tmp);
1819 if ( strcmp(bc->dad,ast->exten)) {
1820 ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
1823 ast_set_callerid(ast, bc->oad, NULL, bc->oad);
1825 if ( !ast_strlen_zero(bc->rad) ) {
1826 if (ast->cid.cid_rdnis)
1827 free(ast->cid.cid_rdnis);
1828 ast->cid.cid_rdnis = strdup(bc->rad);
1831 misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
1832 ast_mutex_init(&ch->overlap_tv_lock);
1833 } /* ORIG MISDN END */
1835 ch->overlap_dial_task = -1;
1837 if (ch->faxdetect) {
1838 misdn_cfg_get( port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
1840 ch->dsp = ast_dsp_new();
1842 ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT | DSP_FEATURE_FAX_DETECT);
1844 ch->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
1847 /* AOCD initialization */
1848 bc->AOCDtype = Fac_None;
1854 /*****************************/
1855 /*** AST Indications Start ***/
1856 /*****************************/
1858 static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
1862 struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
1863 struct misdn_bchannel *newbc;
1864 char *opts=NULL, *ext,*tokb;
1868 strncpy(dest_cp,dest,sizeof(dest_cp)-1);
1869 dest_cp[sizeof(dest_cp)]=0;
1871 ext=strtok_r(dest_cp,"/",&tokb);
1874 ext=strtok_r(NULL,"/",&tokb);
1876 opts=strtok_r(NULL,"/",&tokb);
1878 chan_misdn_log(0,0,"misdn_call: No Extension given!\n");
1885 ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
1889 if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest ) {
1890 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1891 ast->hangupcause=41;
1892 ast_setstate(ast, AST_STATE_DOWN);
1897 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1898 ast->hangupcause=41;
1899 ast_setstate(ast, AST_STATE_DOWN);
1906 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1907 ast->hangupcause=41;
1908 ast_setstate(ast, AST_STATE_DOWN);
1913 strncpy(newbc->dad,ext,sizeof( newbc->dad));
1914 strncpy(ast->exten,ext,sizeof(ast->exten));
1917 if ((exceed=add_out_calls(port))) {
1919 sprintf(tmp,"%d",exceed);
1920 pbx_builtin_setvar_helper(ast,"MAX_OVERFLOW",tmp);
1924 chan_misdn_log(1, port, "* CALL: %s\n",dest);
1926 chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
1928 chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten);
1930 int l = sizeof(newbc->dad);
1931 strncpy(newbc->dad,ast->exten, l);
1932 newbc->dad[l-1] = 0;
1935 chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",AST_CID_P(ast));
1936 if (ast_strlen_zero(newbc->oad) && AST_CID_P(ast) ) {
1938 if (AST_CID_P(ast)) {
1939 int l = sizeof(newbc->oad);
1940 strncpy(newbc->oad,AST_CID_P(ast), l);
1941 newbc->oad[l-1] = 0;
1946 struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
1947 if (!ch) { ast_verbose("No chan_list in misdn_call\n"); return -1;}
1949 newbc->capability=ast->transfercapability;
1950 pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability));
1951 if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
1952 chan_misdn_log(2, port, " --> * Call with flag Digital\n");
1956 /* update screening and presentation */
1957 update_config(ch,ORG_AST);
1959 /* fill in some ies from channel vary*/
1960 import_ch(ast, newbc, ch);
1962 /* Finally The Options Override Everything */
1964 misdn_set_opt_exec(ast,opts);
1966 chan_misdn_log(2,port,"NO OPTS GIVEN\n");
1968 /*check for bridging*/
1970 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
1971 if (bridging && ch->other_ch) {
1972 chan_misdn_log(0, port, "Disabling EC on both Sides\n");
1973 ch->bc->ec_enable=0;
1974 ch->other_ch->bc->ec_enable=0;
1977 r=misdn_lib_send_event( newbc, EVENT_SETUP );
1979 /** we should have l3id after sending setup **/
1980 ch->l3id=newbc->l3_id;
1983 if ( r == -ENOCHAN ) {
1984 chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
1985 chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n",newbc?newbc->pid:-1);
1986 ast->hangupcause=34;
1987 ast_setstate(ast, AST_STATE_DOWN);
1991 chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
1993 ast_setstate(ast, AST_STATE_DIALING);
1994 ast->hangupcause=16;
1996 if (newbc->nt) stop_bc_tones(ch);
1998 ch->state=MISDN_CALLING;
2004 static int misdn_answer(struct ast_channel *ast)
2006 struct chan_list *p;
2009 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
2011 chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n");
2014 ast_log(LOG_WARNING, " --> Channel not connected ??\n");
2015 ast_queue_hangup(ast);
2019 chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n");
2021 ast_queue_hangup(ast);
2025 const char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
2028 chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
2030 int l = sizeof(p->bc->crypt_key);
2031 strncpy(p->bc->crypt_key,tmp_key, l);
2032 p->bc->crypt_key[l-1] = 0;
2035 chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
2041 const char *nodsp=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
2043 chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
2050 p->state = MISDN_CONNECTED;
2053 if ( ast_strlen_zero(p->bc->cad) ) {
2054 chan_misdn_log(2,p->bc->port," --> empty cad using dad\n");
2055 ast_copy_string(p->bc->cad,p->bc->dad,sizeof(p->bc->cad));
2058 misdn_lib_send_event( p->bc, EVENT_CONNECT);
2064 static int misdn_digit_begin(struct ast_channel *chan, char digit)
2066 /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
2070 static int misdn_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
2072 struct chan_list *p;
2074 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) return -1;
2076 struct misdn_bchannel *bc=p->bc;
2077 chan_misdn_log(1, bc?bc->port:0, "* IND : Digit %c\n",digit);
2080 ast_log(LOG_WARNING, " --> !! Got Digit Event withut having bchannel Object\n");
2084 switch (p->state ) {
2092 int l = sizeof(bc->infos_pending);
2093 strncat(bc->infos_pending,buf,l);
2094 bc->infos_pending[l-1] = 0;
2097 case MISDN_CALLING_ACKNOWLEDGE:
2099 bc->info_dad[0]=digit;
2103 int l = sizeof(bc->dad);
2104 strncat(bc->dad,bc->info_dad, l - strlen(bc->dad));
2108 int l = sizeof(p->ast->exten);
2109 strncpy(p->ast->exten, bc->dad, l);
2110 p->ast->exten[l-1] = 0;
2113 misdn_lib_send_event( bc, EVENT_INFORMATION);
2118 if ( bc->send_dtmf ) {
2119 send_digit_to_chan(p,digit);
2128 static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
2130 struct chan_list *p;
2132 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
2134 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);
2143 static int misdn_indication(struct ast_channel *ast, int cond, const void *data, size_t datalen)
2145 struct chan_list *p;
2148 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
2149 ast_log(LOG_WARNING, "Returnded -1 in misdn_indication\n");
2154 chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten);
2155 ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
2159 chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] from %s\n",cond, ast->exten);
2162 case AST_CONTROL_BUSY:
2163 chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n",p->bc?p->bc->pid:-1);
2164 ast_setstate(ast,AST_STATE_BUSY);
2166 p->bc->out_cause=17;
2167 if (p->state != MISDN_CONNECTED) {
2169 misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
2171 chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name);
2175 case AST_CONTROL_RING:
2176 chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
2180 case AST_CONTROL_RINGING:
2181 chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
2183 case MISDN_ALERTING:
2184 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);
2186 case MISDN_CONNECTED:
2187 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);
2191 p->state=MISDN_ALERTING;
2192 chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
2193 misdn_lib_send_event( p->bc, EVENT_ALERTING);
2195 if (p->other_ch && p->other_ch->bc) {
2196 if (misdn_inband_avail(p->other_ch->bc)) {
2197 chan_misdn_log(2,p->bc->port, " --> other End is mISDN and has inband info available\n");
2201 if (!p->other_ch->bc->nt) {
2202 chan_misdn_log(2,p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
2207 chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
2208 ast_setstate(ast,AST_STATE_RINGING);
2210 if ( !p->bc->nt && (p->orginator==ORG_MISDN) && !p->incoming_early_audio )
2211 chan_misdn_log(2,p->bc->port, " --> incoming_early_audio off\n");
2216 case AST_CONTROL_ANSWER:
2217 chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1);
2220 case AST_CONTROL_TAKEOFFHOOK:
2221 chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1);
2224 case AST_CONTROL_OFFHOOK:
2225 chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1);
2228 case AST_CONTROL_FLASH:
2229 chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1);
2231 case AST_CONTROL_PROGRESS:
2232 chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n",p->bc?p->bc->pid:-1);
2233 misdn_lib_send_event( p->bc, EVENT_PROGRESS);
2235 case AST_CONTROL_PROCEEDING:
2236 chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n",p->bc?p->bc->pid:-1);
2237 misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
2239 case AST_CONTROL_CONGESTION:
2240 chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n",p->bc?p->bc->pid:-1);
2242 p->bc->out_cause=42;
2243 if (p->state != MISDN_CONNECTED) {
2245 misdn_lib_send_event( p->bc, EVENT_RELEASE);
2247 misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
2251 hanguptone_indicate(p);
2255 chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n",p->bc?p->bc->pid:-1);
2259 if (p->state == MISDN_CONNECTED)
2264 case AST_CONTROL_HOLD:
2265 chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n",p->bc?p->bc->pid:-1);
2267 case AST_CONTROL_UNHOLD:
2268 chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1);
2271 chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
2277 static int misdn_hangup(struct ast_channel *ast)
2279 struct chan_list *p;
2280 struct misdn_bchannel *bc=NULL;
2283 ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
2285 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
2288 chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
2296 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
2301 if (ast->_state == AST_STATE_RESERVED ||
2302 p->state == MISDN_NOTHING ||
2303 p->state == MISDN_HOLDED ||
2304 p->state == MISDN_HOLD_DISCONNECT ) {
2307 /* between request and call */
2309 ast_log(LOG_DEBUG, "State Reserved (or nothing) => chanIsAvail\n");
2310 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
2312 cl_dequeue_chan(&cl_te, p);
2318 misdn_lib_release(bc);
2324 ast_log(LOG_WARNING,"Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p), p->l3id);
2330 p->need_queue_hangup=0;
2339 const char *varcause=NULL;
2340 bc->out_cause=ast->hangupcause?ast->hangupcause:16;
2342 if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
2343 (varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
2344 int tmpcause=atoi(varcause);
2345 bc->out_cause=tmpcause?tmpcause:16;
2348 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_P(ast), misdn_get_ch_state(p));
2349 chan_misdn_log(3, bc->port, " --> l3id:%x\n",p->l3id);
2350 chan_misdn_log(3, bc->port, " --> cause:%d\n",bc->cause);
2351 chan_misdn_log(2, bc->port, " --> out_cause:%d\n",bc->out_cause);
2352 chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
2356 p->state=MISDN_CLEANING;
2357 misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
2362 hanguptone_indicate(p);
2364 if (bc->need_disconnect)
2365 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2368 case MISDN_CALLING_ACKNOWLEDGE:
2370 hanguptone_indicate(p);
2372 if (bc->need_disconnect)
2373 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2376 case MISDN_ALERTING:
2377 case MISDN_PROGRESS:
2378 case MISDN_PROCEEDING:
2379 if (p->orginator != ORG_AST)
2380 hanguptone_indicate(p);
2382 /*p->state=MISDN_CLEANING;*/
2383 if (bc->need_disconnect)
2384 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2386 case MISDN_CONNECTED:
2387 case MISDN_PRECONNECTED:
2388 /* Alerting or Disconect */
2391 hanguptone_indicate(p);
2392 p->bc->progress_indicator=8;
2394 if (bc->need_disconnect)
2395 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2397 /*p->state=MISDN_CLEANING;*/
2399 case MISDN_DISCONNECTED:
2400 misdn_lib_send_event( bc, EVENT_RELEASE);
2401 p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
2404 case MISDN_RELEASED:
2405 case MISDN_CLEANING:
2406 p->state=MISDN_CLEANING;
2412 case MISDN_HOLD_DISCONNECT:
2413 /* need to send release here */
2414 chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause);
2415 chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause);
2418 misdn_lib_send_event(bc,EVENT_RELEASE);
2419 p->state=MISDN_CLEANING;
2424 misdn_lib_send_event(bc, EVENT_RELEASE);
2425 p->state=MISDN_CLEANING;
2427 if (bc->need_disconnect)
2428 misdn_lib_send_event(bc, EVENT_DISCONNECT);
2432 p->state=MISDN_CLEANING;
2437 chan_misdn_log(3, bc->port, " --> Channel: %s hanguped new state:%s\n",ast->name,misdn_get_ch_state(p));
2443 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
2445 struct ast_frame *f,*f2;
2448 f2 = ast_translate(tmp->trans, frame, 0);
2449 f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
2451 chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
2456 if (!f || (f->frametype != AST_FRAME_DTMF))
2460 ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c\n", f->subclass);
2462 if (tmp->faxdetect && (f->subclass == 'f')) {
2463 /* Fax tone -- Handle and return NULL */
2464 if (!tmp->faxhandled) {
2465 struct ast_channel *ast = tmp->ast;
2467 chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast->name);
2468 tmp->bc->rxgain = 0;
2469 isdn_lib_update_rxgain(tmp->bc);
2470 tmp->bc->txgain = 0;
2471 isdn_lib_update_txgain(tmp->bc);
2472 tmp->bc->ec_enable = 0;
2473 isdn_lib_update_ec(tmp->bc);
2474 isdn_lib_stop_dtmf(tmp->bc);
2475 switch (tmp->faxdetect) {
2477 if (strcmp(ast->exten, "fax")) {
2479 char context_tmp[BUFFERSIZE];
2480 misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
2481 context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp;
2482 if (ast_exists_extension(ast, context, "fax", 1, AST_CID_P(ast))) {
2483 if (option_verbose > 2)
2484 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
2485 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
2486 pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
2487 if (ast_async_goto(ast, context, "fax", 1))
2488 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
2490 ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten);
2493 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
2497 ast_verbose(VERBOSE_PREFIX_3 "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
2502 ast_log(LOG_DEBUG, "Fax already handled\n");
2506 if (tmp->ast_dsp && (f->subclass != 'f')) {
2507 chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass);
2514 static struct ast_frame *misdn_read(struct ast_channel *ast)
2516 struct chan_list *tmp;
2520 chan_misdn_log(1,0,"misdn_read called without ast\n");
2523 if (!(tmp=MISDN_ASTERISK_TECH_PVT(ast))) {
2524 chan_misdn_log(1,0,"misdn_read called without ast->pvt\n");
2528 chan_misdn_log(1,0,"misdn_read called without bc\n");
2532 len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
2535 /* we hangup here, since our pipe is closed */
2536 chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
2540 tmp->frame.frametype = AST_FRAME_VOICE;
2541 tmp->frame.subclass = AST_FORMAT_ALAW;
2542 tmp->frame.datalen = len;
2543 tmp->frame.samples = len;
2544 tmp->frame.mallocd = 0;
2545 tmp->frame.offset = 0;
2546 tmp->frame.delivery= ast_tv(0,0) ;
2547 tmp->frame.src = NULL;
2548 tmp->frame.data = tmp->ast_rd_buf;
2550 if (tmp->faxdetect && !tmp->faxhandled) {
2551 if (tmp->faxdetect_timeout) {
2552 if (ast_tvzero(tmp->faxdetect_tv)) {
2553 tmp->faxdetect_tv = ast_tvnow();
2554 chan_misdn_log(2,tmp->bc->port,"faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
2555 return process_ast_dsp(tmp, &tmp->frame);
2557 struct timeval tv_now = ast_tvnow();
2558 int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
2559 if (diff <= (tmp->faxdetect_timeout * 1000)) {
2560 chan_misdn_log(5,tmp->bc->port,"faxdetect: detecting ...\n");
2561 return process_ast_dsp(tmp, &tmp->frame);
2563 chan_misdn_log(2,tmp->bc->port,"faxdetect: stopping detection (time ran out) ...\n");
2569 chan_misdn_log(5,tmp->bc->port,"faxdetect: detecting ... (no timeout)\n");
2570 return process_ast_dsp(tmp, &tmp->frame);
2574 return process_ast_dsp(tmp, &tmp->frame);
2581 static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
2583 struct chan_list *ch;
2586 if (!ast || ! (ch=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
2588 if (ch->state == MISDN_HOLDED) {
2589 chan_misdn_log(7, 0, "misdn_write: Returning because holded\n");
2594 ast_log(LOG_WARNING, "private but no bc\n");
2599 chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxone\n");
2604 if ( !frame->subclass) {
2605 chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
2609 if ( !(frame->subclass & prefformat)) {
2611 chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
2616 if ( !frame->samples ) {
2617 chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
2621 if ( ! ch->bc->addr ) {
2622 chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
2628 int i, max=5>frame->samples?frame->samples:5;
2630 printf("write2mISDN %p %d bytes: ", p, frame->samples);
2632 for (i=0; i< max ; i++) printf("%2.2x ",((char*) frame->data)[i]);
2638 switch (ch->bc->bc_state) {
2639 case BCHAN_ACTIVATED:
2643 if (!ch->dropped_frame_cnt)
2644 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);
2646 ch->dropped_frame_cnt++;
2647 if (ch->dropped_frame_cnt > 100) {
2648 ch->dropped_frame_cnt=0;
2649 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);
2656 chan_misdn_log(9, ch->bc->port, "Sending :%d bytes 2 MISDN\n",frame->samples);
2657 if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
2658 /* Buffered Transmit (triggert by read from isdn side)*/
2659 if (misdn_jb_fill(ch->jb,frame->data,frame->samples) < 0) {
2661 cb_log(0,ch->bc->port,"Misdn Jitterbuffer Overflow.\n");
2665 /*transmit without jitterbuffer*/
2666 i=misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples);
2677 static enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
2678 struct ast_channel *c1, int flags,
2679 struct ast_frame **fo,
2680 struct ast_channel **rc,
2684 struct chan_list *ch1,*ch2;
2685 struct ast_channel *carr[2], *who;
2687 struct ast_frame *f;
2689 ch1=get_chan_by_ast(c0);
2690 ch2=get_chan_by_ast(c1);
2700 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
2702 /* trying to make a mISDN_dsp conference */
2703 chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid +1);
2704 misdn_lib_bridge(ch1->bc,ch2->bc);
2707 if (option_verbose > 2)
2708 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
2710 chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
2712 if (! (flags&AST_BRIDGE_DTMF_CHANNEL_0) )
2715 if (! (flags&AST_BRIDGE_DTMF_CHANNEL_1) )
2720 who = ast_waitfor_n(carr, 2, &to);
2723 ast_log(LOG_NOTICE,"misdn_bridge: empty read, breaking out\n");
2728 if (!f || f->frametype == AST_FRAME_CONTROL) {
2732 chan_misdn_log(4,ch1->bc->port,"Read Null Frame\n");
2734 chan_misdn_log(4,ch1->bc->port,"Read Frame Controll class:%d\n",f->subclass);
2742 if ( f->frametype == AST_FRAME_DTMF ) {
2743 chan_misdn_log(1,0,"Read DTMF %d from %s\n",f->subclass, who->exten);
2751 if (f->frametype == AST_FRAME_VOICE) {
2752 chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
2767 chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
2769 misdn_lib_split_bridge(ch1->bc,ch2->bc);
2772 return AST_BRIDGE_COMPLETE;
2775 /** AST INDICATIONS END **/
2777 static int dialtone_indicate(struct chan_list *cl)
2779 const struct ind_tone_zone_sound *ts= NULL;
2780 struct ast_channel *ast=cl->ast;
2783 chan_misdn_log(0,cl->bc->port,"No Ast in dialtone_indicate\n");
2788 misdn_cfg_get( cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
2791 chan_misdn_log(1,cl->bc->port,"Not sending Dialtone, because config wants it\n");
2795 chan_misdn_log(3,cl->bc->port," --> Dial\n");
2796 ts=ast_get_indication_tone(ast->zone,"dial");
2802 ast_playtones_start(ast,0, ts->data, 0);
2803 chan_misdn_log(4,cl->bc->port,"Starting Playtones\n");
2804 misdn_lib_tone_generator_start(cl->bc);
2810 static int hanguptone_indicate(struct chan_list *cl)
2812 misdn_lib_send_tone(cl->bc,TONE_HANGUP);
2816 static int stop_indicate(struct chan_list *cl)
2818 struct ast_channel *ast=cl->ast;
2821 chan_misdn_log(0,cl->bc->port,"No Ast in stop_indicate\n");
2825 chan_misdn_log(3,cl->bc->port," --> None\n");
2826 misdn_lib_tone_generator_stop(cl->bc);
2827 ast_playtones_stop(ast);
2828 /*ast_deactivate_generator(ast);*/
2834 static int start_bc_tones(struct chan_list* cl)
2836 misdn_lib_tone_generator_stop(cl->bc);
2842 static int stop_bc_tones(struct chan_list *cl)
2853 static struct chan_list *init_chan_list(int orig)
2855 struct chan_list *cl=malloc(sizeof(struct chan_list));
2858 chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
2862 memset(cl,0,sizeof(struct chan_list));
2865 cl->need_queue_hangup=1;
2868 cl->overlap_dial_task=-1;
2874 static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
2877 struct ast_channel *tmp = NULL;
2878 char group[BUFFERSIZE+1]="";
2880 char buf2[128], *ext=NULL, *port_str;
2881 char *tokb=NULL, *p=NULL;
2882 int channel=0, port=0;
2883 struct misdn_bchannel *newbc = NULL;
2885 struct chan_list *cl=init_chan_list(ORG_AST);
2887 sprintf(buf,"%s/%s",misdn_type,(char*)data);
2888 ast_copy_string(buf2,data, 128);
2890 port_str=strtok_r(buf2,"/", &tokb);
2892 ext=strtok_r(NULL,"/", &tokb);
2895 if (port_str[0]=='g' && port_str[1]==':' ) {
2896 /* We make a group call lets checkout which ports are in my group */
2898 strncpy(group, port_str, BUFFERSIZE);
2900 chan_misdn_log(2, 0, " --> Group Call group: %s\n",group);
2902 else if ((p = strchr(port_str, ':'))) {
2903 /* we have a preselected channel */
2905 channel = atoi(++p);
2906 port = atoi(port_str);
2907 chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
2910 port = atoi(port_str);
2915 ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extension.conf\n",ext);
2919 if (!ast_strlen_zero(group)) {
2921 char cfg_group[BUFFERSIZE+1];
2922 struct robin_list *rr = NULL;
2924 if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
2925 chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...");
2926 rr = get_robin_position(group);
2930 int robin_channel = rr->channel;
2936 for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start;
2937 port = misdn_cfg_get_next_port_spin(port)) {
2942 if (port >= port_start)
2945 if (port <= port_start && next_chan) {
2946 int maxbchans=misdn_lib_get_maxchans(port);
2947 if (++robin_channel >= maxbchans) {
2953 misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
2955 if (!strcasecmp(cfg_group, group)) {
2958 misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
2959 port_up = misdn_lib_port_up(port, check);
2961 if (check && !port_up)
2962 chan_misdn_log(1,port,"L1 is not Up on this Port\n");
2964 if (check && port_up<0) {
2965 ast_log(LOG_WARNING,"This port (%d) is blocked\n", port);
2970 newbc = misdn_lib_get_free_bc(port, robin_channel,0);
2972 chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
2974 chan_misdn_log(4, port, "portup:%d\n", port_up);
2975 rr->port = newbc->port;
2976 rr->channel = newbc->channel;
2982 } while (!newbc && robin_channel != rr->channel);
2985 chan_misdn_log(-1, port, " Failed! No free channel in group %d!", group);
2989 for (port=misdn_cfg_get_next_port(0); port > 0;
2990 port=misdn_cfg_get_next_port(port)) {
2992 misdn_cfg_get( port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
2994 chan_misdn_log(3,port, "Group [%s] Port [%d]\n", group, port);
2995 if (!strcasecmp(cfg_group, group)) {
2998 misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
2999 port_up = misdn_lib_port_up(port, check);
3001 chan_misdn_log(4, port, "portup:%d\n", port_up);
3004 newbc = misdn_lib_get_free_bc(port, 0, 0);
3014 chan_misdn_log(1, port," --> preselected_channel: %d\n",channel);
3015 newbc = misdn_lib_get_free_bc(port, channel, 0);
3019 chan_misdn_log(-1, 0, "Could not create channel on port:%d with extensions:%s\n",port,ext);
3023 /* create ast_channel and link all the objects together */
3026 tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
3029 /* register chan in local list */
3030 cl_queue_chan(&cl_te, cl) ;
3032 /* fill in the config into the objects */
3033 read_config(cl, ORG_AST);
3042 static int misdn_send_text (struct ast_channel *chan, const char *text)
3044 struct chan_list *tmp=chan->tech_pvt;
3046 if (tmp && tmp->bc) {
3047 ast_copy_string(tmp->bc->display,text,sizeof(tmp->bc->display));
3048 misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
3050 ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
3057 static struct ast_channel_tech misdn_tech = {
3059 .description="Channel driver for mISDN Support (Bri/Pri)",
3060 .capabilities= AST_FORMAT_ALAW ,
3061 .requester=misdn_request,
3062 .send_digit_begin=misdn_digit_begin,
3063 .send_digit_end=misdn_digit_end,
3065 .bridge=misdn_bridge,
3066 .hangup=misdn_hangup,
3067 .answer=misdn_answer,
3070 .indicate=misdn_indication,
3072 .send_text=misdn_send_text,
3076 static struct ast_channel_tech misdn_tech_wo_bridge = {
3078 .description="Channel driver for mISDN Support (Bri/Pri)",
3079 .capabilities=AST_FORMAT_ALAW ,
3080 .requester=misdn_request,
3081 .send_digit_begin=misdn_digit_begin,
3082 .send_digit_end=misdn_digit_end,
3084 .hangup=misdn_hangup,
3085 .answer=misdn_answer,
3088 .indicate=misdn_indication,
3090 .send_text=misdn_send_text,
3095 static int glob_channel=0;
3097 static void update_name(struct ast_channel *tmp, int port, int c)
3100 int tmp_port = misdn_cfg_get_next_port(0);
3101 for (; tmp_port > 0; tmp_port=misdn_cfg_get_next_port(tmp_port)) {
3102 if (tmp_port == port) break;
3103 chan_offset+=misdn_lib_port_is_pri(tmp_port)?30:2;
3107 ast_string_field_build(tmp, name, "%s/%d-u%d",
3108 misdn_type, chan_offset+c, glob_channel++);