remove extraneous svn:executable properties
[asterisk/asterisk.git] / channels / chan_misdn.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  * 
4  * Copyright (C) 2004, Christian Richter
5  *
6  * Christian Richter <crich@beronet.com>
7  *
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.
13  *
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.
17  *
18  */
19
20 /*!
21  * \file
22  *
23  * \brief the chan_misdn channel driver for Asterisk
24  * \author Christian Richter <crich@beronet.com>
25  *
26  * \ingroup channel_drivers
27  */
28
29 #include <stdio.h>
30 #include <pthread.h>
31 #include <string.h>
32 #include <sys/socket.h>
33 #include <sys/time.h>
34 #include <errno.h>
35 #include <unistd.h>
36 #include <stdlib.h>
37 #include <arpa/inet.h>
38 #include <fcntl.h>
39 #include <sys/ioctl.h>
40 #include <sys/file.h>
41
42 #include <asterisk/channel.h>
43 #include <asterisk/config.h>
44 #include <asterisk/logger.h>
45 #include <asterisk/module.h>
46 #include <asterisk/pbx.h>
47 #include <asterisk/options.h>
48 #include <asterisk/io.h>
49 #include <asterisk/frame.h>
50 #include <asterisk/translate.h>
51 #include <asterisk/cli.h>
52 #include <asterisk/musiconhold.h>
53 #include <asterisk/dsp.h>
54 #include <asterisk/translate.h>
55 #include <asterisk/config.h>
56 #include <asterisk/file.h>
57 #include <asterisk/callerid.h>
58 #include <asterisk/indications.h>
59 #include <asterisk/app.h>
60 #include <asterisk/features.h>
61
62 #include "chan_misdn_config.h"
63 #include "isdn_lib.h"
64
65 ast_mutex_t release_lock_mutex;
66
67 #define release_lock ast_mutex_lock(&release_lock_mutex)
68 #define release_unlock ast_mutex_unlock(&release_lock_mutex)
69
70
71 /* BEGIN: chan_misdn.h */
72
73 enum misdn_chan_state {
74         MISDN_NOTHING,          /*!< at beginning */
75         MISDN_WAITING4DIGS, /*!<  when waiting for infos */
76         MISDN_EXTCANTMATCH, /*!<  when asterisk couldnt match our ext */
77         MISDN_DIALING, /*!<  when pbx_start */
78         MISDN_PROGRESS, /*!<  we got a progress */
79         MISDN_CALLING, /*!<  when misdn_call is called */
80         MISDN_CALLING_ACKNOWLEDGE, /*!<  when we get SETUP_ACK */
81         MISDN_ALERTING, /*!<  when Alerting */
82         MISDN_BUSY, /*!<  when BUSY */
83         MISDN_CONNECTED, /*!<  when connected */
84         MISDN_BRIDGED, /*!<  when bridged */
85         MISDN_CLEANING, /*!< when hangup from * but we were connected before */
86         MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
87         MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of */
88         /* misdn_hangup */
89         MISDN_HOLDED, /*!< if this chan is holded */
90         MISDN_HOLD_DISCONNECT /*!< if this chan is holded */
91   
92 };
93
94 #define ORG_AST 1
95 #define ORG_MISDN 2
96
97 struct chan_list {
98   
99         ast_mutex_t lock;
100
101         enum misdn_chan_state state;
102         int holded; 
103         int orginator;
104
105         int norxtone;
106         int notxtone; 
107
108         int pipe[2];
109         char ast_rd_buf[4096];
110         struct ast_frame frame;
111
112         int faxdetect;
113         int faxhandled;
114
115         int ast_dsp;
116         
117         struct ast_dsp *dsp;
118         struct ast_trans_pvt *trans;
119   
120         struct ast_channel * ast;
121   
122         struct misdn_bchannel *bc;
123         struct misdn_bchannel *holded_bc;
124
125         unsigned int l3id;
126         int addr;
127         
128         struct chan_list *peer;
129         struct chan_list *next;
130         struct chan_list *prev;
131         struct chan_list *first;
132 };
133
134 struct robin_list {
135         char *group;
136         int port;
137         int channel;
138         struct robin_list *next;
139         struct robin_list *prev;
140 };
141 static struct robin_list *robin = NULL;
142
143 static inline void free_robin_list_r (struct robin_list *r)
144 {
145         if (r) {
146                 if (r->next) free_robin_list_r(r->next);
147                 if (r->group) free(r->group);
148                 free(r);
149         }
150 }
151
152 static void free_robin_list ( void )
153 {
154         free_robin_list_r(robin);
155         robin = NULL;
156 }
157
158 struct robin_list* get_robin_position (char *group) 
159 {
160         struct robin_list *iter = robin;
161         for (; iter; iter = iter->next) {
162                 if (!strcasecmp(iter->group, group))
163                         return iter;
164         }
165         struct robin_list *new = (struct robin_list *)calloc(1, sizeof(struct robin_list));
166         new->group = strndup(group, strlen(group));
167         new->channel = 1;
168         if (robin) {
169                 new->next = robin;
170                 robin->prev = new;
171         }
172         robin = new;
173         return robin;
174 }
175
176 struct ast_channel *misdn_new(struct chan_list *cl, int state, char * name, char * context, char *exten, char *callerid, int format, int port, int c);
177 void send_digit_to_chan(struct chan_list *cl, char digit );
178
179
180 #define AST_CID_P(ast) ast->cid.cid_num
181 #define AST_BRIDGED_P(ast) ast_bridged_channel(ast) 
182 #define AST_LOAD_CFG ast_config_load
183 #define AST_DESTROY_CFG ast_config_destroy
184
185 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
186 #define MISDN_ASTERISK_PVT(ast) 1
187 #define MISDN_ASTERISK_TYPE(ast) ast->tech->type
188
189 /* END: chan_misdn.h */
190
191 #include <asterisk/strings.h>
192
193 /* #define MISDN_DEBUG 1 */
194
195 static  char *desc = "Channel driver for mISDN Support (Bri/Pri)";
196 static  char *type = "mISDN";
197
198 int tracing = 0 ;
199
200 static int usecnt=0;
201
202 char **misdn_key_vector=NULL;
203 int misdn_key_vector_size=0;
204
205 /* Only alaw and mulaw is allowed for now */
206 static int prefformat =  AST_FORMAT_ALAW ; /*  AST_FORMAT_SLINEAR ;  AST_FORMAT_ULAW | */
207
208 static ast_mutex_t usecnt_lock; 
209
210 int *misdn_debug;
211 int *misdn_debug_only;
212 int max_ports;
213
214 struct chan_list dummy_cl;
215
216 struct chan_list *cl_te=NULL;
217 ast_mutex_t cl_te_lock;
218
219 enum event_response_e
220 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
221
222 void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc);
223
224 void cl_queue_chan(struct chan_list **list, struct chan_list *chan);
225 void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);
226 struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);
227 void chan_misdn_log(int level, int port, char *tmpl, ...);
228 void chan_misdn_trace_call(struct ast_channel *chan, int debug, char *tmpl, ...);
229
230 static int start_bc_tones(struct chan_list *cl);
231 static int stop_bc_tones(struct chan_list *cl);
232 static void release_chan(struct misdn_bchannel *bc);
233
234 static int misdn_set_opt_exec(struct ast_channel *chan, void *data);
235 static int misdn_facility_exec(struct ast_channel *chan, void *data);
236
237 /*************** Helpers *****************/
238
239 static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
240 {
241         struct chan_list *tmp;
242   
243         for (tmp=cl_te; tmp; tmp = tmp->next) {
244                 if ( tmp->ast == ast ) return tmp;
245         }
246   
247         return NULL;
248 }
249
250 static struct chan_list * get_chan_by_ast_name(char *name)
251 {
252         struct chan_list *tmp;
253   
254         for (tmp=cl_te; tmp; tmp = tmp->next) {
255                 if ( tmp->ast  && strcmp(tmp->ast->name,name) == 0) return tmp;
256         }
257   
258         return NULL;
259 }
260
261 static char* tone2str(struct misdn_bchannel *bc)
262 {
263         static struct {
264                 char name[16];
265                 enum tone_e tone;
266         } *tone, tone_buf[] = {
267                 {"NOTONE",TONE_NONE},
268                 {"DIAL",TONE_DIAL},
269                 {"BUSY",TONE_BUSY},
270                 {"ALERT",TONE_ALERTING},
271                 {"",TONE_NONE}
272         };
273   
274   
275         for (tone=&tone_buf[0]; tone->name[0]; tone++) {
276                 if (tone->tone == bc->tone) return tone->name;
277         }
278         return NULL;
279 }
280
281 static char *bearer2str(int cap) {
282         static char *bearers[]={
283                 "Speech",
284                 "Audio 3.1k",
285                 "Unres Digital",
286                 "Res Digital",
287                 "Unknown Bearer"
288         };
289         
290         switch (cap) {
291         case INFO_CAPABILITY_SPEECH:
292                 return bearers[0];
293                 break;
294         case INFO_CAPABILITY_AUDIO_3_1K:
295                 return bearers[1];
296                 break;
297         case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
298                 return bearers[2];
299                 break;
300         case INFO_CAPABILITY_DIGITAL_RESTRICTED:
301                 return bearers[3];
302                 break;
303         default:
304                 return bearers[4];
305                 break;
306         }
307 }
308
309 static void print_bearer(struct misdn_bchannel *bc) 
310 {
311         
312         chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
313         
314         switch(bc->law) {
315         case INFO_CODEC_ALAW:
316                 chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
317                 break;
318         case INFO_CODEC_ULAW:
319                 chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
320                 break;
321         }
322 }
323 /*************** Helpers END *************/
324
325 void send_digit_to_chan(struct chan_list *cl, char digit )
326 {
327         static const char* dtmf_tones[] = {
328                 "!941+1336/100,!0/100", /* 0 */
329                 "!697+1209/100,!0/100", /* 1 */
330                 "!697+1336/100,!0/100", /* 2 */
331                 "!697+1477/100,!0/100", /* 3 */
332                 "!770+1209/100,!0/100", /* 4 */
333                 "!770+1336/100,!0/100", /* 5 */
334                 "!770+1477/100,!0/100", /* 6 */
335                 "!852+1209/100,!0/100", /* 7 */
336                 "!852+1336/100,!0/100", /* 8 */
337                 "!852+1477/100,!0/100", /* 9 */
338                 "!697+1633/100,!0/100", /* A */
339                 "!770+1633/100,!0/100", /* B */
340                 "!852+1633/100,!0/100", /* C */
341                 "!941+1633/100,!0/100", /* D */
342                 "!941+1209/100,!0/100", /* * */
343                 "!941+1477/100,!0/100" };       /* # */
344         struct ast_channel *chan=cl->ast; 
345   
346         if (digit >= '0' && digit <='9')
347                 ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
348         else if (digit >= 'A' && digit <= 'D')
349                 ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
350         else if (digit == '*')
351                 ast_playtones_start(chan,0,dtmf_tones[14], 0);
352         else if (digit == '#')
353                 ast_playtones_start(chan,0,dtmf_tones[15], 0);
354         else {
355                 /* not handled */
356                 ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
357     
358     
359         }
360 }
361 /*** CLI HANDLING ***/
362 static int misdn_set_debug(int fd, int argc, char *argv[])
363 {
364         if (argc != 4 && argc != 5 && argc != 6 && argc != 7)
365                 return RESULT_SHOWUSAGE; 
366
367         int level = atoi(argv[3]);
368
369         switch (argc) {
370                 case 4: 
371                 case 5: {
372                                         int only = 0;
373                                         if (argc == 5) {
374                                                 if (strncasecmp(argv[4], "only", strlen(argv[4])))
375                                                         return RESULT_SHOWUSAGE;
376                                                 else
377                                                         only = 1;
378                                         }
379                                         int i;
380                                         for (i=0; i<=max_ports; i++) {
381                                                 misdn_debug[i] = level;
382                                                 misdn_debug_only[i] = only;
383                                         }
384                                         ast_cli(fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
385                                 }
386                                 break;
387                 case 6: 
388                 case 7: {
389                                         if (strncasecmp(argv[4], "port", strlen(argv[4])))
390                                                 return RESULT_SHOWUSAGE;
391                                         int port = atoi(argv[5]);
392                                         if (port <= 0 || port > max_ports) {
393                                                 switch (max_ports) {
394                                                         case 0:
395                                                                 ast_cli(fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
396                                                                 break;
397                                                         case 1:
398                                                                 ast_cli(fd, "port number not valid! only port 1 is availble.\n");
399                                                                 break;
400                                                         default:
401                                                                 ast_cli(fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
402                                                         }
403                                                         return 0;
404                                         }
405                                         if (argc == 7) {
406                                                 if (strncasecmp(argv[6], "only", strlen(argv[6])))
407                                                         return RESULT_SHOWUSAGE;
408                                                 else
409                                                         misdn_debug_only[port] = 1;
410                                         } else
411                                                 misdn_debug_only[port] = 0;
412                                         misdn_debug[port] = level;
413                                         ast_cli(fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
414                                 }
415         }
416         return 0;
417 }
418
419
420 static int misdn_set_crypt_debug(int fd, int argc, char *argv[])
421 {
422         if (argc != 5 )return RESULT_SHOWUSAGE; 
423
424         return 0;
425 }
426
427
428 static int misdn_restart_port (int fd, int argc, char *argv[])
429 {
430         int port;
431   
432         if (argc != 4)
433                 return RESULT_SHOWUSAGE;
434   
435         port = atoi(argv[3]);
436
437         misdn_lib_port_restart(port);
438
439         return 0;
440 }
441
442 static int misdn_port_up (int fd, int argc, char *argv[])
443 {
444         int port;
445         
446         if (argc != 4)
447                 return RESULT_SHOWUSAGE;
448         
449         port = atoi(argv[3]);
450         
451         misdn_lib_get_port_up(port);
452   
453         return 0;
454 }
455
456
457 static int misdn_show_config (int fd, int argc, char *argv[])
458 {
459         char buffer[BUFFERSIZE];
460         enum misdn_cfg_elements elem;
461         int linebreak;
462
463         int onlyport = -1;
464         if (argc >= 4) {
465                 if (!sscanf(argv[3], "%d", &onlyport) || onlyport < 0) {
466                         ast_cli(fd, "Unknown option: %s\n", argv[3]);
467                         return RESULT_SHOWUSAGE;
468                 }
469         }
470         
471         if (argc == 3 || onlyport == 0) {
472                 ast_cli(fd,"Misdn General-Config: \n"); 
473                 ast_cli(fd," ->  VERSION: " CHAN_MISDN_VERSION "\n");
474                 
475                 for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
476                         misdn_cfg_get_config_string( 0, elem, buffer, BUFFERSIZE);
477                         ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
478                 }
479         }
480
481         if (onlyport < 0) {
482                 int port = misdn_cfg_get_next_port(0);
483                 for (; port > 0; port = misdn_cfg_get_next_port(port)) {
484                         ast_cli(fd, "\n[PORT %d]\n", port);
485                         for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
486                                 misdn_cfg_get_config_string( port, elem, buffer, BUFFERSIZE);
487                                 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
488                         }       
489                         ast_cli(fd, "\n");
490                 }
491         }
492         
493         if (onlyport > 0) {
494                 if (misdn_cfg_is_port_valid(onlyport)) {
495                         ast_cli(fd, "[PORT %d]\n", onlyport);
496                         for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
497                                 misdn_cfg_get_config_string( onlyport, elem, buffer, BUFFERSIZE);
498                                 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
499                         }       
500                         ast_cli(fd, "\n");
501                 } else {
502                         ast_cli(fd, "Port %d is not active!\n", onlyport);
503                 }
504         }
505         return 0;
506 }
507
508
509
510 struct state_struct {
511         enum misdn_chan_state state;
512         char txt[255] ;
513 } ;
514
515 struct state_struct state_array[] = {
516         {MISDN_NOTHING,"NOTHING"}, /* at beginning */
517         {MISDN_WAITING4DIGS,"WAITING4DIGS"}, /*  when waiting for infos */
518         {MISDN_EXTCANTMATCH,"EXTCANTMATCH"}, /*  when asterisk couldnt match our ext */
519         {MISDN_DIALING,"DIALING"}, /*  when pbx_start */
520         {MISDN_PROGRESS,"PROGRESS"}, /*  when pbx_start */
521         {MISDN_CALLING,"CALLING"}, /*  when misdn_call is called */
522         {MISDN_ALERTING,"ALERTING"}, /*  when Alerting */
523         {MISDN_BUSY,"BUSY"}, /*  when BUSY */
524         {MISDN_CONNECTED,"CONNECTED"}, /*  when connected */
525         {MISDN_BRIDGED,"BRIDGED"}, /*  when bridged */
526         {MISDN_CLEANING,"CLEANING"}, /* when hangup from * but we were connected before */
527         {MISDN_HUNGUP_FROM_MISDN,"HUNGUP_FROM_MISDN"}, /* when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
528         {MISDN_HOLDED,"HOLDED"}, /* when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
529         {MISDN_HOLD_DISCONNECT,"HOLD_DISCONNECT"}, /* when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
530         {MISDN_HUNGUP_FROM_AST,"HUNGUP_FROM_AST"} /* when DISCONNECT/RELEASE/REL_COMP came out of */
531         /* misdn_hangup */
532 };
533
534
535
536
537 char *misdn_get_ch_state(struct chan_list *p) 
538 {
539         int i;
540         if( !p) return NULL;
541   
542         for (i=0; i< sizeof(state_array)/sizeof(struct state_struct); i++) {
543                 if ( state_array[i].state == p->state) return state_array[i].txt; 
544         }
545   
546         return NULL;
547 }
548
549 static int misdn_reload (int fd, int argc, char *argv[])
550 {
551         int i, cfg_debug;
552         
553         ast_cli(fd, "Reloading mISDN Config\n");
554         chan_misdn_log(0, 0, "Dynamic Crypting Activation is not support during reload at the moment\n");
555         
556         free_robin_list();
557
558         misdn_cfg_reload();
559
560         {
561                 char tempbuf[BUFFERSIZE];
562                 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
563                 if (strlen(tempbuf))
564                         tracing = 1;
565         }
566
567         misdn_cfg_get( 0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(int));
568         for (i = 0;  i <= max_ports; i++) {
569                 misdn_debug[i] = cfg_debug;
570                 misdn_debug_only[i] = 0;
571         }
572         
573         return 0;
574 }
575
576 static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel* bc)
577 {
578         struct ast_channel *ast=help->ast;
579         ast_cli(fd,
580                 "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s ctx:%s state:%s\n",
581                 bc->pid, bc->port, bc->channel,
582                 bc->nt?"NT":"TE",
583                 help->orginator == ORG_AST?"*":"I",
584                 ast?ast->exten:NULL,
585                 ast?AST_CID_P(ast):NULL,
586                 ast?ast->context:NULL,
587                 misdn_get_ch_state(help)
588                 );
589         if (misdn_debug[bc->port] > 0)
590                 ast_cli(fd,
591                         "  --> astname: %s\n"
592                         "  --> ch_l3id: %x\n"
593                         "  --> ch_addr: %x\n"
594                         "  --> bc_addr: %x\n"
595                         "  --> bc_l3id: %x\n"
596                         "  --> tone: %s\n"
597                         "  --> display: %s\n"
598                         "  --> activated: %d\n"
599                         "  --> capability: %s\n"
600                         "  --> echo_cancel: %d\n"
601                         "  --> notone : rx %d tx:%d\n"
602                         "  --> bc_hold: %d holded_bc :%d\n",
603                         help->ast->name,
604                         help->l3id,
605                         help->addr,
606                         bc->addr,
607                         bc?bc->l3_id:-1,
608                         tone2str(bc),
609                         bc->display,
610                         
611                         bc->active,
612                         bearer2str(bc->capability),
613                         bc->ec_enable,
614                         help->norxtone,help->notxtone,
615                         bc->holded, help->holded_bc?1:0
616                         );
617   
618 }
619
620
621 static int misdn_show_cls (int fd, int argc, char *argv[])
622 {
623         struct chan_list *help=cl_te;
624   
625         ast_cli(fd,"Chan List: %p\n",cl_te); 
626   
627         for (;help; help=help->next) {
628                 struct misdn_bchannel *bc=help->bc;   
629                 struct ast_channel *ast=help->ast;
630                 if (misdn_debug[0] > 2) ast_cli(fd, "Bc:%p Ast:%p\n", bc, ast);
631                 if (bc) {
632                         print_bc_info(fd, help, bc);
633                 } else if ( (bc=help->holded_bc) ) {
634                         chan_misdn_log(0, 0, "ITS A HOLDED BC:\n");
635                         print_bc_info(fd, help,  bc);
636                 } else {
637                         ast_cli(fd,"* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, AST_CID_P(ast));
638                 }
639         }
640   
641   
642         return 0;
643 }
644
645
646
647 static int misdn_show_cl (int fd, int argc, char *argv[])
648 {
649         struct chan_list *help=cl_te;
650
651         if (argc != 4)
652                 return RESULT_SHOWUSAGE;
653   
654         for (;help; help=help->next) {
655                 struct misdn_bchannel *bc=help->bc;   
656                 struct ast_channel *ast=help->ast;
657     
658                 if (bc && ast) {
659                         if (!strcasecmp(ast->name,argv[3])) {
660                                 print_bc_info(fd, help, bc);
661                                 break; 
662                         }
663                 } 
664         }
665   
666   
667         return 0;
668 }
669
670 ast_mutex_t lock;
671 int MAXTICS=8;
672
673 static int misdn_set_tics (int fd, int argc, char *argv[])
674 {
675         if (argc != 4)
676                 return RESULT_SHOWUSAGE;
677   
678         MAXTICS=atoi(argv[3]);
679   
680         return 0;
681 }
682
683
684
685 static int misdn_show_stacks (int fd, int argc, char *argv[])
686 {
687         int port;
688         
689         ast_cli(fd, "BEGIN STACK_LIST:\n");
690         for (port=misdn_cfg_get_next_port(0); port > 0;
691              port=misdn_cfg_get_next_port(port)) {
692                 char buf[128];
693                 get_show_stack_details(port,buf);
694                 ast_cli(fd,"  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
695         }
696                 
697
698         return 0;
699
700 }
701
702 static int misdn_show_port (int fd, int argc, char *argv[])
703 {
704         int port;
705         
706         if (argc != 4)
707                 return RESULT_SHOWUSAGE;
708   
709         port = atoi(argv[3]);
710   
711         ast_cli(fd, "BEGIN STACK_LIST:\n");
712
713         char buf[128];
714         get_show_stack_details(port,buf);
715         ast_cli(fd,"  %s  Debug:%d%s\n",buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
716
717         
718         return 0;
719 }
720
721 static int misdn_send_cd (int fd, int argc, char *argv[])
722 {
723         char *channame; 
724         char *nr; 
725   
726         if (argc != 5)
727                 return RESULT_SHOWUSAGE;
728   
729         channame = argv[3];
730         nr = argv[4];
731         
732         ast_cli(fd, "Sending Calldeflection (%s) to %s\n",nr, channame);
733         
734         {
735                 struct chan_list *tmp=get_chan_by_ast_name(channame);
736                 
737                 if (!tmp) {
738                         ast_cli(fd, "Sending CD with nr %s to %s failed Channel does not exist\n",nr, channame);
739                         return 0; 
740                 } else {
741                         
742                         misdn_lib_send_facility(tmp->bc, FACILITY_CALLDEFLECT, nr);
743                 }
744         }
745   
746         return 0; 
747 }
748
749
750
751 static int misdn_send_digit (int fd, int argc, char *argv[])
752 {
753         char *channame; 
754         char *msg; 
755   
756         if (argc != 5)
757                 return RESULT_SHOWUSAGE;
758   
759         channame = argv[3];
760         msg = argv[4];
761
762         ast_cli(fd, "Sending %s to %s\n",msg, channame);
763   
764         {
765                 struct chan_list *tmp=get_chan_by_ast_name(channame);
766     
767                 if (!tmp) {
768                         ast_cli(fd, "Sending %s to %s failed Channel does not exist\n",msg, channame);
769                         return 0; 
770                 } else {
771 #if 1
772                         int i;
773                         int msglen = strlen(msg);
774                         for (i=0; i<msglen; i++) {
775                                 ast_cli(fd, "Sending: %c\n",msg[i]);
776                                 send_digit_to_chan(tmp, msg[i]);
777                                 /* res = ast_safe_sleep(tmp->ast, 250); */
778                                 usleep(250000);
779                                 /* res = ast_waitfor(tmp->ast,100); */
780                         }
781 #else
782                         int res;
783                         res = ast_dtmf_stream(tmp->ast,NULL,msg,250);
784 #endif
785                 }
786         }
787   
788         return 0; 
789 }
790
791 static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
792 {
793         char *channame; 
794
795         if (argc != 4)
796                 return RESULT_SHOWUSAGE;
797         
798         channame = argv[3];
799   
800         ast_cli(fd, "Toggling EchoCancel on %s\n", channame);
801   
802         {
803                 struct chan_list *tmp=get_chan_by_ast_name(channame);
804     
805                 if (!tmp) {
806                         ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
807                         return 0; 
808                 } else {
809                         tmp->bc->ec_enable=tmp->bc->ec_enable?0:1;
810
811                         if (tmp->bc->ec_enable) {
812                                 manager_ec_enable(tmp->bc);
813                         } else {
814                                 manager_ec_disable(tmp->bc);
815                         }
816                 }
817         }
818   
819         return 0; 
820 }
821
822
823
824 static int misdn_send_display (int fd, int argc, char *argv[])
825 {
826         char *channame; 
827         char *msg; 
828   
829         if (argc != 5)
830                 return RESULT_SHOWUSAGE;
831   
832         channame = argv[3];
833         msg = argv[4];
834
835         ast_cli(fd, "Sending %s to %s\n",msg, channame);
836         {
837                 struct chan_list *tmp;
838                 tmp=get_chan_by_ast_name(channame);
839     
840                 if (tmp && tmp->bc) {
841                         int l = sizeof(tmp->bc->display);
842                         strncpy(tmp->bc->display, msg, l);
843                         tmp->bc->display[l-1] = 0;
844                         misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
845                 } else {
846                         ast_cli(fd,"No such channel %s\n",channame);
847                         return RESULT_FAILURE;
848                 }
849         }
850
851         return RESULT_SUCCESS ;
852 }
853
854
855
856
857 static char *complete_ch_helper(char *line, char *word, int pos, int state, int rpos)
858 {
859         struct ast_channel *c;
860         int which=0;
861         char *ret;
862         if (pos != rpos)
863                 return NULL;
864         c = ast_channel_walk_locked(NULL);
865         while(c) {
866                 if (!strncasecmp(word, c->name, strlen(word))) {
867                         if (++which > state)
868                                 break;
869                 }
870                 ast_mutex_unlock(&c->lock);
871                 c = ast_channel_walk_locked(c);
872         }
873         if (c) {
874                 ret = strdup(c->name);
875                 ast_mutex_unlock(&c->lock);
876         } else
877                 ret = NULL;
878         return ret;
879 }
880
881 static char *complete_ch(char *line, char *word, int pos, int state)
882 {
883         return complete_ch_helper(line, word, pos, state, 3);
884 }
885
886 static char *complete_debug_port (char *line, char *word, int pos, int state)
887 {
888         if (state)
889                 return NULL;
890
891         switch (pos) {
892         case 4: if (*word == 'p')
893                                 return strdup("port");
894                         else if (*word == 'o')
895                                 return strdup("only");
896                         break;
897         case 6: if (*word == 'o')
898                                 return strdup("only");
899                         break;
900         }
901         return NULL;
902 }
903
904 static struct ast_cli_entry cli_send_cd =
905 { {"misdn","send","calldeflect", NULL},
906   misdn_send_cd,
907   "Sends CallDeflection to mISDN Channel", 
908   "Usage: misdn send calldeflect <channel> \"<nr>\" \n",
909   complete_ch
910 };
911
912
913 static struct ast_cli_entry cli_send_digit =
914 { {"misdn","send","digit", NULL},
915   misdn_send_digit,
916   "Sends DTMF Digit to mISDN Channel", 
917   "Usage: misdn send digit <channel> \"<msg>\" \n"
918   "       Send <digit> to <channel> as DTMF Tone\n"
919   "       when channel is a mISDN channel\n",
920   complete_ch
921 };
922
923
924 static struct ast_cli_entry cli_toggle_echocancel =
925 { {"misdn","toggle","echocancel", NULL},
926   misdn_toggle_echocancel,
927   "Toggles EchoCancel on mISDN Channel", 
928   "Usage: misdn toggle echocancel <channel>\n", 
929   complete_ch
930 };
931
932
933
934 static struct ast_cli_entry cli_send_display =
935 { {"misdn","send","display", NULL},
936   misdn_send_display,
937   "Sends Text to mISDN Channel", 
938   "Usage: misdn send display <channel> \"<msg>\" \n"
939   "       Send <msg> to <channel> as Display Message\n"
940   "       when channel is a mISDN channel\n",
941   complete_ch
942 };
943
944
945 static struct ast_cli_entry cli_show_config =
946 { {"misdn","show","config", NULL},
947   misdn_show_config,
948   "Shows internal mISDN config, read from cfg-file", 
949   "Usage: misdn show config [port | 0]\n       use 0 to only print the general config.\n"
950 };
951  
952
953 static struct ast_cli_entry cli_reload =
954 { {"misdn","reload", NULL},
955   misdn_reload,
956   "Reloads internal mISDN config, read from cfg-file", 
957   "Usage: misdn reload\n"
958 };
959
960 static struct ast_cli_entry cli_set_tics =
961 { {"misdn","set","tics", NULL},
962   misdn_set_tics,
963   "", 
964   "\n"
965 };
966
967
968 static struct ast_cli_entry cli_show_cls =
969 { {"misdn","show","channels", NULL},
970   misdn_show_cls,
971   "Shows internal mISDN chan_list", 
972   "Usage: misdn show channels\n"
973 };
974
975 static struct ast_cli_entry cli_show_cl =
976 { {"misdn","show","channel", NULL},
977   misdn_show_cl,
978   "Shows internal mISDN chan_list", 
979   "Usage: misdn show channels\n",
980   complete_ch
981 };
982
983
984
985 static struct ast_cli_entry cli_restart_port =
986 { {"misdn","restart","port", NULL},
987   misdn_restart_port,
988   "Restarts the given port", 
989   "Usage: misdn restart port\n"
990 };
991
992
993 static struct ast_cli_entry cli_port_up =
994 { {"misdn","port","up", NULL},
995   misdn_port_up,
996   "Tries to establish L1 on the given port", 
997   "Usage: misdn port up <port>\n"
998 };
999
1000
1001 static struct ast_cli_entry cli_show_stacks =
1002 { {"misdn","show","stacks", NULL},
1003   misdn_show_stacks,
1004   "Shows internal mISDN stack_list", 
1005   "Usage: misdn show stacks\n"
1006 };
1007
1008 static struct ast_cli_entry cli_show_port =
1009 { {"misdn","show","port", NULL},
1010   misdn_show_port,
1011   "Shows detailed information for given port", 
1012   "Usage: misdn show port <port>\n"
1013 };
1014
1015
1016
1017 static struct ast_cli_entry cli_set_debug =
1018 { {"misdn","set","debug", NULL},
1019   misdn_set_debug,
1020   "Sets Debuglevel of chan_misdn",
1021   "Usage: misdn set debug <level> [only] | [port <port> [only]]\n",
1022   complete_debug_port
1023 };
1024
1025 static struct ast_cli_entry cli_set_crypt_debug =
1026 { {"misdn","set","crypt","debug", NULL},
1027   misdn_set_crypt_debug,
1028   "Sets CryptDebuglevel of chan_misdn, at the moment, level={1,2}", 
1029   "Usage: misdn set crypt debug <level>\n"
1030 };
1031 /*** CLI END ***/
1032
1033
1034 /*****************************/
1035 /*** AST Indications Start ***/
1036 /*****************************/
1037
1038 static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
1039 {
1040         int port=0;
1041         int r;
1042         struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
1043         struct misdn_bchannel *newbc;
1044         char *opts=NULL, *ext=NULL;
1045         char dest_cp[256];
1046         char *tokb;
1047         
1048         {
1049                 strncpy(dest_cp,dest,sizeof(dest_cp)-1);
1050                 dest_cp[sizeof(dest_cp)]=0;
1051                 
1052                 ext=strtok_r(dest_cp,"/",&tokb);
1053                 
1054                 if (ext) {
1055                         ext=strtok_r(NULL,"/",&tokb);
1056                         if (ext) {
1057                                 opts=strtok_r(NULL,"/",&tokb);
1058                         } else {
1059                                 chan_misdn_log(-1,0,"misdn_call: No Extension given!\n");
1060                                 return -1;
1061                         }
1062                 }
1063                 
1064                 
1065         }
1066
1067         if (!ast) {
1068                 ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
1069                 return -1;
1070         }
1071
1072         if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest  ) {
1073                 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1074                 ast->hangupcause=41;
1075                 ast_setstate(ast, AST_STATE_DOWN);
1076                 return -1;
1077         }
1078
1079
1080         if (!ch) {
1081                 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1082                 ast->hangupcause=41;
1083                 ast_setstate(ast, AST_STATE_DOWN);
1084                 return -1;
1085         }
1086         
1087         newbc=ch->bc;
1088         
1089         if (!newbc) {
1090                 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1091                 ast->hangupcause=41;
1092                 ast_setstate(ast, AST_STATE_DOWN);
1093                 return -1;
1094         }
1095         
1096         port=newbc->port;
1097         
1098         ast_copy_string(newbc->dad, ext, sizeof(newbc->dad));
1099         ast_copy_string(ast->exten, ext, sizeof(ast->exten));
1100         
1101         
1102         chan_misdn_log(1, 0, "* CALL: %s\n",dest);
1103         
1104         chan_misdn_log(1, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
1105         
1106         {
1107                 char context[BUFFERSIZE];
1108                 
1109                 misdn_cfg_get( port, MISDN_CFG_CONTEXT, context, sizeof(ast->context));
1110                 {
1111                         int l = sizeof(ast->context);
1112                         strncpy(ast->context,context, l);
1113                         ast->context[l-1] = 0;
1114                 }
1115                 chan_misdn_log(2, port, " --> * Setting Context to %s\n",context);
1116                 misdn_cfg_get( port, MISDN_CFG_LANGUAGE, ast->language, BUFFERSIZE);
1117                 
1118                 misdn_cfg_get( port, MISDN_CFG_TXGAIN, &newbc->txgain, sizeof(int));
1119                 misdn_cfg_get( port, MISDN_CFG_RXGAIN, &newbc->rxgain, sizeof(int));
1120                 
1121                 misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(newbc->te_choose_channel), sizeof(int));
1122                 
1123
1124                 {
1125                         char callerid[BUFFERSIZE];
1126                         misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
1127                         if ( ! ast_strlen_zero(callerid) ) {
1128                                 chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
1129                                 {
1130                                         int l = sizeof(newbc->oad);
1131                                         strncpy(newbc->oad,callerid, l);
1132                                         newbc->oad[l-1] = 0;
1133                                 }
1134                                 
1135                                 misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &newbc->dnumplan, sizeof(int));
1136                                 switch (newbc->dnumplan) {
1137                                 case NUMPLAN_INTERNATIONAL:
1138                                 case NUMPLAN_NATIONAL:
1139                                 case NUMPLAN_SUBSCRIBER:
1140                                 case NUMPLAN_UNKNOWN:
1141                                         /* Maybe we should cut off the prefix if present ? */
1142                                         break;
1143                                 default:
1144                                         chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
1145                                         break;
1146                                 }
1147                                 
1148                         }
1149                 }
1150                 
1151                 /* Will be overridden by asterisk in head! */
1152                 {
1153                         int pres;
1154                         
1155                         misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int));
1156                         newbc->pres=pres?0:1;
1157                         
1158                 }
1159                 
1160                 int def_callingpres;
1161                 misdn_cfg_get( port, MISDN_CFG_USE_CALLINGPRES, &def_callingpres, sizeof(int));
1162                 if ( def_callingpres) {
1163                         switch (ast->cid.cid_pres & 0x60){
1164                                 
1165                         case AST_PRES_RESTRICTED:
1166                                 newbc->pres=1;
1167                                 break;
1168                                 
1169                         case AST_PRES_UNAVAILABLE:
1170                                 newbc->pres=2;
1171                                 break;
1172                         
1173                         default:
1174                                 newbc->pres=0;
1175                         }
1176                         
1177                         switch (ast->cid.cid_pres & 0x3){
1178                                 
1179                         case AST_PRES_USER_NUMBER_UNSCREENED:
1180                                 newbc->screen=0;
1181                                 break;
1182
1183                         case AST_PRES_USER_NUMBER_PASSED_SCREEN:
1184                                 newbc->screen=1;
1185                                 break;
1186                         case AST_PRES_USER_NUMBER_FAILED_SCREEN:
1187                                 newbc->screen=2;
1188                                 break;
1189                                 
1190                         case AST_PRES_NETWORK_NUMBER:
1191                                 newbc->screen=3;
1192                                 break;
1193                                 
1194                         default:
1195                                 newbc->screen=0;
1196                         }
1197                 }
1198
1199                 
1200                 {
1201                         int ec, ectr;
1202                         
1203                         misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
1204                         
1205                         misdn_cfg_get( port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int));
1206                         if (ec == 1 ) {
1207                                 newbc->ec_enable=1;
1208                         } else if ( ec > 1 ) {
1209                                 newbc->ec_enable=1;
1210                                 newbc->ec_deftaps=ec;
1211                         }
1212
1213                         if ( !ectr ) {
1214                                 newbc->ec_training=0;
1215                         }
1216                 }
1217                 
1218         } 
1219         
1220         chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten);
1221         if (ast->exten) {
1222                 int l = sizeof(newbc->dad);
1223                 strncpy(newbc->dad,ast->exten, l);
1224                 newbc->dad[l-1] = 0;
1225         }
1226         newbc->rad[0]=0;
1227         chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",AST_CID_P(ast));
1228         if (ast_strlen_zero(newbc->oad) && AST_CID_P(ast) ) {
1229                 if (AST_CID_P(ast)) {
1230                         int l = sizeof(newbc->oad);
1231                         strncpy(newbc->oad,AST_CID_P(ast), l);
1232                         newbc->oad[l-1] = 0;
1233                 }
1234         }
1235         
1236         {
1237                 struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
1238                 if (!ch) { ast_verbose("No chan_list in misdn_call"); return -1;}
1239                 ch->bc = newbc;
1240                 ch->orginator=ORG_AST;
1241                 ch->ast = ast;
1242                 
1243                 MISDN_ASTERISK_TECH_PVT(ast) = ch ;
1244                 
1245                 
1246       
1247                 newbc->capability=ast->transfercapability;
1248                 pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability));
1249                 if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
1250                         chan_misdn_log(2, port, " --> * Call with flag Digital\n");
1251                 }
1252                 
1253
1254                 /* Finally The Options Override Everything */
1255                 if (opts)
1256                         misdn_set_opt_exec(ast,opts);
1257                 else
1258                         chan_misdn_log(1,0,"NO OPTS GIVEN\n");
1259                 
1260                 
1261                 cl_queue_chan(&cl_te, ch) ;
1262                 ch->state=MISDN_CALLING;
1263
1264                 chan_misdn_trace_call(ast,1,"*->I: EVENT_CALL\n" );
1265                 
1266                 r=misdn_lib_send_event( newbc, EVENT_SETUP );
1267                 
1268                 /** we should have l3id after sending setup **/
1269                 ch->l3id=newbc->l3_id;
1270         }
1271         
1272         if ( r == -ENOCHAN  ) {
1273                 chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
1274                 chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n",newbc?newbc->pid:-1);
1275                 ast->hangupcause=34;
1276                 ast_setstate(ast, AST_STATE_DOWN);
1277                 return -1;
1278         }
1279         
1280         chan_misdn_log(1, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
1281
1282         ast_setstate(ast, AST_STATE_DIALING);
1283         
1284         ast->hangupcause=16;
1285         return 0; 
1286 }
1287
1288
1289 int misdn_answer(struct ast_channel *ast)
1290 {
1291         struct chan_list *p;
1292
1293         
1294         if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
1295         p = MISDN_ASTERISK_TECH_PVT(ast) ;
1296         
1297         chan_misdn_trace_call(ast,1,"*->I: EVENT_ANSWER\n");
1298         
1299         chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n");
1300         
1301         if (!p) {
1302                 ast_log(LOG_WARNING, " --> Channel not connected ??\n");
1303                 ast_queue_hangup(ast);
1304         }
1305
1306         if (!p->bc) {
1307                 chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n");
1308
1309                 ast_queue_hangup(ast);
1310         }
1311
1312         {
1313                 char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
1314                 
1315                 if (tmp_key ) {
1316                         chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
1317                         {
1318                                 int l = sizeof(p->bc->crypt_key);
1319                                 strncpy(p->bc->crypt_key,tmp_key, l);
1320                                 p->bc->crypt_key[l-1] = 0;
1321                         }
1322                 } else {
1323                         chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
1324                 }
1325     
1326         }
1327
1328         {
1329                 char *async=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
1330                 if (async) {
1331                         chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
1332                         p->bc->async=1;
1333                 }
1334         }
1335         
1336         p->state = MISDN_CONNECTED;
1337         misdn_lib_send_event( p->bc, EVENT_CONNECT);
1338         start_bc_tones(p);
1339         
1340         return 0;
1341 }
1342
1343 int misdn_digit(struct ast_channel *ast, char digit )
1344 {
1345         struct chan_list *p;
1346         
1347         if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
1348         p = MISDN_ASTERISK_TECH_PVT(ast) ;
1349         
1350
1351         struct misdn_bchannel *bc=p->bc;
1352         chan_misdn_log(1, bc?bc->port:0, "* IND : Digit %c\n",digit);
1353         
1354         if (!bc) {
1355                 ast_log(LOG_WARNING, " --> !! Got Digit Event withut having bchannel Object\n");
1356                 return -1;
1357         }
1358         
1359         switch (p->state ) {
1360                 case MISDN_CALLING:
1361                 {
1362                         
1363                         char buf[8];
1364                         buf[0]=digit;
1365                         buf[1]=0;
1366                         
1367                         int l = sizeof(bc->infos_pending);
1368                         strncat(bc->infos_pending,buf,l);
1369                         bc->infos_pending[l-1] = 0;
1370                 }
1371                 break;
1372                 case MISDN_CALLING_ACKNOWLEDGE:
1373                 {
1374                         bc->info_dad[0]=digit;
1375                         bc->info_dad[1]=0;
1376                         
1377                         {
1378                                 int l = sizeof(bc->dad);
1379                                 strncat(bc->dad,bc->info_dad, l - strlen(bc->dad));
1380                                 bc->dad[l-1] = 0;
1381                 }
1382                         {
1383                                 int l = sizeof(p->ast->exten);
1384                                 strncpy(p->ast->exten, bc->dad, l);
1385                                 p->ast->exten[l-1] = 0;
1386                         }
1387                         
1388                         misdn_lib_send_event( bc, EVENT_INFORMATION);
1389                 }
1390                 break;
1391                 
1392                 default:
1393                         if ( bc->send_dtmf ) {
1394                                 send_digit_to_chan(p,digit);
1395                         }
1396                 break;
1397         }
1398         
1399         return 0;
1400 }
1401
1402
1403 int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
1404 {
1405         struct chan_list *p;
1406         
1407         if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
1408         p = MISDN_ASTERISK_TECH_PVT(ast) ;
1409         
1410         chan_misdn_log(1, p->bc?p->bc->port:0, "* IND: Got Fixup State:%s Holded:%d L3id:%x\n", misdn_get_ch_state(p), p->holded, p->l3id);
1411         
1412         p->ast = ast ;
1413         p->state=MISDN_CONNECTED;
1414   
1415         return 0;
1416 }
1417
1418
1419 int misdn_transfer (struct ast_channel *ast, char *dest)
1420 {
1421         struct chan_list *p;
1422         
1423         if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
1424         p = MISDN_ASTERISK_TECH_PVT(ast) ;
1425
1426         chan_misdn_log(1, p->bc?p->bc->port:0, "* IND : Got Transfer %s\n",dest);
1427         return 0;
1428 }
1429
1430
1431
1432 int misdn_indication(struct ast_channel *ast, int cond)
1433 {
1434         struct chan_list *p;
1435
1436   
1437         if (!ast || ! MISDN_ASTERISK_PVT(ast)) {
1438                 ast_log(LOG_WARNING, "Returnded -1 in misdn_indication\n");
1439                 return -1;
1440         }
1441         p = MISDN_ASTERISK_TECH_PVT(ast) ;
1442         
1443         if (!p->bc ) {
1444                 chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten);
1445                 ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
1446                 return -1;
1447         }
1448         
1449         chan_misdn_log(1, p->bc->port, "* IND : Indication from %s\n",ast->exten);
1450         
1451         switch (cond) {
1452         case AST_CONTROL_BUSY:
1453                 chan_misdn_log(1, p->bc->port, "* IND :\tbusy\n");
1454                 chan_misdn_log(1, p->bc->port, " --> * SEND: State Busy pid:%d\n",p->bc?p->bc->pid:-1);
1455                 ast_setstate(ast,AST_STATE_BUSY);
1456                 
1457                 p->bc->out_cause=17;
1458                 if (p->state != MISDN_CONNECTED) {
1459                         misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
1460                         manager_send_tone(p->bc, TONE_BUSY);
1461                 } else {
1462                         chan_misdn_log(0, p->bc->port, " --> !! Got Busy in Connected State !?! port:%d ast:%s\n",
1463                                        p->bc->port, ast->name);
1464                 }
1465                 break;
1466         case AST_CONTROL_RING:
1467                 chan_misdn_log(1, p->bc->port, " --> * IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
1468                 break;
1469         case AST_CONTROL_RINGING:
1470                 if ( p->state == MISDN_ALERTING) {
1471                         chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d but I ws Ringing before, so ignoreing it\n",p->bc?p->bc->pid:-1);
1472                         break;
1473                 }
1474                 p->state=MISDN_ALERTING;
1475                 
1476                 chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
1477                 
1478                 misdn_lib_send_event( p->bc, EVENT_ALERTING);
1479                 
1480                 manager_send_tone(p->bc, TONE_ALERTING);
1481                 chan_misdn_log(1, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
1482                 ast_setstate(ast,AST_STATE_RINGING);
1483                 break;
1484                 
1485         case AST_CONTROL_ANSWER:
1486                 chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1);
1487                 break;
1488         case AST_CONTROL_TAKEOFFHOOK:
1489                 chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1);
1490                 break;
1491         case AST_CONTROL_OFFHOOK:
1492                 chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1);
1493                 break; 
1494         case AST_CONTROL_FLASH:
1495                 chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1);
1496                 break;
1497         case AST_CONTROL_PROGRESS:
1498                 chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n",p->bc?p->bc->pid:-1);
1499                 break;
1500         case AST_CONTROL_CONGESTION:
1501                 chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n",p->bc?p->bc->pid:-1);
1502
1503                 p->bc->out_cause=42;
1504                 if (p->state != MISDN_CONNECTED) {
1505                         start_bc_tones(p);
1506                         //misdn_lib_send_event( p->bc, EVENT_RELEASE_COMPLETE);
1507                         misdn_lib_send_event( p->bc, EVENT_RELEASE);
1508                 } else {
1509                         misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
1510                 }
1511                 if (p->bc->nt) {
1512                         manager_send_tone(p->bc, TONE_BUSY);
1513                 }
1514                 break;
1515         case -1 :
1516                 chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! pid:%d\n",p->bc?p->bc->pid:-1);
1517                 break;
1518         case AST_CONTROL_HOLD:
1519                 chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n",p->bc?p->bc->pid:-1);
1520                 break;
1521         case AST_CONTROL_UNHOLD:
1522                 chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1);
1523                 break;
1524         default:
1525                 ast_log(LOG_WARNING, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
1526         }
1527   
1528         return 0;
1529 }
1530
1531 int misdn_hangup(struct ast_channel *ast)
1532 {
1533         struct chan_list *p;
1534         struct misdn_bchannel *bc=NULL;
1535         
1536         if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
1537         p = MISDN_ASTERISK_TECH_PVT(ast) ;
1538
1539         release_lock;
1540
1541         chan_misdn_trace_call(ast,1,"*->I: EVENT_HANGUP cause=%d\n",ast->hangupcause);
1542         
1543         ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
1544         
1545         if (!p) {
1546                 chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
1547                 release_unlock;
1548                 return 0 ;
1549         }
1550         
1551         bc=p->bc;
1552
1553         if (!bc) {
1554                 release_unlock;
1555                 ast_log(LOG_WARNING,"Hangup with private but no bc ?\n");
1556                 return 0;
1557         }
1558
1559         
1560         MISDN_ASTERISK_TECH_PVT(ast)=NULL;
1561         p->ast=NULL;
1562
1563         if (ast->_state == AST_STATE_RESERVED) {
1564                 /* between request and call */
1565                 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
1566                 release_unlock;
1567                 
1568                 cl_dequeue_chan(&cl_te, p);
1569                 free(p);
1570
1571                 misdn_lib_release(bc);
1572                 
1573                 return 0;
1574         }
1575
1576         stop_bc_tones(p);
1577         
1578         release_unlock;
1579         
1580         
1581         
1582         
1583         
1584         
1585         {
1586                 char *varcause=NULL;
1587                 bc->cause=ast->hangupcause?ast->hangupcause:16;
1588                 
1589                 if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
1590                      (varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
1591                         int tmpcause=atoi(varcause);
1592                         bc->out_cause=tmpcause?tmpcause:16;
1593                 }
1594     
1595                 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));
1596                 chan_misdn_log(2, bc->port, " --> l3id:%x\n",p->l3id);
1597                 chan_misdn_log(1, bc->port, " --> cause:%d\n",bc->cause);
1598                 chan_misdn_log(1, bc->port, " --> out_cause:%d\n",bc->out_cause);
1599                 
1600                 switch (p->state) {
1601                 case MISDN_CALLING:
1602                         p->state=MISDN_CLEANING;
1603                         misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
1604                         break;
1605                 case MISDN_HOLDED:
1606                 case MISDN_DIALING:
1607                         start_bc_tones(p);
1608                         manager_send_tone(bc, TONE_BUSY);
1609                         p->state=MISDN_CLEANING;
1610                         
1611                         misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
1612       
1613                         break;
1614       
1615                 case MISDN_ALERTING:
1616                         chan_misdn_log(2, bc->port, " --> * State Alerting\n");
1617
1618                         if (p->orginator != ORG_AST) 
1619                                 manager_send_tone(bc, TONE_BUSY);
1620       
1621                         p->state=MISDN_CLEANING;
1622                         misdn_lib_send_event( bc, EVENT_DISCONNECT);
1623                         break;
1624                 case MISDN_CONNECTED:
1625                         /*  Alerting or Disconect */
1626                         chan_misdn_log(2, bc->port, " --> * State Connected\n");
1627                         start_bc_tones(p);
1628                         manager_send_tone(bc, TONE_BUSY);
1629                         misdn_lib_send_event( bc, EVENT_DISCONNECT);
1630       
1631                         p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
1632                         break;
1633
1634                 case MISDN_CLEANING:
1635                         break;
1636       
1637                 case MISDN_HOLD_DISCONNECT:
1638                         /* need to send release here */
1639                         chan_misdn_log(2, bc->port, " --> state HOLD_DISC\n");
1640                         chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause);
1641                         chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause);
1642                         
1643                         misdn_lib_send_event(bc,EVENT_RELEASE);
1644                         break;
1645                 default:
1646                         /*  Alerting or Disconect */
1647                         if (bc->nt)
1648                                 misdn_lib_send_event(bc, EVENT_RELEASE);
1649                         else
1650                                 misdn_lib_send_event(bc, EVENT_DISCONNECT);
1651                         p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
1652                 }
1653     
1654         }
1655         
1656         chan_misdn_log(1, bc->port, "Channel: %s hanguped\n",ast->name);
1657         
1658         return 0;
1659 }
1660
1661 struct ast_frame  *misdn_read(struct ast_channel *ast)
1662 {
1663         struct chan_list *tmp;
1664         
1665         char blah[255];
1666         int len =0 ;
1667         
1668         if (!ast) return NULL;
1669         tmp = MISDN_ASTERISK_TECH_PVT(ast);
1670         if (!tmp) return NULL;
1671         if (!tmp->bc) return NULL;
1672         
1673         
1674         read(tmp->pipe[0],blah,sizeof(blah));
1675         
1676         
1677         len = misdn_ibuf_usedcount(tmp->bc->astbuf);
1678
1679         /*shrinken len if necessary, we transmit at maximum 4k*/
1680         len = len<=sizeof(tmp->ast_rd_buf)?len:sizeof(tmp->ast_rd_buf);
1681         
1682         misdn_ibuf_memcpy_r(tmp->ast_rd_buf, tmp->bc->astbuf,len);
1683         
1684         tmp->frame.frametype  = AST_FRAME_VOICE;
1685         tmp->frame.subclass = AST_FORMAT_ALAW;
1686         tmp->frame.datalen = len;
1687         tmp->frame.samples = len ;
1688         tmp->frame.mallocd =0 ;
1689         tmp->frame.offset= 0 ;
1690         tmp->frame.src = NULL;
1691         tmp->frame.data = tmp->ast_rd_buf ;
1692
1693         chan_misdn_trace_call(tmp->ast,3,"*->I: EVENT_READ len=%d\n",len);
1694         return &tmp->frame;
1695 }
1696
1697 int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
1698 {
1699         struct chan_list *p;
1700         int i  = 0;
1701         
1702         if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
1703         p = MISDN_ASTERISK_TECH_PVT(ast) ;
1704         
1705         if (!p->bc ) {
1706                 ast_log(LOG_WARNING, "private but no bc\n");
1707                 return -1;
1708         }
1709         
1710         if (p->bc->tone != TONE_NONE)
1711                 manager_send_tone(p->bc,TONE_NONE);
1712         
1713         
1714         if (p->holded ) {
1715                 chan_misdn_log(5, p->bc->port, "misdn_write: Returning because holded\n");
1716                 return 0;
1717         }
1718         
1719         if (p->notxtone) {
1720                 chan_misdn_log(5, p->bc->port, "misdn_write: Returning because notxone\n");
1721                 return 0;
1722         }
1723         
1724         if ( !(frame->subclass & prefformat)) {
1725                 chan_misdn_log(0, p->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
1726         }
1727         
1728         
1729 #if MISDN_DEBUG
1730         {
1731                 int i, max=5>frame->samples?frame->samples:5;
1732                 
1733                 printf("write2mISDN %p %d bytes: ", p, frame->samples);
1734                 
1735                 for (i=0; i<  max ; i++) printf("%2.2x ",((char*) frame->data)[i]);
1736                 printf ("\n");
1737         }
1738 #endif
1739         chan_misdn_trace_call(ast,3,"*->I: EVENT_WRITE len=%d\n",frame->samples);
1740         i= manager_tx2misdn_frm(p->bc, frame->data, frame->samples);
1741         
1742         return 0;
1743 }
1744
1745
1746 enum ast_bridge_result  misdn_bridge (struct ast_channel *c0,
1747                                       struct ast_channel *c1, int flags,
1748                                       struct ast_frame **fo,
1749                                       struct ast_channel **rc,
1750                                       int timeoutms)
1751
1752 {
1753         struct chan_list *ch1,*ch2;
1754         struct ast_channel *carr[2], *who;
1755         int to=-1;
1756         struct ast_frame *f;
1757   
1758         ch1=get_chan_by_ast(c0);
1759         ch2=get_chan_by_ast(c1);
1760
1761         carr[0]=c0;
1762         carr[1]=c1;
1763   
1764   
1765         if (ch1 && ch2 ) ;
1766         else
1767                 return -1;
1768   
1769
1770         int bridging;
1771         misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
1772         if (bridging) {
1773                 int ecwb;
1774                 misdn_cfg_get( ch1->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
1775                 if ( !ecwb ) {
1776                         chan_misdn_log(0, ch1->bc->port, "Disabling Echo Cancellor when Bridged\n");
1777                         ch1->bc->ec_enable=0;
1778                         manager_ec_disable(ch1->bc);
1779                 }
1780                 misdn_cfg_get( ch2->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
1781                 if ( !ecwb ) {
1782                         chan_misdn_log(0, ch2->bc->port, "Disabling Echo Cancellor when Bridged\n");
1783                         ch2->bc->ec_enable=0;
1784                         manager_ec_disable(ch2->bc);
1785                 }
1786                 
1787                 /* trying to make a mISDN_dsp conference */
1788                 chan_misdn_log(0, ch1->bc->port, "I SEND: Making conference with Number:%d\n", (ch1->bc->pid<<1) +1);
1789
1790                 misdn_lib_bridge(ch1->bc,ch2->bc);
1791         }
1792         
1793         chan_misdn_log(1, ch1->bc->port, "* Makeing Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
1794   
1795         while(1) {
1796                 to=-1;
1797                 who = ast_waitfor_n(carr, 2, &to);
1798
1799                 if (!who) {
1800                         ast_log(LOG_DEBUG,"misdn_bridge: empty read\n");
1801                         continue;
1802                 }
1803                 f = ast_read(who);
1804     
1805                 if (!f || f->frametype == AST_FRAME_CONTROL) {
1806                         /* got hangup .. */
1807                         *fo=f;
1808                         *rc=who;
1809       
1810                         break;
1811                 }
1812     
1813     
1814                 if (who == c0) {
1815                         ast_write(c1,f);
1816                 }
1817                 else {
1818                         ast_write(c0,f);
1819                 }
1820     
1821         }
1822   
1823         if (bridging) {
1824                 misdn_lib_split_bridge(ch1->bc,ch2->bc);
1825         }
1826   
1827         return 0;
1828 }
1829
1830 /** AST INDICATIONS END **/
1831
1832 static int start_bc_tones(struct chan_list* cl)
1833 {
1834         manager_bchannel_activate(cl->bc);
1835         manager_send_tone(cl->bc ,TONE_NONE);
1836         cl->notxtone=0;
1837         cl->norxtone=0;
1838         return 0;
1839 }
1840
1841 static int stop_bc_tones(struct chan_list *cl)
1842 {
1843         if (cl->bc) {
1844                 manager_bchannel_deactivate(cl->bc);
1845         }
1846         cl->notxtone=1;
1847         cl->norxtone=1;
1848         
1849         return 0;
1850 }
1851
1852
1853 struct chan_list *init_chan_list(void)
1854 {
1855         struct chan_list *cl=malloc(sizeof(struct chan_list));
1856         
1857         if (!cl) {
1858                 chan_misdn_log(0, 0, "misdn_request: malloc failed!");
1859                 return NULL;
1860         }
1861         
1862         memset(cl,0,sizeof(struct chan_list));
1863         
1864         return cl;
1865         
1866 }
1867
1868 static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
1869
1870 {
1871         struct ast_channel *tmp = NULL;
1872         char group[BUFFERSIZE]="";
1873         char buf[128];
1874         char buf2[128], *ext=NULL, *port_str;
1875         char *tokb=NULL, *p=NULL;
1876         int channel=0, port=0;
1877         struct misdn_bchannel *newbc = NULL;
1878         
1879         struct chan_list *cl=init_chan_list();
1880         
1881         sprintf(buf,"%s/%s",type,(char*)data);
1882         strncpy(buf2,data, 128);
1883         buf2[127] = 0;
1884         port_str=strtok_r(buf2,"/", &tokb);
1885
1886         ext=strtok_r(NULL,"/", &tokb);
1887
1888         /*
1889           if (!ext) {
1890           ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITH WRONG ARGS, check extension.conf\n",ext);
1891           
1892           return NULL;
1893           }
1894         */
1895         
1896         if (port_str) {
1897                 if (port_str[0]=='g' && port_str[1]==':' ) {
1898                         /* We make a group call lets checkout which ports are in my group */
1899                         port_str += 2;
1900                         strncpy(group, port_str, BUFFERSIZE);
1901                         group[127] = 0;
1902                         chan_misdn_log(2, 0, " --> Group Call group: %s\n",group);
1903                 } 
1904                 else if ((p = strchr(port_str, ':'))) {
1905                         // we have a preselected channel
1906                         *p = 0;
1907                         channel = atoi(++p);
1908                         port = atoi(port_str);
1909                         chan_misdn_log(2, port, " --> Call on preselected Channel (%d) on Port %d\n", channel, port);
1910                 }
1911                 else {
1912                         port = atoi(port_str);
1913                 }
1914                 
1915                 
1916         } else {
1917                 ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extension.conf\n",ext);
1918                 return NULL;
1919         }
1920
1921         if (!ast_strlen_zero(group)) {
1922         
1923                 char cfg_group[BUFFERSIZE];
1924                 struct robin_list *rr = NULL;
1925
1926                 if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
1927                         chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...");
1928                         rr = get_robin_position(group);
1929                 }
1930                 
1931                 if (rr) {
1932                         int robin_channel = rr->channel;
1933                         int port_start;
1934                         int next_chan = 1;
1935
1936                         do {
1937                                 port_start = 0;
1938                                 for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start;
1939                                          port = misdn_cfg_get_next_port_spin(port)) {
1940
1941                                         if (!port_start)
1942                                                 port_start = port;
1943
1944                                         if (port >= port_start)
1945                                                 next_chan = 1;
1946                                         
1947                                         if (port < port_start && next_chan) {
1948                                                 if (++robin_channel >= MAX_BCHANS) {
1949                                                         robin_channel = 1;
1950                                                 }
1951                                                 next_chan = 0;
1952                                         }
1953
1954                                         misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
1955                                         
1956                                         if (!strcasecmp(cfg_group, group)) {
1957                                                 int l1, port_up;
1958                                         
1959                                                 misdn_cfg_get( 0, MISDN_GEN_L1_INFO_OK, &l1, sizeof(l1));
1960                                                 port_up = misdn_lib_port_up(port);
1961                                                 
1962                                                 if ((l1 && port_up) || !l1)     {
1963                                                         newbc = misdn_lib_get_free_bc(port, robin_channel);
1964                                                         if (newbc) {
1965                                                                 chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
1966                                                                 if (port_up)
1967                                                                         chan_misdn_log(4, port, "def_l1:%d, portup:%d\n", l1, port_up);
1968                                                                 rr->port = newbc->port;
1969                                                                 rr->channel = newbc->channel;
1970                                                                 break;
1971                                                         }
1972                                                 }
1973                                         }
1974                                 }
1975                         } while (!newbc && robin_channel != rr->channel);
1976                         
1977                         if (!newbc)
1978                                 chan_misdn_log(4, port, " Failed! No free channel in group %d!", group);
1979                 }
1980                 
1981                 else {          
1982                         for (port=misdn_cfg_get_next_port(0); port > 0;
1983                                  port=misdn_cfg_get_next_port(port)) {
1984                                 
1985                                 misdn_cfg_get( port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
1986                                 
1987                                 if (!strcasecmp(cfg_group, group)) {
1988                                         int l1, port_up;
1989                                         
1990                                         misdn_cfg_get( 0, MISDN_GEN_L1_INFO_OK, &l1, sizeof(l1));
1991                                         port_up = misdn_lib_port_up(port);
1992
1993                                         chan_misdn_log(4, port, "def_l1:%d, portup:%d\n", l1, port_up);
1994                                         
1995                                         if ((l1 && port_up) || !l1)     {
1996                                                 newbc = misdn_lib_get_free_bc(port, 0);
1997                                                 if (newbc)
1998                                                         break;
1999                                         }
2000                                 }
2001                         }
2002                 }
2003                 
2004         } else {
2005                 if (channel)
2006                         chan_misdn_log(1, port," --> preselected_channel: %d\n",channel);
2007                 newbc = misdn_lib_get_free_bc(port, channel);
2008         }
2009         
2010         if (!newbc) {
2011                 chan_misdn_log(1, 0, " --> ! No free channel chan ext:%s even after Group Call\n",ext);
2012                 chan_misdn_log(1, 0, " --> SEND: State Down\n");
2013                 return NULL;
2014         }
2015         
2016         cl->bc=newbc;
2017         
2018         tmp = misdn_new(cl, AST_STATE_RESERVED, buf, "default", ext, ext, format, port, channel);
2019         
2020         return tmp;
2021 }
2022
2023
2024 struct ast_channel_tech misdn_tech = {
2025         .type="mISDN",
2026         .description="Channel driver for mISDN Support (Bri/Pri)",
2027         .capabilities= AST_FORMAT_ALAW ,
2028         .requester=misdn_request,
2029         .send_digit=misdn_digit,
2030         .call=misdn_call,
2031         .bridge=misdn_bridge, 
2032         .hangup=misdn_hangup,
2033         .answer=misdn_answer,
2034         .read=misdn_read,
2035         .write=misdn_write,
2036         .indicate=misdn_indication,
2037         .fixup=misdn_fixup,
2038         .properties=0
2039         /* .transfer=misdn_transfer */
2040 };
2041
2042 struct ast_channel_tech misdn_tech_wo_bridge = {
2043         .type="mISDN",
2044         .description="Channel driver for mISDN Support (Bri/Pri)",
2045         .capabilities=AST_FORMAT_ALAW ,
2046         .requester=misdn_request,
2047         .send_digit=misdn_digit,
2048         .call=misdn_call,
2049         .hangup=misdn_hangup,
2050         .answer=misdn_answer,
2051         .read=misdn_read,
2052         .write=misdn_write,
2053         .indicate=misdn_indication,
2054         .fixup=misdn_fixup,
2055         .properties=0
2056         /* .transfer=misdn_transfer */
2057 };
2058
2059
2060 unsigned long glob_channel=0;
2061
2062 struct ast_channel *misdn_new(struct chan_list *chlist, int state, char * name, char * context, char *exten, char *callerid, int format, int port, int c)
2063 {
2064         struct ast_channel *tmp;
2065         
2066         tmp = ast_channel_alloc(1);
2067         
2068         if (tmp) {
2069                 chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s ctx:%s\n",exten,callerid, context);
2070                 
2071                 
2072                 if (c<=0) {
2073                         c=glob_channel++;
2074                         snprintf(tmp->name, sizeof(tmp->name), "%s/%d-u%d",
2075                                  type, port, c);
2076                 } else {
2077                         snprintf(tmp->name, sizeof(tmp->name), "%s/%d-%d",
2078                                  type, port, c);
2079                 }
2080                 
2081                 tmp->type = type;
2082     
2083                 tmp->nativeformats = prefformat;
2084                 tmp->readformat = format;
2085                 tmp->writeformat = format;
2086     
2087                 tmp->tech_pvt = chlist;
2088
2089                 int bridging;
2090                 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
2091                 if (bridging)
2092                         tmp->tech = &misdn_tech;
2093                 else
2094                         tmp->tech = &misdn_tech_wo_bridge;
2095     
2096     
2097                 tmp->writeformat = format;
2098                 tmp->readformat = format;
2099                 tmp->priority=1;
2100     
2101                 
2102                 if (context)
2103                         ast_copy_string(tmp->context, context, sizeof(tmp->context));
2104                 else
2105                         chan_misdn_log(1,0,"misdn_new: no context given.\n");
2106                 if (exten) 
2107                         ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
2108                 else
2109                         chan_misdn_log(1,0,"misdn_new: no exten given.\n");
2110
2111                 if (callerid) {
2112                         char *cid_name, *cid_num;
2113       
2114                         ast_callerid_parse(callerid, &cid_name, &cid_num);
2115                         if (cid_name)
2116                                 tmp->cid.cid_name=strdup(cid_name);
2117                         if (cid_num)
2118                                 tmp->cid.cid_num=strdup(cid_num);
2119                 }
2120
2121                 {
2122                         if (pipe(chlist->pipe)<0)
2123                                 perror("Pipe failed\n");
2124                         
2125                         tmp->fds[0]=chlist->pipe[0];
2126                         
2127                 }
2128                 
2129                 if (chlist->bc) {
2130                         int port=chlist->bc->port;
2131                         misdn_cfg_get( port, MISDN_CFG_LANGUAGE, tmp->language, sizeof(tmp->language));
2132                         
2133                         {
2134                                 char buf[256];
2135                                 ast_group_t pg,cg;
2136                                 
2137                                 misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
2138                                 misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
2139                                 
2140                                 chan_misdn_log(2, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
2141                                 tmp->pickupgroup=pg;
2142                                 tmp->callgroup=cg;
2143                         }
2144                         misdn_cfg_get(port, MISDN_CFG_TXGAIN, &chlist->bc->txgain, sizeof(int));
2145                         misdn_cfg_get(port, MISDN_CFG_RXGAIN, &chlist->bc->rxgain, sizeof(int));
2146                         chan_misdn_log(2, port, " --> rxgain:%d txgain:%d\n",chlist->bc->rxgain,chlist->bc->txgain);
2147                         
2148                 } else {
2149                         chan_misdn_log(3, 0, " --> Not Setting Pickupgroup, we have no bc yet\n");
2150                 }
2151                 
2152                 ast_setstate(tmp, state);
2153                 if (state == AST_STATE_RING)
2154                         tmp->rings = 1;
2155                 else
2156                         tmp->rings = 0;
2157         } else {
2158                 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
2159                 chan_misdn_log(0,0,"Unable to allocate channel structure\n");
2160         }
2161         
2162         return tmp;
2163 }
2164
2165
2166
2167 int misdn_tx2ast_frm(struct chan_list * tmp, char * buf,  int len )
2168 {
2169         struct ast_frame frame;
2170         
2171         /* If in hold state we drop frame .. */
2172         if (tmp->holded ) return 0;
2173
2174         switch(tmp->state) {
2175         case MISDN_CLEANING:
2176         case MISDN_EXTCANTMATCH:
2177         case MISDN_WAITING4DIGS:
2178                 return 0;
2179         default:
2180                 break;
2181         }
2182         
2183         if (tmp->norxtone) {
2184                 chan_misdn_log(3, tmp->bc->port, "misdn_tx2ast_frm: Returning because norxtone\n");
2185                 return 0;
2186         }
2187         
2188         frame.frametype  = AST_FRAME_VOICE;
2189         frame.subclass = AST_FORMAT_ALAW;
2190         frame.datalen = len;
2191         frame.samples = len ;
2192         frame.mallocd =0 ;
2193         frame.offset= 0 ;
2194         frame.src = NULL;
2195         frame.data = buf ;
2196         
2197         if (tmp->faxdetect || tmp->ast_dsp ) {
2198                 struct ast_frame *f,*f2;
2199                 if (tmp->trans)
2200                         f2=ast_translate(tmp->trans, &frame,0);
2201                 else {
2202                         chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
2203                         return 0;
2204                 }
2205                 
2206                 f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
2207                 if (f && (f->frametype == AST_FRAME_DTMF)) {
2208                         ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c", f->subclass);
2209                         if (f->subclass == 'f' && tmp->faxdetect) {
2210                                 /* Fax tone -- Handle and return NULL */
2211                                 struct ast_channel *ast = tmp->ast;
2212                                 if (!tmp->faxhandled) {
2213                                         tmp->faxhandled++;
2214                                         if (strcmp(ast->exten, "fax")) {
2215                                                 if (ast_exists_extension(ast, ast_strlen_zero(ast->macrocontext)? ast->context : ast->macrocontext, "fax", 1, AST_CID_P(ast))) {
2216                                                         if (option_verbose > 2)
2217                                                                 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
2218                                                         /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
2219                                                         pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
2220                                                         if (ast_async_goto(ast, ast->context, "fax", 1))
2221                                                                 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, ast->context);
2222                                                 } else
2223                                                         ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n",ast->context, ast->exten);
2224                                         } else
2225                                                 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
2226                                 } else
2227                                         ast_log(LOG_DEBUG, "Fax already handled\n");
2228                                 frame.frametype = AST_FRAME_NULL;
2229                                 frame.subclass = 0;
2230                                 f = &frame;
2231                         }  else if ( tmp->ast_dsp) {
2232                                 struct ast_frame fr;
2233                                 memset(&fr, 0 , sizeof(fr));
2234                                 fr.frametype = AST_FRAME_DTMF;
2235                                 fr.subclass = f->subclass ;
2236                                 fr.src=NULL;
2237                                 fr.data = NULL ;
2238                                 fr.datalen = 0;
2239                                 fr.samples = 0 ;
2240                                 fr.mallocd =0 ;
2241                                 fr.offset= 0 ;
2242                                 
2243                                 chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n",f->subclass);
2244                                 ast_queue_frame(tmp->ast, &fr);
2245                                 
2246                                 frame.frametype = AST_FRAME_NULL;
2247                                 frame.subclass = 0;
2248                                 f = &frame;
2249                         }
2250                 }
2251         }
2252         
2253         if (tmp && tmp->ast && MISDN_ASTERISK_PVT (tmp->ast) && MISDN_ASTERISK_TECH_PVT(tmp->ast) ) {
2254 #if MISDN_DEBUG
2255                 int i, max=5>len?len:5;
2256     
2257                 printf("write2* %p %d bytes: ",tmp, len);
2258     
2259                 for (i=0; i<  max ; i++) printf("%2.2x ",((char*) frame.data)[i]);
2260                 printf ("\n");
2261 #endif
2262                 chan_misdn_log(9, tmp->bc->port, "Queueing %d bytes 2 Asterisk\n",len);
2263                 ast_queue_frame(tmp->ast,&frame);
2264                 
2265         }  else {
2266                 ast_log (LOG_WARNING, "No ast || ast->pvt || ch\n");
2267         }
2268         
2269         return 0;
2270 }
2271
2272 /** Channel Queue ***/
2273
2274 struct chan_list *find_chan_by_l3id(struct chan_list *list, unsigned long l3id)
2275 {
2276         struct chan_list *help=list;
2277         for (;help; help=help->next) {
2278                 if (help->l3id == l3id ) return help;
2279         }
2280   
2281         chan_misdn_log(4, list? (list->bc? list->bc->port : 0) : 0, "$$$ find_chan: No channel found with l3id:%x\n",l3id);
2282   
2283         return NULL;
2284 }
2285
2286 struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
2287 {
2288         struct chan_list *help=list;
2289         for (;help; help=help->next) {
2290                 if (help->bc == bc) return help;
2291         }
2292   
2293         chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
2294   
2295         return NULL;
2296 }
2297
2298
2299 struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
2300 {
2301         struct chan_list *help=list;
2302         
2303         chan_misdn_log(4, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
2304         for (;help; help=help->next) {
2305                 chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->bc->holded, help->bc->channel);
2306                 if (help->bc->port == bc->port
2307                     && help->bc->holded ) return help;
2308         }
2309         
2310         chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
2311   
2312         return NULL;
2313 }
2314
2315 void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
2316 {
2317         chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan);
2318   
2319         ast_mutex_lock(&cl_te_lock);
2320         if (!*list) {
2321                 *list = chan;
2322         } else {
2323                 struct chan_list *help=*list;
2324                 for (;help->next; help=help->next); 
2325                 help->next=chan;
2326         }
2327         chan->next=NULL;
2328         ast_mutex_unlock(&cl_te_lock);
2329 }
2330
2331 void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan) 
2332 {
2333         if (chan->dsp) 
2334                 ast_dsp_free(chan->dsp);
2335         if (chan->trans)
2336                 ast_translator_free_path(chan->trans);
2337         
2338
2339         ast_mutex_lock(&cl_te_lock);
2340         if (!*list) {
2341                 ast_mutex_unlock(&cl_te_lock);
2342                 return;
2343         }
2344   
2345         if (*list == chan) {
2346                 *list=(*list)->next;
2347                 ast_mutex_unlock(&cl_te_lock);
2348                 return ;
2349         }
2350   
2351         {
2352                 struct chan_list *help=*list;
2353                 for (;help->next; help=help->next) {
2354                         if (help->next == chan) {
2355                                 help->next=help->next->next;
2356                                 ast_mutex_unlock(&cl_te_lock);
2357                                 return;
2358                         }
2359                 }
2360         }
2361         
2362         ast_mutex_unlock(&cl_te_lock);
2363 }
2364
2365 /** Channel Queue End **/
2366
2367
2368
2369 /** Isdn asks us to release channel, pendant to misdn_hangup **/
2370 static void release_chan(struct misdn_bchannel *bc) {
2371         struct ast_channel *ast=NULL;
2372         
2373         {
2374                 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
2375                 if (!ch) ch=find_chan_by_l3id (cl_te, bc->l3_id);
2376                 
2377                 release_lock;
2378                 if (ch->ast) {
2379                         ast=ch->ast;
2380                 } 
2381                 release_unlock;
2382                 
2383                 chan_misdn_log(1, bc->port, "Trying to Release bc with l3id: %x\n",bc->l3_id);
2384                 if (ch) {
2385                         if (ast)
2386                                 chan_misdn_trace_call(ast,1,"I->*: EVENT_RELEASE\n");
2387                         
2388                         close(ch->pipe[0]);
2389                         close(ch->pipe[1]);
2390                         
2391                         if (ast && MISDN_ASTERISK_PVT(ast)) {
2392                                 chan_misdn_log(1, bc->port, "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s state: %s\n",bc?bc->pid:-1, ast->context, ast->exten,AST_CID_P(ast),misdn_get_ch_state(ch));
2393                                 chan_misdn_log(3, bc->port, " --> * State Down\n");
2394                                 /* copy cause */
2395                                 send_cause2ast(ast,bc);
2396                                 
2397                                 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
2398                                 
2399       
2400                                 if (ast->_state != AST_STATE_RESERVED) {
2401                                         chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
2402                                         ast_setstate(ast, AST_STATE_DOWN);
2403                                 }
2404                                 
2405                                 switch(ch->state) {
2406                                 case MISDN_EXTCANTMATCH:
2407                                 case MISDN_WAITING4DIGS:
2408                                 {
2409                                         chan_misdn_log(3,  bc->port, " --> * State Wait4dig | ExtCantMatch\n");
2410                                         ast_hangup(ast);
2411                                 }
2412                                 break;
2413                                 
2414                                 case MISDN_DIALING:
2415                                 case MISDN_CALLING_ACKNOWLEDGE:
2416                                 case MISDN_PROGRESS:
2417                                         chan_misdn_log(2,  bc->port, "* --> In State Dialin\n");
2418                                         chan_misdn_log(2,  bc->port, "* --> Queue Hangup\n");
2419                                         
2420
2421                                         ast_queue_hangup(ast);
2422                                         break;
2423                                 case MISDN_CALLING:
2424                                         
2425                                         chan_misdn_log(2,  bc->port, "* --> In State Callin\n");
2426                                         
2427                                         if (!bc->nt) {
2428                                                 chan_misdn_log(2,  bc->port, "* --> Queue Hangup\n");
2429                                                 ast_queue_hangup(ast);
2430                                         } else {
2431                                                 chan_misdn_log(2,  bc->port, "* --> Hangup\n");
2432                                                 ast_queue_hangup(ast);
2433                                                 //ast_hangup(ast);
2434                                         }
2435                                         break;
2436                                         
2437                                 case MISDN_CLEANING:
2438                                         /* this state comes out of ast so we mustnt call a ast function ! */
2439                                         chan_misdn_log(2,  bc->port, "* --> In StateCleaning\n");
2440                                         break;
2441                                 case MISDN_HOLD_DISCONNECT:
2442                                         chan_misdn_log(2,  bc->port, "* --> In HOLD_DISC\n");
2443                                         break;
2444                                 default:
2445                                         chan_misdn_log(2,  bc->port, "* --> In State Default\n");
2446                                         chan_misdn_log(2,  bc->port, "* --> Queue Hangup\n");
2447         
2448                                         
2449                                         if (ast && MISDN_ASTERISK_PVT(ast)) {
2450                                                 ast_queue_hangup(ast);
2451                                         } else {
2452                                                 chan_misdn_log (0,  bc->port, "!! Not really queued!\n");
2453                                         }
2454                                 }
2455                         }
2456                         cl_dequeue_chan(&cl_te, ch);
2457                         
2458                         free(ch);
2459                 } else {
2460                         /* chan is already cleaned, so exiting  */
2461                 }
2462         }
2463 }
2464 /*** release end **/
2465
2466 void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
2467 {
2468         chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan->ast->name, tmp_ch->ast->name);
2469         
2470         tmp_ch->state=MISDN_HOLD_DISCONNECT;
2471   
2472         ast_moh_stop(AST_BRIDGED_P(holded_chan->ast));
2473
2474         holded_chan->state=MISDN_CONNECTED;
2475         holded_chan->holded=0;
2476         misdn_lib_transfer(holded_chan->bc?holded_chan->bc:holded_chan->holded_bc);
2477         
2478         ast_channel_masquerade(holded_chan->ast, AST_BRIDGED_P(tmp_ch->ast));
2479 }
2480
2481
2482 void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast)
2483 {
2484         char predial[256]="";
2485         char *p = predial;
2486   
2487         struct ast_frame fr;
2488   
2489         strncpy(predial, ast->exten, sizeof(predial) -1 );
2490   
2491         ch->state=MISDN_DIALING;
2492         
2493         if (bc->nt) {
2494                 int ret; 
2495                 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
2496         } else {
2497                 int ret;
2498                 if ( misdn_lib_is_ptp(bc->port)) {
2499                         ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
2500                 } else {
2501                         ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
2502                 }
2503         }
2504
2505         manager_send_tone(bc,TONE_DIAL);  
2506   
2507         chan_misdn_log(1, bc->port, "* Starting Ast ctx:%s dad:%s oad:%s with 's' extension\n", ast->context, ast->exten, AST_CID_P(ast));
2508   
2509         strncpy(ast->exten,"s", 2);
2510   
2511         if (ast_pbx_start(ast)<0) {
2512                 ast=NULL;
2513                 manager_send_tone(bc,TONE_BUSY);
2514                 if (bc->nt)
2515                         misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
2516                 else
2517                         misdn_lib_send_event(bc, EVENT_DISCONNECT );
2518         }
2519   
2520   
2521         while (!ast_strlen_zero(p) ) {
2522                 fr.frametype = AST_FRAME_DTMF;
2523                 fr.subclass = *p ;
2524                 fr.src=NULL;
2525                 fr.data = NULL ;
2526                 fr.datalen = 0;
2527                 fr.samples = 0 ;
2528                 fr.mallocd =0 ;
2529                 fr.offset= 0 ;
2530
2531                 if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
2532                         ast_queue_frame(ch->ast, &fr);
2533                 }
2534                 p++;
2535         }
2536 }
2537
2538
2539
2540 void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc) {
2541         
2542         ast->hangupcause=bc->cause;
2543         
2544         switch ( bc->cause) {
2545                 
2546         case 1: /** Congestion Cases **/
2547         case 2:
2548         case 3:
2549         case 4:
2550         case 22:
2551         case 27:
2552                 chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Congestion pid:%d\n", bc?bc->pid:-1);
2553                 
2554                 ast_queue_control(ast, AST_CONTROL_CONGESTION);
2555                 break;
2556                 
2557         case 21:
2558         case 17: /* user busy */
2559                 chan_misdn_log(1,  bc?bc->port:0, " --> * SEND: Queue Busy pid:%d\n", bc?bc->pid:-1);
2560                 
2561                 ast_queue_control(ast, AST_CONTROL_BUSY);
2562                 
2563                 break;
2564         }
2565 }
2566
2567 /************************************************************/
2568 /*  Receive Events from isdn_lib  here                     */
2569 /************************************************************/
2570 enum event_response_e
2571 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
2572 {
2573         struct chan_list *ch=find_chan_by_bc(cl_te, bc);
2574         
2575         if (!ch)
2576                 ch=find_chan_by_l3id(cl_te, bc->l3_id);
2577         
2578         if (event != EVENT_BCHAN_DATA) { /*  Debug Only Non-Bchan */
2579                 chan_misdn_log(1, bc->port, "I IND :%s oad:%s dad:%s port:%d\n", manager_isdn_get_info(event), bc->oad, bc->dad, bc->port);
2580                 misdn_lib_log_ies(bc);
2581         }
2582         
2583         if (event != EVENT_SETUP) {
2584                 if (!ch) {
2585                         if (event != EVENT_CLEANUP )
2586                                 ast_log(LOG_WARNING, "Chan not existing at the moment bc->l3id:%x bc:%p event:%s port:%d channel:%d\n",bc->l3_id, bc, manager_isdn_get_info( event), bc->port,bc->channel);
2587                         return -1;
2588                 }
2589         }
2590         
2591         if (ch ) {
2592                 switch (event) {
2593                 case EVENT_RELEASE:
2594                 case EVENT_RELEASE_COMPLETE:
2595                 case EVENT_CLEANUP:
2596                         break;
2597                 default:
2598                         if ( !ch->ast  || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
2599                                 if (event!=EVENT_BCHAN_DATA)
2600                                         ast_log(LOG_WARNING, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
2601                                 return -1;
2602                         }
2603                 }
2604         }
2605         
2606         
2607         switch (event) {
2608         case EVENT_NEW_L3ID:
2609                 ch->l3id=bc->l3_id;
2610                 break;
2611
2612         case EVENT_NEW_BC:
2613                 if (bc)
2614                         ch->bc=bc;
2615                 break;
2616                 
2617         case EVENT_DTMF_TONE:
2618         {
2619                 /*  sending INFOS as DTMF-Frames :) */
2620                 struct ast_frame fr;
2621                 memset(&fr, 0 , sizeof(fr));
2622                 fr.frametype = AST_FRAME_DTMF;
2623                 fr.subclass = bc->dtmf ;
2624                 fr.src=NULL;
2625                 fr.data = NULL ;
2626                 fr.datalen = 0;
2627                 fr.samples = 0 ;
2628                 fr.mallocd =0 ;
2629                 fr.offset= 0 ;
2630                 
2631                 chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
2632                 
2633                 ast_queue_frame(ch->ast, &fr);
2634         }
2635         break;
2636         case EVENT_STATUS:
2637                 break;
2638     
2639         case EVENT_INFORMATION:
2640         {
2641                 int stop_tone;
2642                 misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
2643                 if ( stop_tone && bc->tone != TONE_NONE) {
2644                         manager_send_tone(bc,TONE_NONE);
2645                 }
2646                 
2647                 if (ch->state == MISDN_WAITING4DIGS ) {
2648                         /*  Ok, incomplete Setup, waiting till extension exists */
2649                         {
2650                                 int l = sizeof(bc->dad);
2651                                 strncat(bc->dad,bc->info_dad, l);
2652                                 bc->dad[l-1] = 0;
2653                         }
2654                         
2655                         
2656                         {
2657                                 int l = sizeof(ch->ast->exten);
2658                                 strncpy(ch->ast->exten, bc->dad, l);
2659                                 ch->ast->exten[l-1] = 0;
2660                         }
2661 /*                      chan_misdn_log(5, bc->port, "Can Match Extension: dad:%s oad:%s\n",bc->dad,bc->oad);*/
2662                         
2663                         char bc_context[BUFFERSIZE];
2664                         misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
2665                         if(!ast_canmatch_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
2666                                 chan_misdn_log(0, bc->port, "Extension can never match, so disconnecting\n");
2667                                 manager_send_tone(bc,TONE_BUSY);
2668                                 ch->state=MISDN_EXTCANTMATCH;
2669                                 bc->out_cause=1;
2670                                 if (bc->nt)
2671                                         misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
2672                                 else
2673                                         misdn_lib_send_event(bc, EVENT_DISCONNECT );
2674                                 break;
2675                         }
2676                         if (ast_exists_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
2677                                 ch->state=MISDN_DIALING;
2678           
2679                                 manager_send_tone(bc,TONE_NONE);
2680 /*                              chan_misdn_log(1, bc->port, " --> * Starting Ast ctx:%s\n", ch->ast->context);*/
2681                                 if (ast_pbx_start(ch->ast)<0) {
2682                                         chan_misdn_log(0, bc->port, "ast_pbx_start returned < 0 in INFO\n");
2683                                         manager_send_tone(bc,TONE_BUSY);
2684                                         if (bc->nt)
2685                                                 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
2686                                         else
2687                                                 misdn_lib_send_event(bc, EVENT_DISCONNECT );
2688                                 }
2689                         }
2690         
2691                 } else {
2692                         /*  sending INFOS as DTMF-Frames :) */
2693                         struct ast_frame fr;
2694                         fr.frametype = AST_FRAME_DTMF;
2695                         fr.subclass = bc->info_dad[0] ;
2696                         fr.src=NULL;
2697                         fr.data = NULL ;
2698                         fr.datalen = 0;
2699                         fr.samples = 0 ;
2700                         fr.mallocd =0 ;
2701                         fr.offset= 0 ;
2702
2703                         
2704                         int digits;
2705                         misdn_cfg_get( 0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
2706                         if (ch->state != MISDN_CONNECTED ) {
2707                                 if (digits) {
2708                                         int l = sizeof(bc->dad);
2709                                         strncat(bc->dad,bc->info_dad, l);
2710                                         bc->dad[l-1] = 0;
2711                                         l = sizeof(ch->ast->exten);
2712                                         strncpy(ch->ast->exten, bc->dad, l);
2713                                         ch->ast->exten[l-1] = 0;
2714
2715                                         ast_cdr_update(ch->ast);
2716                                 }
2717                                 
2718                                 ast_queue_frame(ch->ast, &fr);
2719                         }
2720                         
2721                 }
2722         }
2723         break;
2724         case EVENT_SETUP:
2725         {
2726                 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
2727                 if (ch && ch->state != MISDN_NOTHING ) {
2728                         chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
2729                         return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /*  Ignore MSNs which are not in our List */
2730                 }
2731         }
2732         
2733         int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
2734         if (!bc->nt && ! msn_valid) {
2735                 chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
2736                 return RESPONSE_IGNORE_SETUP; /*  Ignore MSNs which are not in our List */
2737         }
2738         
2739         print_bearer(bc);
2740     
2741         {
2742                 struct chan_list *ch=init_chan_list();
2743                 struct ast_channel *chan;
2744                 char name[128];
2745                 if (!ch) { chan_misdn_log(0, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;}
2746                 
2747                 ch->bc = bc;
2748                 ch->l3id=bc->l3_id;
2749                 ch->addr=bc->addr;
2750                 ch->orginator = ORG_MISDN;
2751
2752                 
2753                 {
2754                         char prefix[BUFFERSIZE]="";
2755                         switch( bc->onumplan ) {
2756                         case NUMPLAN_INTERNATIONAL:
2757                                 misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
2758                                 break;
2759           
2760                         case NUMPLAN_NATIONAL:
2761                                 misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
2762                                 break;
2763           
2764           
2765                         case NUMPLAN_SUBSCRIBER:
2766                                 /* dunno what to do here ? */
2767                                 break;
2768
2769                         case NUMPLAN_UNKNOWN:
2770                                 break;
2771                         default:
2772                                 break;
2773                         }
2774
2775                         {
2776                                 int l = strlen(prefix) + strlen(bc->oad);
2777                                 char tmp[l+1];
2778                                 strcpy(tmp,prefix);
2779                                 strcat(tmp,bc->oad);
2780                                 strcpy(bc->oad,tmp);
2781                         }
2782                         
2783                         if (!ast_strlen_zero(bc->oad))
2784                                 sprintf(name,"mISDN/%d/%s",bc->port,bc->oad);
2785                         else
2786                                 sprintf(name,"mISDN/%d",bc->port);
2787
2788
2789                         if (!ast_strlen_zero(bc->dad)) {
2790                                 strncpy(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
2791                                 bc->orig_dad[sizeof(bc->orig_dad)-1] = 0;
2792                         }
2793                         
2794                         if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
2795                                 strncpy(bc->dad,bc->keypad, sizeof(bc->dad));
2796                                 bc->dad[sizeof(bc->dad)-1] = 0;
2797                         }
2798                         prefix[0] = 0;
2799                         
2800                         switch( bc->dnumplan ) {
2801                         case NUMPLAN_INTERNATIONAL:
2802                                 misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
2803                                 break;
2804                                 
2805                         case NUMPLAN_NATIONAL:
2806                                 misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
2807                                 break;
2808                                 
2809                                 
2810                         case NUMPLAN_SUBSCRIBER:
2811                                 /* dunno what to do here ? */
2812                                 break;
2813                                 
2814                         case NUMPLAN_UNKNOWN:
2815                                 break;
2816                         default:
2817                                 break;
2818                         }
2819                 
2820                         {
2821                                 int l = strlen(prefix) + strlen(bc->dad);
2822                                 char tmp[l+1];
2823                                 strcpy(tmp,prefix);
2824                                 strcat(tmp,bc->dad);
2825                                 strcpy(bc->dad,tmp);
2826                         }
2827                         
2828                         char bc_context[BUFFERSIZE];
2829                         misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
2830                         chan=misdn_new(ch, AST_STATE_RING,name ,bc_context, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
2831                         
2832                         if (!chan) {
2833                                 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
2834                                 return 0;
2835                         }
2836                         
2837                         ch->ast = chan;
2838                         pbx_builtin_setvar_helper(ch->ast,"REDIRECTING_NUMBER",bc->rad);
2839                         
2840                 }
2841
2842                 
2843
2844                 chan_misdn_trace_call(chan,1,"I->*: EVENT_SETUP\n");
2845                 
2846                 if ( bc->pres ) {
2847                         chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
2848                 }  else {
2849                         chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
2850                 }
2851       
2852                 pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
2853                 chan->transfercapability=bc->capability;
2854       
2855                 switch (bc->capability) {
2856                 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
2857                         pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL");
2858                         break;
2859                 default:
2860                         pbx_builtin_setvar_helper(chan,"CALLTYPE","SPEECH");
2861                 }
2862
2863                 /** queue new chan **/
2864                 cl_queue_chan(&cl_te, ch) ;
2865
2866
2867                 /*
2868                   added support for s extension hope it will help those poor cretains
2869                   which haven't overlap dial.
2870                 */
2871                 {
2872                         
2873                         misdn_cfg_get( bc->port, MISDN_CFG_LANGUAGE, chan->language, sizeof(chan->language));
2874                         int ai;
2875                         misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
2876                         if ( ai ) {
2877                                 do_immediate_setup(bc, ch , chan);
2878                                 break;
2879                         }
2880
2881                         int immediate;
2882                         misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &immediate, sizeof(int));
2883                         
2884                         if (ast_strlen_zero(bc->orig_dad) && immediate ) {
2885                                 do_immediate_setup(bc, ch , chan);
2886                                 break;
2887                         }
2888                         
2889                 }
2890
2891
2892                 {
2893                         int ec, ectr;
2894                         
2895                         misdn_cfg_get( bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
2896                         
2897                         misdn_cfg_get( bc->port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int));
2898                         if (ec == 1 ) {
2899                                 bc->ec_enable=1;
2900                         } else if ( ec > 1 ) {
2901                                 bc->ec_enable=1;
2902                                 bc->ec_deftaps=ec;
2903                         }
2904                         
2905                         if ( !ectr ) {
2906                                 bc->ec_training=0;
2907                         }
2908                 }
2909                 
2910
2911                 if (bc->urate>0) {
2912                         char buf[16];
2913                         snprintf(buf,16,"%d",bc->urate);
2914                         pbx_builtin_setvar_helper(chan,"MISDN_URATE",buf);
2915                 }
2916                 
2917                 /* Check for Pickup Request first */
2918                 if (!strcmp(chan->exten, ast_pickup_ext())) {
2919                         int ret;/** Sending SETUP_ACK**/
2920                         ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
2921         
2922                         if (ast_pickup_call(chan)) {
2923                                 ast_hangup(chan);
2924                         } else {
2925                                 ch->state = MISDN_CALLING_ACKNOWLEDGE;
2926           
2927                                 ch->ast=NULL;
2928           
2929                                 ast_setstate(chan, AST_STATE_DOWN);
2930                                 ast_hangup(chan); 
2931           
2932                                 break;
2933                         }
2934                 }
2935                 
2936                 /** Now after we've finished configuring our channel object
2937                     we'll jump into the dialplan **/
2938                 
2939                 char bc_context[BUFFERSIZE];
2940                 misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
2941                 if(!ast_canmatch_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
2942                         chan_misdn_log(0, bc->port, "Extension can never match, so disconnecting\n");
2943                         manager_send_tone(bc,TONE_BUSY);
2944                         ch->state=MISDN_EXTCANTMATCH;
2945                         bc->out_cause=1;
2946                         if (bc->nt)
2947                                 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
2948                         else
2949                                 misdn_lib_send_event(bc, EVENT_DISCONNECT );
2950                         break;
2951                 }
2952                 
2953                 if (ast_exists_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
2954                         ch->state=MISDN_DIALING;
2955         
2956                         if (bc->nt) {
2957                                 int ret; 
2958                                 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
2959                         } else {
2960                                 int ret;
2961                                 ret= misdn_lib_send_event(bc, EVENT_PROCEEDING );
2962                         }
2963         
2964                         if (ast_pbx_start(chan)<0) {
2965                                 chan_misdn_log(0, bc->port, "ast_pbx_start returned <0 in SETUP\n");
2966                                 chan=NULL;
2967                                 manager_send_tone(bc,TONE_BUSY);
2968                                 if (bc->nt)
2969                                         misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
2970                                 else
2971                                         misdn_lib_send_event(bc, EVENT_DISCONNECT );
2972                         }
2973                 } else {
2974                         int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
2975                         if (ret == -ENOCHAN) {
2976                                 ast_log(LOG_WARNING,"Channel was catched, before we could Acknowledge\n");
2977                                 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
2978                         }
2979                         /*  send tone to phone :) */
2980                         
2981                         int stop_tone;
2982                         misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
2983                         if ( (!ast_strlen_zero(bc->dad)) && stop_tone ) 
2984                                 manager_send_tone(bc,TONE_NONE);
2985                         else
2986                                 manager_send_tone(bc,TONE_DIAL);
2987         
2988                         ch->state=MISDN_WAITING4DIGS;
2989                 }
2990       
2991         }
2992         break;
2993         case EVENT_SETUP_ACKNOWLEDGE:
2994         {
2995                 ch->state = MISDN_CALLING_ACKNOWLEDGE;
2996                 if (!ast_strlen_zero(bc->infos_pending)) {
2997                         /* TX Pending Infos */
2998                         
2999                         {
3000                                 int l = sizeof(bc->dad);
3001                                 strncat(bc->dad,bc->infos_pending, l - strlen(bc->dad));
3002                                 bc->dad[l-1] = 0;
3003                         }       
3004                         {
3005                                 int l = sizeof(ch->ast->exten);
3006                                 strncpy(ch->ast->exten, bc->dad, l);
3007                                 ch->ast->exten[l-1] = 0;
3008                         }
3009                         {
3010                                 int l = sizeof(bc->info_dad);
3011                                 strncpy(bc->info_dad, bc->infos_pending, l);
3012                                 bc->info_dad[l-1] = 0;
3013                         }
3014                         strncpy(bc->infos_pending,"", 1);
3015
3016                         misdn_lib_send_event(bc, EVENT_INFORMATION);
3017                 }
3018         }
3019         break;
3020         case EVENT_PROCEEDING:
3021         {
3022                 
3023                 if ( misdn_cap_is_speech(bc->capability) &&
3024                      misdn_inband_avail(bc) ) {
3025                         start_bc_tones(ch);
3026                 }
3027         }
3028         break;
3029         case EVENT_PROGRESS:
3030                 if (!bc->nt ) {
3031                         if ( misdn_cap_is_speech(bc->capability) &&
3032                              misdn_inband_avail(bc)
3033                                 ) {
3034                                 start_bc_tones(ch);
3035                         }
3036                         
3037                         ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
3038                         
3039                         ch->state=MISDN_PROGRESS;
3040                 }
3041                 break;
3042                 
3043                 
3044         case EVENT_ALERTING:
3045         {
3046                 ch->state = MISDN_ALERTING;
3047                 
3048                 ast_queue_control(ch->ast, AST_CONTROL_RINGING);
3049                 ast_setstate(ch->ast, AST_STATE_RINGING);
3050                 
3051                 cb_log(1,bc->port,"Set State Ringing\n");
3052                 
3053                 if ( misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
3054                          start_bc_tones(ch);
3055                  }
3056         }
3057         break;
3058         case EVENT_CONNECT:
3059                 misdn_lib_send_event(bc,EVENT_CONNECT_ACKNOWLEDGE);
3060         case EVENT_CONNECT_ACKNOWLEDGE:
3061         {
3062                 bc->state=STATE_CONNECTED;
3063                 
3064                 ch->l3id=bc->l3_id;
3065                 ch->addr=bc->addr;
3066                 
3067                 start_bc_tones(ch);
3068                 
3069                 chan_misdn_trace_call(ch->ast,1,"I->*: EVENT_CONNECT\n");
3070                 
3071                 ch->state = MISDN_CONNECTED;
3072                 ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
3073         }
3074         break;
3075         case EVENT_DISCONNECT:
3076         {
3077                 
3078                 struct chan_list *holded_ch=find_holded(cl_te, bc);
3079                 
3080                 
3081                 send_cause2ast(ch->ast,bc);
3082
3083                 if (misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
3084                         /* If there's inband information available (e.g. a
3085                            recorded message saying what was wrong with the
3086                            dialled number, or perhaps even giving an
3087                            alternative number, then play it instead of
3088                            immediately releasing the call */
3089                         start_bc_tones(ch);
3090                         break;
3091                 }
3092                 
3093                 /*Check for holded channel, to implement transfer*/
3094                 if (holded_ch ) {
3095                         if  (ch->state == MISDN_CONNECTED ) {
3096                                 misdn_transfer_bc(ch, holded_ch) ;
3097                                 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
3098                                 break;
3099                         }
3100                 }
3101                 
3102                 stop_bc_tones(ch);
3103                 bc->out_cause=16;
3104                 misdn_lib_send_event(bc,EVENT_RELEASE);
3105                 
3106         }
3107         break;
3108         
3109         case EVENT_RELEASE:
3110                 {
3111                         
3112                         switch ( bc->cause) {
3113                                 
3114                         case -1:
3115                                 /*
3116                                   OK, it really sucks, this is a RELEASE from NT-Stack So we take
3117                                   it and return easylie, It seems that we've send a DISCONNECT
3118                                   before, so we should RELEASE_COMPLETE after that Disconnect
3119                                   (looks like ALERTING State at misdn_hangup !!
3120                                 */
3121                                 return RESPONSE_OK;
3122                                 break;
3123                         }
3124                         
3125                         
3126                         bc->out_cause=16;
3127                         
3128                         stop_bc_tones(ch);
3129                         release_chan(bc);
3130                 }
3131                 break;
3132         case EVENT_RELEASE_COMPLETE:
3133         {
3134                 stop_bc_tones(ch);
3135                 release_chan(bc);
3136         }
3137         break;
3138         
3139         case EVENT_BCHAN_DATA:
3140         {
3141                 chan_misdn_trace_call(ch->ast,3,"I->*: EVENT_B_DATA len=%d\n",bc->bframe_len);
3142                 
3143                 if ( !misdn_cap_is_speech(ch->bc->capability) || bc->nojitter) {
3144                         misdn_tx2ast_frm(ch, bc->bframe, bc->bframe_len );
3145                 } else {
3146                         int len=bc->bframe_len;
3147                         int free=misdn_ibuf_freecount(bc->astbuf);
3148                         
3149                         
3150                         if (bc->bframe_len > free) {
3151                                 ast_log(LOG_DEBUG, "sbuf overflow!\n");
3152                                 len=misdn_ibuf_freecount(bc->astbuf);
3153
3154                                 if (len == 0) {
3155                                         ast_log(LOG_WARNING, "BCHAN_DATA: write buffer overflow port:%d channel:%d!\n",bc->port,bc->channel);
3156                                 }
3157                         }
3158                         
3159                         misdn_ibuf_memcpy_w(bc->astbuf, bc->bframe, len);
3160                         
3161                         {
3162                                 char blah[1]="\0";
3163 #ifdef FLATTEN_JITTER
3164                                 {
3165                                         struct timeval tv;
3166                                         gettimeofday(&tv,NULL);
3167                                         
3168                                         if (tv.tv_usec % 10000 > 0 ) {
3169                                                 write(ch->pipe[1], blah,sizeof(blah));
3170                                                 bc->time_usec=tv.tv_usec;
3171                                         }
3172                                 }
3173 #else
3174                                 write(ch->pipe[1], blah,sizeof(blah));
3175 #endif
3176                                 
3177                                 
3178                         }
3179                 }
3180                 
3181         }
3182         break;
3183         case EVENT_TIMEOUT:
3184                 break; /* Ignore now .. */
3185                 {
3186                         switch (ch->state) {
3187                         case MISDN_CALLING:
3188                                 chan_misdn_log(0, bc?bc->port:0, "GOT TIMOUT AT CALING pid:%d\n", bc?bc->pid:-1);
3189                                         break;
3190                         case MISDN_DIALING:
3191                         case MISDN_PROGRESS:
3192                                 break;
3193                         default:
3194                                 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
3195                         }
3196                 }
3197                 break;
3198         case EVENT_CLEANUP:
3199         {
3200                 stop_bc_tones(ch);
3201                 release_chan(bc);
3202         }
3203         break;
3204     
3205         /***************************/
3206         /** Suplementary Services **/
3207         /***************************/
3208         case EVENT_RETRIEVE:
3209         {
3210                 struct ast_channel *hold_ast=AST_BRIDGED_P(ch->ast);
3211                 ch->state = MISDN_CONNECTED;
3212                 
3213                 //ast_moh_stop(ch->ast);
3214                 //start_bc_tones(ch);
3215                 if (hold_ast) {
3216                         ast_moh_stop(hold_ast);
3217                 }
3218                 
3219                 if ( misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0)
3220                         misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
3221                 
3222                 
3223         }
3224         break;
3225     
3226         case EVENT_HOLD:
3227         {
3228                 int hold_allowed;
3229                 misdn_cfg_get( bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
3230                 
3231                 if (!hold_allowed) {
3232                         chan_misdn_log(0, bc->port, "Hold not allowed on port:%d\n", bc->port);
3233                         misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
3234                         break;
3235                 }
3236
3237                 {
3238                         struct chan_list *holded_ch=find_holded(cl_te, bc);
3239                         if (holded_ch) {
3240                                 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
3241                                 chan_misdn_log(0, bc->port, "We can't use RETRIEVE at the moment due to mISDN bug!\n");
3242                                 break;
3243                         }
3244                 }
3245                 
3246                 if (AST_BRIDGED_P(ch->ast)){
3247                         ch->state = MISDN_HOLDED;
3248                         ch->l3id = bc->l3_id;
3249                         
3250                         ast_moh_start(AST_BRIDGED_P(ch->ast), NULL);
3251                         misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
3252                 } else {
3253                         misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
3254                         chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
3255                 }
3256         } 
3257         break;
3258         default:
3259                 ast_log(LOG_WARNING, "Got Unknown Event\n");
3260                 break;
3261         }
3262         
3263         return RESPONSE_OK;
3264 }
3265
3266 /** TE STUFF END **/
3267
3268 /******************************************
3269  *
3270  *   Asterisk Channel Endpoint END
3271  *
3272  *
3273  *******************************************/
3274
3275
3276 int clearl3_true ( void ) {
3277         int default_clearl3;
3278         misdn_cfg_get( 0, MISDN_GEN_CLEAR_L3, &default_clearl3, sizeof(int));
3279         return default_clearl3;
3280 }
3281
3282 int g_config_initialized=0;
3283
3284 int load_module(void)
3285 {
3286         int i;
3287         
3288         char ports[256]="";
3289         
3290         max_ports=misdn_lib_maxports_get();
3291         
3292         if (max_ports<=0) {
3293                 ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
3294                 return -1;
3295         }
3296         
3297         
3298         misdn_cfg_init(max_ports);
3299         g_config_initialized=1;
3300         
3301         misdn_debug = (int *)malloc(sizeof(int) * (max_ports+1));
3302         misdn_cfg_get( 0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(int));
3303         for (i = 1; i <= max_ports; i++)
3304                 misdn_debug[i] = misdn_debug[0];
3305         misdn_debug_only = (int *)calloc(max_ports + 1, sizeof(int));
3306
3307         
3308         {
3309                 char tempbuf[BUFFERSIZE];
3310                 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
3311                 if (strlen(tempbuf))
3312                         tracing = 1;
3313         }
3314
3315         ast_mutex_init(&cl_te_lock);
3316         ast_mutex_init(&release_lock_mutex);
3317
3318         misdn_cfg_get_ports_string(ports);
3319         if (strlen(ports))
3320                 chan_misdn_log(0, 0, "Got: %s from get_ports\n",ports);
3321         
3322         {
3323                 struct misdn_lib_iface iface = {
3324                         .cb_event = cb_events,
3325                         .cb_log = chan_misdn_log,
3326                         .cb_clearl3_true = clearl3_true
3327                 };
3328                 if (misdn_lib_init(ports, &iface, NULL))
3329                         chan_misdn_log(0, 0, "No te ports initialized\n");
3330         }
3331
3332
3333         {
3334                 if (ast_channel_register(&misdn_tech)) {
3335                         ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
3336                         unload_module();
3337                         return -1;
3338                 }
3339         }
3340   
3341         ast_cli_register(&cli_send_display);
3342         ast_cli_register(&cli_send_cd);
3343         ast_cli_register(&cli_send_digit);
3344         ast_cli_register(&cli_toggle_echocancel);
3345         ast_cli_register(&cli_set_tics);
3346
3347         ast_cli_register(&cli_show_cls);
3348         ast_cli_register(&cli_show_cl);
3349         ast_cli_register(&cli_show_config);
3350         ast_cli_register(&cli_show_port);
3351         ast_cli_register(&cli_show_stacks);
3352
3353         ast_cli_register(&cli_restart_port);
3354         ast_cli_register(&cli_port_up);
3355         ast_cli_register(&cli_set_debug);
3356         ast_cli_register(&cli_set_crypt_debug);
3357         ast_cli_register(&cli_reload);
3358
3359   
3360         ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_flags",
3361                                  "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
3362                                  "Sets mISDN opts. and optargs\n"
3363                                  "\n"
3364                 );
3365
3366         
3367         ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
3368                                  "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
3369                                  "Sends the Facility Message FACILITY_TYPE with \n"
3370                                  "the given Arguments to the current ISDN Channel\n"
3371                                  "Supported Facilities are:\n"
3372                                  "\n"
3373                                  "type=calldeflect args=Nr where to deflect\n"
3374                                  "\n"
3375                 );
3376   
3377         chan_misdn_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
3378
3379         return 0;
3380 }
3381
3382
3383
3384 int unload_module(void)
3385 {
3386         /* First, take us out of the channel loop */
3387         chan_misdn_log(0, 0, "-- Unregistering mISDN Channel Driver --\n");
3388
3389         if (!g_config_initialized) return 0;
3390         
3391         ast_cli_unregister(&cli_send_display);
3392         
3393         ast_cli_unregister(&cli_send_cd);
3394         
3395         ast_cli_unregister(&cli_send_digit);
3396         ast_cli_unregister(&cli_toggle_echocancel);
3397         ast_cli_unregister(&cli_set_tics);
3398   
3399         ast_cli_unregister(&cli_show_cls);
3400         ast_cli_unregister(&cli_show_cl);
3401         ast_cli_unregister(&cli_show_config);
3402         ast_cli_unregister(&cli_show_port);
3403         ast_cli_unregister(&cli_show_stacks);
3404         ast_cli_unregister(&cli_restart_port);
3405         ast_cli_unregister(&cli_port_up);
3406         ast_cli_unregister(&cli_set_debug);
3407         ast_cli_unregister(&cli_set_crypt_debug);
3408         ast_cli_unregister(&cli_reload);
3409         /* ast_unregister_application("misdn_crypt"); */
3410         ast_unregister_application("misdn_set_opt");
3411         ast_unregister_application("misdn_facility");
3412   
3413         ast_channel_unregister(&misdn_tech);
3414
3415         free_robin_list();
3416         misdn_cfg_destroy();
3417         misdn_lib_destroy();
3418   
3419         if (misdn_debug)
3420                 free(misdn_debug);
3421         if (misdn_debug_only)
3422                 free(misdn_debug_only);
3423         
3424         return 0;
3425 }
3426
3427 int usecount(void)
3428 {
3429         int res;
3430         ast_mutex_lock(&usecnt_lock);
3431         res = usecnt;
3432         ast_mutex_unlock(&usecnt_lock);
3433         return res;
3434 }
3435
3436 char *description(void)
3437 {
3438         return desc;
3439 }
3440
3441 char *key(void)
3442 {
3443         return ASTERISK_GPL_KEY;
3444 }
3445
3446 void chan_misdn_log(int level, int port, char *tmpl, ...)
3447 {
3448         if (! ((0 <= port) && (port <= max_ports))) {
3449                 ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
3450                 return;
3451         }
3452                 
3453         va_list ap;
3454         char buf[1024];
3455   
3456         va_start(ap, tmpl);
3457         vsnprintf( buf, 1023, tmpl, ap );
3458         va_end(ap);
3459         
3460         if (misdn_debug_only[port] ? (level==1 && misdn_debug[port]) || (level==misdn_debug[port]) : level <= misdn_debug[port]) {
3461                 ast_console_puts(buf);
3462         }
3463         
3464         if (level <= misdn_debug[0] && tracing) {
3465                 time_t tm = time(NULL);
3466                 char *tmp=ctime(&tm),*p;
3467                 char file[BUFFERSIZE];
3468                 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, file, BUFFERSIZE);
3469                 FILE *fp= fopen(file, "a+");
3470
3471                 p=strchr(tmp,'\n');
3472                 if (p) *p=':';
3473     
3474                 if (!fp) {
3475                         ast_console_puts("Error opening Tracefile: ");
3476                         ast_console_puts(strerror(errno));
3477                         ast_console_puts("\n");
3478                         return ;
3479                 }
3480                 
3481                 fputs(tmp,fp);
3482                 fputs(" ", fp);
3483                 fputs(buf, fp);
3484
3485                 fclose(fp);
3486         }
3487 }
3488
3489
3490 void chan_misdn_trace_call(struct ast_channel *chan, int debug, char *tmpl, ...)
3491 {
3492         va_list ap;
3493