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