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