issue #5639
[asterisk/asterisk.git] / channels / chan_misdn.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  * 
4  * Copyright (C) 2004, Christian Richter
5  *
6  * Christian Richter <crich@beronet.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  *
18  */
19
20 /*!
21  * \file
22  *
23  * \brief the chan_misdn channel driver for Asterisk
24  * \author Christian Richter <crich@beronet.com>
25  *
26  * \ingroup channel_drivers
27  */
28
29 #include <stdio.h>
30 #include <pthread.h>
31 #include <string.h>
32 #include <sys/socket.h>
33 #include <sys/time.h>
34 #include <errno.h>
35 #include <unistd.h>
36 #include <stdlib.h>
37 #include <arpa/inet.h>
38 #include <fcntl.h>
39 #include <sys/ioctl.h>
40 #include <sys/file.h>
41
42 #include <asterisk/channel.h>
43 #include <asterisk/config.h>
44 #include <asterisk/logger.h>
45 #include <asterisk/module.h>
46 #include <asterisk/pbx.h>
47 #include <asterisk/options.h>
48 #include <asterisk/io.h>
49 #include <asterisk/frame.h>
50 #include <asterisk/translate.h>
51 #include <asterisk/cli.h>
52 #include <asterisk/musiconhold.h>
53 #include <asterisk/dsp.h>
54 #include <asterisk/translate.h>
55 #include <asterisk/config.h>
56 #include <asterisk/file.h>
57 #include <asterisk/callerid.h>
58 #include <asterisk/indications.h>
59 #include <asterisk/app.h>
60 #include <asterisk/features.h>
61
62 #include "chan_misdn_config.h"
63 #include "isdn_lib.h"
64
65 ast_mutex_t release_lock_mutex;
66
67 #define release_lock ast_mutex_lock(&release_lock_mutex)
68 #define release_unlock ast_mutex_unlock(&release_lock_mutex)
69
70
71 /* BEGIN: chan_misdn.h */
72
73 enum misdn_chan_state {
74         MISDN_NOTHING,          /*!< at beginning */
75         MISDN_WAITING4DIGS, /*!<  when waiting for infos */
76         MISDN_EXTCANTMATCH, /*!<  when asterisk couldnt match our ext */
77         MISDN_DIALING, /*!<  when pbx_start */
78         MISDN_PROGRESS, /*!<  we got a progress */
79         MISDN_CALLING, /*!<  when misdn_call is called */
80         MISDN_CALLING_ACKNOWLEDGE, /*!<  when we get SETUP_ACK */
81         MISDN_ALERTING, /*!<  when Alerting */
82         MISDN_BUSY, /*!<  when BUSY */
83         MISDN_CONNECTED, /*!<  when connected */
84         MISDN_BRIDGED, /*!<  when bridged */
85         MISDN_CLEANING, /*!< when hangup from * but we were connected before */
86         MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
87         MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of */
88         /* misdn_hangup */
89         MISDN_HOLDED, /*!< if this chan is holded */
90         MISDN_HOLD_DISCONNECT /*!< if this chan is holded */
91   
92 };
93
94 #define ORG_AST 1
95 #define ORG_MISDN 2
96
97 struct chan_list {
98   
99         ast_mutex_t lock;
100
101         enum misdn_chan_state state;
102         int holded; 
103         int orginator;
104
105         int norxtone;
106         int notxtone; 
107
108         int pipe[2];
109         char ast_rd_buf[4096];
110         struct ast_frame frame;
111
112         int faxdetect;
113         int faxhandled;
114
115         int ast_dsp;
116         
117         struct ast_dsp *dsp;
118         struct ast_trans_pvt *trans;
119   
120         struct ast_channel * ast;
121   
122         struct misdn_bchannel *bc;
123         struct misdn_bchannel *holded_bc;
124
125         unsigned int l3id;
126         int addr;
127         
128         struct chan_list *peer;
129         struct chan_list *next;
130         struct chan_list *prev;
131         struct chan_list *first;
132 };
133
134 struct robin_list {
135         char *group;
136         int port;
137         int channel;
138         struct robin_list *next;
139         struct robin_list *prev;
140 };
141 static struct robin_list *robin = NULL;
142
143 static inline void free_robin_list_r (struct robin_list *r)
144 {
145         if (r) {
146                 if (r->next) free_robin_list_r(r->next);
147                 if (r->group) free(r->group);
148                 free(r);
149         }
150 }
151
152 static void free_robin_list ()
153 {
154         free_robin_list_r(robin);
155 }
156
157 struct robin_list* get_robin_position (char *group) 
158 {
159         struct robin_list *iter = robin;
160         for (; iter; iter = iter->next) {
161                 if (!strcasecmp(iter->group, group))
162                         return iter;
163         }
164         struct robin_list *new = (struct robin_list *)calloc(1, sizeof(struct robin_list));
165         new->group = strndup(group, strlen(group));
166         new->channel = 1;
167         if (robin) {
168                 new->next = robin;
169                 robin->prev = new;
170         }
171         robin = new;
172         return robin;
173 }
174
175 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);
176 void send_digit_to_chan(struct chan_list *cl, char digit );
177
178
179 #define AST_CID_P(ast) ast->cid.cid_num
180 #define AST_BRIDGED_P(ast) ast_bridged_channel(ast) 
181 #define AST_LOAD_CFG ast_config_load
182 #define AST_DESTROY_CFG ast_config_destroy
183
184 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
185 #define MISDN_ASTERISK_PVT(ast) 1
186 #define MISDN_ASTERISK_TYPE(ast) ast->tech->type
187
188 /* END: chan_misdn.h */
189
190 #include <asterisk/strings.h>
191
192 /* #define MISDN_DEBUG 1 */
193
194 static  char *desc = "Channel driver for mISDN Support (Bri/Pri)";
195 static  char *type = "mISDN";
196
197 int tracing = 0 ;
198
199 static int usecnt=0;
200
201 char **misdn_key_vector=NULL;
202 int misdn_key_vector_size=0;
203
204 /* Only alaw and mulaw is allowed for now */
205 static int prefformat =  AST_FORMAT_ALAW ; /*  AST_FORMAT_SLINEAR ;  AST_FORMAT_ULAW | */
206
207 static ast_mutex_t usecnt_lock; 
208
209 int *misdn_debug;
210 int *misdn_debug_only;
211 int max_ports;
212
213 struct chan_list dummy_cl;
214
215 struct chan_list *cl_te=NULL;
216 ast_mutex_t cl_te_lock;
217
218 enum event_response_e
219 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
220
221 void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc);
222
223 void cl_queue_chan(struct chan_list **list, struct chan_list *chan);
224 void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);
225 struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);
226 void chan_misdn_log(int level, int port, char *tmpl, ...);
227 void chan_misdn_trace_call(struct ast_channel *chan, int debug, char *tmpl, ...);
228
229 static int start_bc_tones(struct chan_list *cl);
230 static int stop_bc_tones(struct chan_list *cl);
231 static void release_chan(struct misdn_bchannel *bc);
232
233 static int misdn_set_opt_exec(struct ast_channel *chan, void *data);
234 static int misdn_facility_exec(struct ast_channel *chan, void *data);
235
236 /*************** Helpers *****************/
237
238 static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
239 {
240         struct chan_list *tmp;
241   
242         for (tmp=cl_te; tmp; tmp = tmp->next) {
243                 if ( tmp->ast == ast ) return tmp;
244         }
245   
246         return NULL;
247 }
248
249 static struct chan_list * get_chan_by_ast_name(char *name)
250 {
251         struct chan_list *tmp;
252   
253         for (tmp=cl_te; tmp; tmp = tmp->next) {
254                 if ( tmp->ast  && strcmp(tmp->ast->name,name) == 0) return tmp;
255         }
256   
257         return NULL;
258 }
259
260 static char* tone2str(struct misdn_bchannel *bc)
261 {
262         static struct {
263                 char name[16];
264                 enum tone_e tone;
265         } *tone, tone_buf[] = {
266                 {"NOTONE",TONE_NONE},
267                 {"DIAL",TONE_DIAL},
268                 {"BUSY",TONE_BUSY},
269                 {"ALERT",TONE_ALERTING},
270                 {"",TONE_NONE}
271         };
272   
273   
274         for (tone=&tone_buf[0]; tone->name[0]; tone++) {
275                 if (tone->tone == bc->tone) return tone->name;
276         }
277         return NULL;
278 }
279
280 static char *bearer2str(int cap) {
281         static char *bearers[]={
282                 "Speech",
283                 "Audio 3.1k",
284                 "Unres Digital",
285                 "Res Digital",
286                 "Unknown Bearer"
287         };
288         
289         switch (cap) {
290         case INFO_CAPABILITY_SPEECH:
291                 return bearers[0];
292                 break;
293         case INFO_CAPABILITY_AUDIO_3_1K:
294                 return bearers[1];
295                 break;
296         case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
297                 return bearers[2];
298                 break;
299         case INFO_CAPABILITY_DIGITAL_RESTRICTED:
300                 return bearers[3];
301                 break;
302         default:
303                 return bearers[4];
304                 break;
305         }
306 }
307
308 static void print_bearer(struct misdn_bchannel *bc) 
309 {
310         
311         chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
312         
313         switch(bc->law) {
314         case INFO_CODEC_ALAW:
315                 chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
316                 break;
317         case INFO_CODEC_ULAW:
318                 chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
319                 break;
320         }
321 }
322 /*************** Helpers END *************/
323
324 void send_digit_to_chan(struct chan_list *cl, char digit )
325 {
326         static const char* dtmf_tones[] = {
327                 "!941+1336/100,!0/100", /* 0 */
328                 "!697+1209/100,!0/100", /* 1 */
329                 "!697+1336/100,!0/100", /* 2 */
330                 "!697+1477/100,!0/100", /* 3 */
331                 "!770+1209/100,!0/100", /* 4 */
332                 "!770+1336/100,!0/100", /* 5 */
333                 "!770+1477/100,!0/100", /* 6 */
334                 "!852+1209/100,!0/100", /* 7 */
335                 "!852+1336/100,!0/100", /* 8 */
336                 "!852+1477/100,!0/100", /* 9 */
337                 "!697+1633/100,!0/100", /* A */
338                 "!770+1633/100,!0/100", /* B */
339                 "!852+1633/100,!0/100", /* C */
340                 "!941+1633/100,!0/100", /* D */
341                 "!941+1209/100,!0/100", /* * */
342                 "!941+1477/100,!0/100" };       /* # */
343         struct ast_channel *chan=cl->ast; 
344   
345         if (digit >= '0' && digit <='9')
346                 ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
347         else if (digit >= 'A' && digit <= 'D')
348                 ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
349         else if (digit == '*')
350                 ast_playtones_start(chan,0,dtmf_tones[14], 0);
351         else if (digit == '#')
352                 ast_playtones_start(chan,0,dtmf_tones[15], 0);
353         else {
354                 /* not handled */
355                 ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
356     
357     
358         }
359 }
360 /*** CLI HANDLING ***/
361 static int misdn_set_debug(int fd, int argc, char *argv[])
362 {
363         if (argc != 4 && argc != 5 && argc != 6 && argc != 7)
364                 return RESULT_SHOWUSAGE; 
365
366         int level = atoi(argv[3]);
367
368         switch (argc) {
369                 case 4: 
370                 case 5: {
371                                         int only = 0;
372                                         if (argc == 5) {
373                                                 if (strncasecmp(argv[4], "only", strlen(argv[4])))
374                                                         return RESULT_SHOWUSAGE;
375                                                 else
376                                                         only = 1;
377                                         }
378                                         int i;
379                                         for (i=0; i<=max_ports; i++) {
380                                                 misdn_debug[i] = level;
381                                                 misdn_debug_only[i] = only;
382                                         }
383                                         ast_cli(fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
384                                 }
385                                 break;
386                 case 6: 
387                 case 7: {
388                                         if (strncasecmp(argv[4], "port", strlen(argv[4])))
389                                                 return RESULT_SHOWUSAGE;
390                                         int port = atoi(argv[5]);
391                                         if (port <= 0 || port > max_ports) {
392                                                 switch (max_ports) {
393                                                         case 0:
394                                                                 ast_cli(fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
395                                                                 break;
396                                                         case 1:
397                                                                 ast_cli(fd, "port number not valid! only port 1 is availble.\n");
398                                                                 break;
399                                                         default:
400                                                                 ast_cli(fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
401                                                         }
402                                                         return 0;
403                                         }
404                                         if (argc == 7) {
405                                                 if (strncasecmp(argv[6], "only", strlen(argv[6])))
406                                                         return RESULT_SHOWUSAGE;
407                                                 else
408                                                         misdn_debug_only[port] = 1;
409                                         } else
410                                                 misdn_debug_only[port] = 0;
411                                         misdn_debug[port] = level;
412                                         ast_cli(fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
413                                 }
414         }
415         return 0;
416 }
417
418
419 static int misdn_set_crypt_debug(int fd, int argc, char *argv[])
420 {
421         if (argc != 5 )return RESULT_SHOWUSAGE; 
422
423         return 0;
424 }
425
426
427 static int misdn_restart_port (int fd, int argc, char *argv[])
428 {
429         int port;
430   
431         if (argc != 4)
432                 return RESULT_SHOWUSAGE;
433   
434         port = atoi(argv[3]);
435
436         misdn_lib_port_restart(port);
437
438         return 0;
439 }
440
441 static int misdn_port_up (int fd, int argc, char *argv[])
442 {
443         int port;
444         
445         if (argc != 4)
446                 return RESULT_SHOWUSAGE;
447         
448         port = atoi(argv[3]);
449         
450         misdn_lib_get_port_up(port);
451   
452         return 0;
453 }
454
455
456 static int misdn_show_config (int fd, int argc, char *argv[])
457 {
458         char buffer[BUFFERSIZE];
459         enum misdn_cfg_elements elem;
460         int linebreak;
461
462         int onlyport = -1;
463         if (argc >= 4) {
464                 if (!sscanf(argv[3], "%d", &onlyport) || onlyport < 0) {
465                         ast_cli(fd, "Unknown option: %s\n", argv[3]);
466                         return RESULT_SHOWUSAGE;
467                 }
468         }
469         
470         if (argc == 3 || onlyport == 0) {
471                 ast_cli(fd,"Misdn General-Config: \n"); 
472                 ast_cli(fd," ->  VERSION: " CHAN_MISDN_VERSION "\n");
473                 
474                 for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
475                         misdn_cfg_get_config_string( 0, elem, buffer, BUFFERSIZE);
476                         ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
477                 }
478         }
479
480         if (onlyport < 0) {
481                 int port = misdn_cfg_get_next_port(0);
482                 for (; port > 0; port = misdn_cfg_get_next_port(port)) {
483                         ast_cli(fd, "\n[PORT %d]\n", port);
484                         for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
485                                 misdn_cfg_get_config_string( port, elem, buffer, BUFFERSIZE);
486                                 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
487                         }       
488                         ast_cli(fd, "\n");
489                 }
490         }
491         
492         if (onlyport > 0) {
493                 if (misdn_cfg_is_port_valid(onlyport)) {
494                         ast_cli(fd, "[PORT %d]\n", onlyport);
495                         for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
496                                 misdn_cfg_get_config_string( onlyport, elem, buffer, BUFFERSIZE);
497                                 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
498                         }       
499                         ast_cli(fd, "\n");
500                 } else {
501                         ast_cli(fd, "Port %d is not active!\n", onlyport);
502                 }
503         }
504         return 0;
505 }
506
507
508
509 struct state_struct {
510         enum misdn_chan_state state;
511         char txt[255] ;
512 } ;
513
514 struct state_struct state_array[] = {
515         {MISDN_NOTHING,"NOTHING"}, /* at beginning */
516         {MISDN_WAITING4DIGS,"WAITING4DIGS"}, /*  when waiting for infos */
517         {MISDN_EXTCANTMATCH,"EXTCANTMATCH"}, /*  when asterisk couldnt match our ext */
518         {MISDN_DIALING,"DIALING"}, /*  when pbx_start */
519         {MISDN_PROGRESS,"PROGRESS"}, /*  when pbx_start */
520         {MISDN_CALLING,"CALLING"}, /*  when misdn_call is called */
521         {MISDN_ALERTING,"ALERTING"}, /*  when Alerting */
522         {MISDN_BUSY,"BUSY"}, /*  when BUSY */
523         {MISDN_CONNECTED,"CONNECTED"}, /*  when connected */
524         {MISDN_BRIDGED,"BRIDGED"}, /*  when bridged */
525         {MISDN_CLEANING,"CLEANING"}, /* when hangup from * but we were connected before */
526         {MISDN_HUNGUP_FROM_MISDN,"HUNGUP_FROM_MISDN"}, /* when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
527         {MISDN_HOLDED,"HOLDED"}, /* when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
528         {MISDN_HOLD_DISCONNECT,"HOLD_DISCONNECT"}, /* when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
529         {MISDN_HUNGUP_FROM_AST,"HUNGUP_FROM_AST"} /* when DISCONNECT/RELEASE/REL_COMP came out of */
530         /* misdn_hangup */
531 };
532
533
534
535
536 char *misdn_get_ch_state(struct chan_list *p) 
537 {
538         int i;
539         if( !p) return NULL;
540   
541         for (i=0; i< sizeof(state_array)/sizeof(struct state_struct); i++) {
542                 if ( state_array[i].state == p->state) return state_array[i].txt; 
543         }
544   
545         return NULL;
546 }
547
548 static int misdn_reload (int fd, int argc, char *argv[])
549 {
550         int i, cfg_debug;
551         
552         ast_cli(fd, "Reloading mISDN Config\n");
553         chan_misdn_log(0, 0, "Dynamic Crypting Activation is not support during reload at the moment\n");
554         
555         free_robin_list();
556
557         misdn_cfg_reload();
558
559         {
560                 char tempbuf[BUFFERSIZE];
561                 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
562                 if (strlen(tempbuf))
563                         tracing = 1;
564         }
565
566         misdn_cfg_get( 0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(int));
567         for (i = 0;  i <= max_ports; i++) {
568                 misdn_debug[i] = cfg_debug;
569                 misdn_debug_only[i] = 0;
570         }
571         
572         return 0;
573 }
574
575 static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel* bc)
576 {
577         struct ast_channel *ast=help->ast;
578         ast_cli(fd,
579                 "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s ctx:%s state:%s\n",
580                 bc->pid, bc->port, bc->channel,
581                 bc->nt?"NT":"TE",
582                 help->orginator == ORG_AST?"*":"I",
583                 ast?ast->exten:NULL,
584                 ast?AST_CID_P(ast):NULL,
585                 ast?ast->context:NULL,
586                 misdn_get_ch_state(help)
587                 );
588         if (misdn_debug[bc->port] > 0)
589                 ast_cli(fd,
590                         "  --> astname: %s\n"
591                         "  --> ch_l3id: %x\n"
592                         "  --> ch_addr: %x\n"
593                         "  --> bc_addr: %x\n"
594                         "  --> bc_l3id: %x\n"
595                         "  --> tone: %s\n"
596                         "  --> display: %s\n"
597                         "  --> activated: %d\n"
598                         "  --> capability: %s\n"
599                         "  --> echo_cancel: %d\n"
600                         "  --> notone : rx %d tx:%d\n"
601                         "  --> bc_hold: %d holded_bc :%d\n",
602                         help->ast->name,
603                         help->l3id,
604                         help->addr,
605                         bc->addr,
606                         bc?bc->l3_id:-1,
607                         tone2str(bc),
608                         bc->display,
609                         
610                         bc->active,
611                         bearer2str(bc->capability),
612                         bc->ec_enable,
613                         help->norxtone,help->notxtone,
614                         bc->holded, help->holded_bc?1:0
615                         );
616   
617 }
618
619
620 static int misdn_show_cls (int fd, int argc, char *argv[])
621 {
622         struct chan_list *help=cl_te;
623   
624         ast_cli(fd,"Chan List: %p\n",cl_te); 
625   
626         for (;help; help=help->next) {
627                 struct misdn_bchannel *bc=help->bc;   
628                 struct ast_channel *ast=help->ast;
629                 if (misdn_debug[0] > 2) ast_cli(fd, "Bc:%p Ast:%p\n", bc, ast);
630                 if (bc) {
631                         print_bc_info(fd, help, bc);
632                 } else if ( (bc=help->holded_bc) ) {
633                         chan_misdn_log(0, 0, "ITS A HOLDED BC:\n");
634                         print_bc_info(fd, help,  bc);
635                 } else {
636                         ast_cli(fd,"* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, AST_CID_P(ast));
637                 }
638         }
639   
640   
641         return 0;
642 }
643
644
645
646 static int misdn_show_cl (int fd, int argc, char *argv[])
647 {
648         struct chan_list *help=cl_te;
649
650         if (argc != 4)
651                 return RESULT_SHOWUSAGE;
652   
653         for (;help; help=help->next) {
654                 struct misdn_bchannel *bc=help->bc;   
655                 struct ast_channel *ast=help->ast;
656     
657                 if (bc && ast) {
658                         if (!strcasecmp(ast->name,argv[3])) {
659                                 print_bc_info(fd, help, bc);
660                                 break; 
661                         }
662                 } 
663         }
664   
665   
666         return 0;
667 }
668
669 ast_mutex_t lock;
670 int MAXTICS=8;
671
672 static int misdn_set_tics (int fd, int argc, char *argv[])
673 {
674         if (argc != 4)
675                 return RESULT_SHOWUSAGE;
676   
677         MAXTICS=atoi(argv[3]);
678   
679         return 0;
680 }
681
682
683
684 static int misdn_show_stacks (int fd, int argc, char *argv[])
685 {
686         int port;
687         
688         ast_cli(fd, "BEGIN STACK_LIST:\n");
689         for (port=misdn_cfg_get_next_port(0); port > 0;
690              port=misdn_cfg_get_next_port(port)) {
691                 char buf[128];
692                 get_show_stack_details(port,buf);
693                 ast_cli(fd,"  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
694         }
695                 
696
697         return 0;
698
699 }
700
701 static int misdn_show_port (int fd, int argc, char *argv[])
702 {
703         int port;
704         
705         if (argc != 4)
706                 return RESULT_SHOWUSAGE;
707   
708         port = atoi(argv[3]);
709   
710         ast_cli(fd, "BEGIN STACK_LIST:\n");
711
712         char buf[128];
713         get_show_stack_details(port,buf);
714         ast_cli(fd,"  %s  Debug:%d%s\n",buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
715
716         
717         return 0;
718 }
719
720 static int misdn_send_cd (int fd, int argc, char *argv[])
721 {
722         char *channame; 
723         char *nr; 
724   
725         if (argc != 5)
726                 return RESULT_SHOWUSAGE;
727   
728         channame = argv[3];
729         nr = argv[4];
730         
731         ast_cli(fd, "Sending Calldeflection (%s) to %s\n",nr, channame);
732         
733         {
734                 struct chan_list *tmp=get_chan_by_ast_name(channame);
735                 
736                 if (!tmp) {
737                         ast_cli(fd, "Sending CD with nr %s to %s failed Channel does not exist\n",nr, channame);
738                         return 0; 
739                 } else {
740                         
741                         misdn_lib_send_facility(tmp->bc, FACILITY_CALLDEFLECT, nr);
742                 }
743         }
744   
745         return 0; 
746 }
747
748
749
750 static int misdn_send_digit (int fd, int argc, char *argv[])
751 {
752         char *channame; 
753         char *msg; 
754   
755         if (argc != 5)
756                 return RESULT_SHOWUSAGE;
757   
758         channame = argv[3];
759         msg = argv[4];
760
761         ast_cli(fd, "Sending %s to %s\n",msg, channame);
762   
763         {
764                 struct chan_list *tmp=get_chan_by_ast_name(channame);
765     
766                 if (!tmp) {
767                         ast_cli(fd, "Sending %s to %s failed Channel does not exist\n",msg, channame);
768                         return 0; 
769                 } else {
770 #if 1
771                         int i;
772                         int msglen = strlen(msg);
773                         for (i=0; i<msglen; i++) {
774                                 ast_cli(fd, "Sending: %c\n",msg[i]);
775                                 send_digit_to_chan(tmp, msg[i]);
776                                 /* res = ast_safe_sleep(tmp->ast, 250); */
777                                 usleep(250000);
778                                 /* res = ast_waitfor(tmp->ast,100); */
779                         }
780 #else
781                         int res;
782                         res = ast_dtmf_stream(tmp->ast,NULL,msg,250);
783 #endif
784                 }
785         }
786   
787         return 0; 
788 }
789
790 static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
791 {
792         char *channame; 
793
794         if (argc != 4)
795                 return RESULT_SHOWUSAGE;
796         
797         channame = argv[3];
798   
799         ast_cli(fd, "Toggling EchoCancel on %s\n", channame);
800   
801         {
802                 struct chan_list *tmp=get_chan_by_ast_name(channame);
803     
804                 if (!tmp) {
805                         ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
806                         return 0; 
807                 } else {
808                         tmp->bc->ec_enable=tmp->bc->ec_enable?0:1;
809
810                         if (tmp->bc->ec_enable) {
811                                 manager_ec_enable(tmp->bc);
812                         } else {
813                                 manager_ec_disable(tmp->bc);
814                         }
815                 }
816         }
817   
818         return 0; 
819 }
820
821
822
823 static int misdn_send_display (int fd, int argc, char *argv[])
824 {
825         char *channame; 
826         char *msg; 
827   
828         if (argc != 5)
829                 return RESULT_SHOWUSAGE;
830   
831         channame = argv[3];
832         msg = argv[4];
833
834         ast_cli(fd, "Sending %s to %s\n",msg, channame);
835         {
836                 struct chan_list *tmp;
837                 tmp=get_chan_by_ast_name(channame);
838     
839                 if (tmp && tmp->bc) {
840                         int l = sizeof(tmp->bc->display);
841                         strncpy(tmp->bc->display, msg, l);
842                         tmp->bc->display[l-1] = 0;
843                         misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
844                 } else {
845                         ast_cli(fd,"No such channel %s\n",channame);
846                         return RESULT_FAILURE;
847                 }
848         }
849
850         return RESULT_SUCCESS ;
851 }
852
853
854
855
856 static char *complete_ch_helper(char *line, char *word, int pos, int state, int rpos)
857 {
858         struct ast_channel *c;
859         int which=0;
860         char *ret;
861         if (pos != rpos)
862                 return NULL;
863         c = ast_channel_walk_locked(NULL);
864         while(c) {
865                 if (!strncasecmp(word, c->name, strlen(word))) {
866                         if (++which > state)
867                                 break;
868                 }
869                 ast_mutex_unlock(&c->lock);
870                 c = ast_channel_walk_locked(c);
871         }
872         if (c) {
873                 ret = strdup(c->name);
874                 ast_mutex_unlock(&c->lock);
875         } else
876                 ret = NULL;
877         return ret;
878 }
879
880 static char *complete_ch(char *line, char *word, int pos, int state)
881 {
882         return complete_ch_helper(line, word, pos, state, 3);
883 }
884
885 static char *complete_debug_port (char *line, char *word, int pos, int state)
886 {
887         if (state)
888                 return NULL;
889
890         switch (pos) {
891         case 4: if (*word == 'p')
892                                 return strdup("port");
893                         else if (*word == 'o')
894                                 return strdup("only");
895                         break;
896         case 6: if (*word == 'o')
897                                 return strdup("only");
898                         break;
899         }
900         return NULL;
901 }
902
903 static struct ast_cli_entry cli_send_cd =
904 { {"misdn","send","calldeflect", NULL},
905   misdn_send_cd,
906   "Sends CallDeflection to mISDN Channel", 
907   "Usage: misdn send calldeflect <channel> \"<nr>\" \n",
908   complete_ch
909 };
910
911
912 static struct ast_cli_entry cli_send_digit =
913 { {"misdn","send","digit", NULL},
914   misdn_send_digit,
915   "Sends DTMF Digit to mISDN Channel", 
916   "Usage: misdn send digit <channel> \"<msg>\" \n"
917   "       Send <digit> to <channel> as DTMF Tone\n"
918   "       when channel is a mISDN channel\n",
919   complete_ch
920 };
921
922
923 static struct ast_cli_entry cli_toggle_echocancel =
924 { {"misdn","toggle","echocancel", NULL},
925   misdn_toggle_echocancel,
926   "Toggles EchoCancel on mISDN Channel", 
927   "Usage: misdn toggle echocancel <channel>\n", 
928   complete_ch
929 };
930
931
932
933 static struct ast_cli_entry cli_send_display =
934 { {"misdn","send","display", NULL},
935   misdn_send_display,
936   "Sends Text to mISDN Channel", 
937   "Usage: misdn send display <channel> \"<msg>\" \n"
938   "       Send <msg> to <channel> as Display Message\n"
939   "       when channel is a mISDN channel\n",
940   complete_ch
941 };
942
943
944 static struct ast_cli_entry cli_show_config =
945 { {"misdn","show","config", NULL},
946   misdn_show_config,
947   "Shows internal mISDN config, read from cfg-file", 
948   "Usage: misdn show config [port | 0]\n       use 0 to only print the general config.\n"
949 };
950  
951
952 static struct ast_cli_entry cli_reload =
953 { {"misdn","reload", NULL},
954   misdn_reload,
955   "Reloads internal mISDN config, read from cfg-file", 
956   "Usage: misdn reload\n"
957 };
958
959 static struct ast_cli_entry cli_set_tics =
960 { {"misdn","set","tics", NULL},
961   misdn_set_tics,
962   "", 
963   "\n"
964 };
965
966
967 static struct ast_cli_entry cli_show_cls =
968 { {"misdn","show","channels", NULL},
969   misdn_show_cls,
970   "Shows internal mISDN chan_list", 
971   "Usage: misdn show channels\n"
972 };
973
974 static struct ast_cli_entry cli_show_cl =
975 { {"misdn","show","channel", NULL},
976   misdn_show_cl,
977   "Shows internal mISDN chan_list", 
978   "Usage: misdn show channels\n",
979   complete_ch
980 };
981
982
983
984 static struct ast_cli_entry cli_restart_port =
985 { {"misdn","restart","port", NULL},
986   misdn_restart_port,
987   "Restarts the given port", 
988   "Usage: misdn restart port\n"
989 };
990
991
992 static struct ast_cli_entry cli_port_up =
993 { {"misdn","port","up", NULL},
994   misdn_port_up,
995   "Tries to establish L1 on the given port", 
996   "Usage: misdn port up <port>\n"
997 };
998
999
1000 static struct ast_cli_entry cli_show_stacks =
1001 { {"misdn","show","stacks", NULL},
1002   misdn_show_stacks,
1003   "Shows internal mISDN stack_list", 
1004   "Usage: misdn show stacks\n"
1005 };
1006
1007 static struct ast_cli_entry cli_show_port =
1008 { {"misdn","show","port", NULL},
1009   misdn_show_port,
1010   "Shows detailed information for given port", 
1011   "Usage: misdn show port <port>\n"
1012 };
1013
1014
1015
1016 static struct ast_cli_entry cli_set_debug =
1017 { {"misdn","set","debug", NULL},
1018   misdn_set_debug,
1019   "Sets Debuglevel of chan_misdn",
1020   "Usage: misdn set debug <level> [only] | [port <port> [only]]\n",
1021   complete_debug_port
1022 };
1023
1024 static struct ast_cli_entry cli_set_crypt_debug =
1025 { {"misdn","set","crypt","debug", NULL},
1026   misdn_set_crypt_debug,
1027   "Sets CryptDebuglevel of chan_misdn, at the moment, level={1,2}", 
1028   "Usage: misdn set crypt debug <level>\n"
1029 };
1030 /*** CLI END ***/
1031
1032
1033 /*****************************/
1034 /*** AST Indications Start ***/
1035 /*****************************/
1036
1037 static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
1038 {
1039         int port=0;
1040         int r;
1041         struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
1042         struct misdn_bchannel *newbc;
1043         char *opts=NULL;
1044         char dest_cp[256];
1045         
1046         {
1047                 strncpy(dest_cp,dest,sizeof(dest_cp)-1);
1048                 dest_cp[sizeof(dest_cp)]=0;
1049                 opts=strchr(dest_cp,'/');
1050                 if ( opts && (opts=strchr(++opts,'/')) ) {
1051                         if (opts) {
1052                                 opts++;
1053                                 if (!*opts) opts=NULL;
1054                         }
1055                 }
1056         }
1057         
1058         if (!ast) {
1059                 ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
1060                 return -1;
1061         }
1062
1063         if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest  ) {
1064                 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1065                 ast->hangupcause=41;
1066                 ast_setstate(ast, AST_STATE_DOWN);
1067                 return -1;
1068         }
1069
1070
1071         if (!ch) {
1072                 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1073                 ast->hangupcause=41;
1074                 ast_setstate(ast, AST_STATE_DOWN);
1075                 return -1;
1076         }
1077         
1078         newbc=ch->bc;
1079         
1080         if (!newbc) {
1081                 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1082                 ast->hangupcause=41;
1083                 ast_setstate(ast, AST_STATE_DOWN);
1084                 return -1;
1085         }
1086         
1087         port=newbc->port;
1088
1089         
1090         chan_misdn_log(1, 0, "* CALL: %s\n",dest);
1091         
1092         chan_misdn_log(1, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
1093         
1094         {
1095                 char context[BUFFERSIZE];
1096                 
1097                 misdn_cfg_get( port, MISDN_CFG_CONTEXT, context, sizeof(ast->context));
1098                 {
1099                         int l = sizeof(ast->context);
1100                         strncpy(ast->context,context, l);
1101                         ast->context[l-1] = 0;
1102                 }
1103                 chan_misdn_log(2, port, " --> * Setting Context to %s\n",context);
1104                 misdn_cfg_get( port, MISDN_CFG_LANGUAGE, ast->language, BUFFERSIZE);
1105                 
1106                 misdn_cfg_get( port, MISDN_CFG_TXGAIN, &newbc->txgain, sizeof(int));
1107                 misdn_cfg_get( port, MISDN_CFG_RXGAIN, &newbc->rxgain, sizeof(int));
1108                 
1109                 misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(newbc->te_choose_channel), sizeof(int));
1110                 
1111
1112                 {
1113                         char callerid[BUFFERSIZE];
1114                         misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
1115                         if ( ! ast_strlen_zero(callerid) ) {
1116                                 chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
1117                                 {
1118                                         int l = sizeof(newbc->oad);
1119                                         strncpy(newbc->oad,callerid, l);
1120                                         newbc->oad[l-1] = 0;
1121                                 }
1122                                 
1123                                 misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &newbc->dnumplan, sizeof(int));
1124                                 switch (newbc->dnumplan) {
1125                                 case NUMPLAN_INTERNATIONAL:
1126                                 case NUMPLAN_NATIONAL:
1127                                 case NUMPLAN_SUBSCRIBER:
1128                                 case NUMPLAN_UNKNOWN:
1129                                         /* Maybe we should cut off the prefix if present ? */
1130                                         break;
1131                                 default:
1132                                         chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
1133                                         break;
1134                                 }
1135                                 
1136                         }
1137                 }
1138                 
1139                 /* Will be overridden by asterisk in head! */
1140                 {
1141                         int pres;
1142                         
1143                         misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int));
1144                         newbc->pres=pres?0:1;
1145                         
1146                 }
1147                 
1148                 int def_callingpres;
1149                 misdn_cfg_get( port, MISDN_CFG_USE_CALLINGPRES, &def_callingpres, sizeof(int));
1150                 if ( def_callingpres) {
1151                         switch (ast->cid.cid_pres){
1152                         case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
1153                                 newbc->pres=1;
1154                                 break;
1155                                 
1156                         case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
1157                                 newbc->pres=0;
1158                                 break;
1159                         default:
1160                                 newbc->pres=0;
1161                         }
1162                 }
1163
1164                 
1165                 {
1166                         int ec, ectr;
1167                         
1168                         misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
1169                         
1170                         misdn_cfg_get( port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int));
1171                         if (ec == 1 ) {
1172                                 newbc->ec_enable=1;
1173                         } else if ( ec > 1 ) {
1174                                 newbc->ec_enable=1;
1175                                 newbc->ec_deftaps=ec;
1176                         }
1177
1178                         if ( !ectr ) {
1179                                 newbc->ec_training=0;
1180                         }
1181                 }
1182                 
1183         } 
1184         
1185         chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten);
1186         if (ast->exten) {
1187                 int l = sizeof(newbc->dad);
1188                 strncpy(newbc->dad,ast->exten, l);
1189                 newbc->dad[l-1] = 0;
1190         }
1191         newbc->rad[0]=0;
1192         chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",AST_CID_P(ast));
1193         if (ast_strlen_zero(newbc->oad) && AST_CID_P(ast) ) {
1194                 if (AST_CID_P(ast)) {
1195                         int l = sizeof(newbc->oad);
1196                         strncpy(newbc->oad,AST_CID_P(ast), l);
1197                         newbc->oad[l-1] = 0;
1198                 }
1199         }
1200         
1201         {
1202                 struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
1203                 if (!ch) { ast_verbose("No chan_list in misdn_call"); return -1;}
1204                 ch->bc = newbc;
1205                 ch->orginator=ORG_AST;
1206                 ch->ast = ast;
1207                 
1208                 MISDN_ASTERISK_TECH_PVT(ast) = ch ;
1209                 
1210                 
1211       
1212                 newbc->capability=ast->transfercapability;
1213                 pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability));
1214                 if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
1215                         chan_misdn_log(2, port, " --> * Call with flag Digital\n");
1216                 }
1217                 
1218
1219                 /* Finally The Options Override Everything */
1220                 if (opts)
1221                         misdn_set_opt_exec(ast,opts);
1222                 else
1223                         chan_misdn_log(1,0,"NO OPTS GIVEN\n");
1224                 
1225                 
1226                 cl_queue_chan(&cl_te, ch) ;
1227                 ch->state=MISDN_CALLING;
1228
1229                 chan_misdn_trace_call(ast,1,"*->I: EVENT_CALL\n" );
1230                 
1231                 r=misdn_lib_send_event( newbc, EVENT_SETUP );
1232                 
1233                 /** we should have l3id after sending setup **/
1234                 ch->l3id=newbc->l3_id;
1235         }
1236         
1237         if ( r == -ENOCHAN  ) {
1238                 chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
1239                 chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n",newbc?newbc->pid:-1);
1240                 ast->hangupcause=34;
1241                 ast_setstate(ast, AST_STATE_DOWN);
1242                 return -1;
1243         }
1244         
1245         chan_misdn_log(1, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
1246
1247         ast_setstate(ast, AST_STATE_DIALING);
1248         
1249         ast->hangupcause=16;
1250         return 0; 
1251 }
1252
1253
1254 int misdn_answer(struct ast_channel *ast)
1255 {
1256         struct chan_list *p;
1257
1258         
1259         if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
1260         p = MISDN_ASTERISK_TECH_PVT(ast) ;
1261         
1262         chan_misdn_trace_call(ast,1,"*->I: EVENT_ANSWER\n");
1263         
1264         chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n");
1265         
1266         if (!p) {
1267                 ast_log(LOG_WARNING, " --> Channel not connected ??\n");
1268                 ast_queue_hangup(ast);
1269         }
1270
1271         if (!p->bc) {
1272                 chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n");
1273
1274                 ast_queue_hangup(ast);
1275         }
1276
1277         {
1278                 char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
1279                 
1280                 if (tmp_key ) {
1281                         chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
1282                         {
1283                                 int l = sizeof(p->bc->crypt_key);
1284                                 strncpy(p->bc->crypt_key,tmp_key, l);
1285                                 p->bc->crypt_key[l-1] = 0;
1286                         }
1287                 } else {
1288                         chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
1289                 }
1290     
1291         }
1292         
1293         p->state = MISDN_CONNECTED;
1294         misdn_lib_send_event( p->bc, EVENT_CONNECT);
1295         start_bc_tones(p);
1296         
1297   
1298         return 0;
1299 }
1300
1301 int misdn_digit(struct ast_channel *ast, char digit )
1302 {
1303         struct chan_list *p;
1304         
1305         if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
1306         p = MISDN_ASTERISK_TECH_PVT(ast) ;
1307         
1308
1309         struct misdn_bchannel *bc=p->bc;
1310         chan_misdn_log(1, bc?bc->port:0, "* IND : Digit %c\n",digit);
1311         
1312         if (!bc) {
1313                 ast_log(LOG_WARNING, " --> !! Got Digit Event withut having bchannel Object\n");
1314                 return -1;
1315         }
1316         
1317         switch (p->state ) {
1318                 case MISDN_CALLING:
1319                 {
1320                         
1321                         char buf[8];
1322                         buf[0]=digit;
1323                         buf[1]=0;
1324                         
1325                         int l = sizeof(bc->infos_pending);
1326                         strncat(bc->infos_pending,buf,l);
1327                         bc->infos_pending[l-1] = 0;
1328                 }
1329                 break;
1330                 case MISDN_CALLING_ACKNOWLEDGE:
1331                 {
1332                         bc->info_dad[0]=digit;
1333                         bc->info_dad[1]=0;
1334                         
1335                         {
1336                                 int l = sizeof(bc->dad);
1337                                 strncat(bc->dad,bc->info_dad, l - strlen(bc->dad));
1338                                 bc->dad[l-1] = 0;
1339                 }
1340                         {
1341                                 int l = sizeof(p->ast->exten);
1342                                 strncpy(p->ast->exten, bc->dad, l);
1343                                 p->ast->exten[l-1] = 0;
1344                         }
1345                         
1346                         misdn_lib_send_event( bc, EVENT_INFORMATION);
1347                 }
1348                 break;
1349                 
1350                 default:
1351                         if ( bc->send_dtmf ) {
1352                                 send_digit_to_chan(p,digit);
1353                         }
1354                 break;
1355         }
1356         
1357         return 0;
1358 }
1359
1360
1361 int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
1362 {
1363         struct chan_list *p;
1364         
1365         if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
1366         p = MISDN_ASTERISK_TECH_PVT(ast) ;
1367         
1368         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);
1369         
1370         p->ast = ast ;
1371         p->state=MISDN_CONNECTED;
1372   
1373         return 0;
1374 }
1375
1376
1377 int misdn_transfer (struct ast_channel *ast, char *dest)
1378 {
1379         struct chan_list *p;
1380         
1381         if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
1382         p = MISDN_ASTERISK_TECH_PVT(ast) ;
1383
1384         chan_misdn_log(1, p->bc?p->bc->port:0, "* IND : Got Transfer %s\n",dest);
1385         return 0;
1386 }
1387
1388
1389
1390 int misdn_indication(struct ast_channel *ast, int cond)
1391 {
1392         struct chan_list *p;
1393
1394   
1395         if (!ast || ! MISDN_ASTERISK_PVT(ast)) {
1396                 ast_log(LOG_WARNING, "Returnded -1 in misdn_indication\n");
1397                 return -1;
1398         }
1399         p = MISDN_ASTERISK_TECH_PVT(ast) ;
1400         
1401         if (!p->bc ) {
1402                 chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten);
1403                 ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
1404                 return -1;
1405         }
1406         
1407         chan_misdn_log(1, p->bc->port, "* IND : Indication from %s\n",ast->exten);
1408         
1409         switch (cond) {
1410         case AST_CONTROL_BUSY:
1411                 chan_misdn_log(1, p->bc->port, "* IND :\tbusy\n");
1412                 chan_misdn_log(1, p->bc->port, " --> * SEND: State Busy pid:%d\n",p->bc?p->bc->pid:-1);
1413                 ast_setstate(ast,AST_STATE_BUSY);
1414                 
1415                 p->bc->out_cause=17;
1416                 if (p->state != MISDN_CONNECTED) {
1417                         misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
1418                         manager_send_tone(p->bc, TONE_BUSY);
1419                 } else {
1420                         chan_misdn_log(0, p->bc->port, " --> !! Got Busy in Connected State !?! port:%d ast:%s\n",
1421                                        p->bc->port, ast->name);
1422                 }
1423                 break;
1424         case AST_CONTROL_RING:
1425                 chan_misdn_log(1, p->bc->port, " --> * IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
1426                 break;
1427         case AST_CONTROL_RINGING:
1428                 if ( p->state == MISDN_ALERTING) {
1429                         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);
1430                         break;
1431                 }
1432                 p->state=MISDN_ALERTING;
1433                 
1434                 chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
1435                 
1436                 misdn_lib_send_event( p->bc, EVENT_ALERTING);
1437                 
1438                 manager_send_tone(p->bc, TONE_ALERTING);
1439                 chan_misdn_log(1, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
1440                 ast_setstate(ast,AST_STATE_RINGING);
1441                 break;
1442                 
1443         case AST_CONTROL_ANSWER:
1444                 chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1);
1445                 break;
1446         case AST_CONTROL_TAKEOFFHOOK:
1447                 chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1);
1448                 break;
1449         case AST_CONTROL_OFFHOOK:
1450                 chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1);
1451                 break; 
1452         case AST_CONTROL_FLASH:
1453                 chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1);
1454                 break;
1455         case AST_CONTROL_PROGRESS:
1456                 chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n",p->bc?p->bc->pid:-1);
1457                 break;
1458         case AST_CONTROL_CONGESTION:
1459                 chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n",p->bc?p->bc->pid:-1);
1460
1461                 p->bc->out_cause=42;
1462                 if (p->state != MISDN_CONNECTED) {
1463                         start_bc_tones(p);
1464                         //misdn_lib_send_event( p->bc, EVENT_RELEASE_COMPLETE);
1465                         misdn_lib_send_event( p->bc, EVENT_RELEASE);
1466                 } else {
1467                         misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
1468                 }
1469                 if (p->bc->nt) {
1470                         manager_send_tone(p->bc, TONE_BUSY);
1471                 }
1472                 break;
1473         case -1 :
1474                 chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! pid:%d\n",p->bc?p->bc->pid:-1);
1475                 break;
1476         case AST_CONTROL_HOLD:
1477                 chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n",p->bc?p->bc->pid:-1);
1478                 break;
1479         case AST_CONTROL_UNHOLD:
1480                 chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1);
1481                 break;
1482         default:
1483                 ast_log(LOG_WARNING, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
1484         }
1485   
1486         return 0;
1487 }
1488
1489 int misdn_hangup(struct ast_channel *ast)
1490 {
1491         struct chan_list *p;
1492         struct misdn_bchannel *bc=NULL;
1493         
1494         if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
1495         p = MISDN_ASTERISK_TECH_PVT(ast) ;
1496
1497         release_lock;
1498
1499         chan_misdn_trace_call(ast,1,"*->I: EVENT_HANGUP cause=%d\n",ast->hangupcause);
1500         
1501         ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
1502         
1503         if (!p) {
1504                 chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
1505                 release_unlock;
1506                 return 0 ;
1507         }
1508         
1509
1510         
1511         MISDN_ASTERISK_TECH_PVT(ast)=NULL;
1512         p->ast=NULL;
1513
1514         if (ast->_state == AST_STATE_RESERVED) {
1515                 /* between request and call */
1516                 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
1517                 release_unlock;
1518                 
1519                 cl_dequeue_chan(&cl_te, p);
1520                 free(p);
1521
1522                 misdn_lib_release(bc);
1523                 
1524                 return 0;
1525         }
1526
1527         stop_bc_tones(p);
1528         
1529         release_unlock;
1530         
1531         
1532         bc=p->bc;
1533         
1534         if (!bc) {
1535                 ast_log(LOG_WARNING,"Hangup with private but no bc ?\n");
1536                 return 0;
1537         }
1538         
1539         {
1540                 char *varcause=NULL;
1541                 bc->cause=ast->hangupcause?ast->hangupcause:16;
1542                 
1543                 if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
1544                      (varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
1545                         int tmpcause=atoi(varcause);
1546                         bc->out_cause=tmpcause?tmpcause:16;
1547                 }
1548     
1549                 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));
1550                 chan_misdn_log(2, bc->port, " --> l3id:%x\n",p->l3id);
1551                 chan_misdn_log(1, bc->port, " --> cause:%d\n",bc->cause);
1552                 chan_misdn_log(1, bc->port, " --> out_cause:%d\n",bc->out_cause);
1553                 
1554                 switch (p->state) {
1555                 case MISDN_CALLING:
1556                         p->state=MISDN_CLEANING;
1557                         misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
1558                         break;
1559                 case MISDN_HOLDED:
1560                 case MISDN_DIALING:
1561                         start_bc_tones(p);
1562                         manager_send_tone(bc, TONE_BUSY);
1563                         p->state=MISDN_CLEANING;
1564                         
1565                         misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
1566       
1567                         break;
1568       
1569                 case MISDN_ALERTING:
1570                         chan_misdn_log(2, bc->port, " --> * State Alerting\n");
1571
1572                         if (p->orginator != ORG_AST) 
1573                                 manager_send_tone(bc, TONE_BUSY);
1574       
1575                         p->state=MISDN_CLEANING;
1576                         misdn_lib_send_event( bc, EVENT_DISCONNECT);
1577                         break;
1578                 case MISDN_CONNECTED:
1579                         /*  Alerting or Disconect */
1580                         chan_misdn_log(2, bc->port, " --> * State Connected\n");
1581                         start_bc_tones(p);
1582                         manager_send_tone(bc, TONE_BUSY);
1583                         misdn_lib_send_event( bc, EVENT_DISCONNECT);
1584       
1585                         p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
1586                         break;
1587
1588                 case MISDN_CLEANING:
1589                         break;
1590       
1591                 case MISDN_HOLD_DISCONNECT:
1592                         /* need to send release here */
1593                         chan_misdn_log(2, bc->port, " --> state HOLD_DISC\n");
1594                         chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause);
1595                         chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause);
1596                         
1597                         misdn_lib_send_event(bc,EVENT_RELEASE);
1598                         break;
1599                 default:
1600                         /*  Alerting or Disconect */
1601                         if (bc->nt)
1602                                 misdn_lib_send_event(bc, EVENT_RELEASE);
1603                         else
1604                                 misdn_lib_send_event(bc, EVENT_DISCONNECT);
1605                         p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
1606                 }
1607     
1608         }
1609         
1610         chan_misdn_log(1, bc->port, "Channel: %s hanguped\n",ast->name);
1611         
1612         return 0;
1613 }
1614
1615 struct ast_frame  *misdn_read(struct ast_channel *ast)
1616 {
1617         struct chan_list *tmp;
1618         
1619         char blah[255];
1620         int len =0 ;
1621         
1622         if (!ast) return NULL;
1623         tmp = MISDN_ASTERISK_TECH_PVT(ast);
1624         if (!tmp) return NULL;
1625         if (!tmp->bc) return NULL;
1626         
1627         
1628         read(tmp->pipe[0],blah,sizeof(blah));
1629         
1630         
1631         len = misdn_ibuf_usedcount(tmp->bc->astbuf);
1632
1633         /*shrinken len if necessary, we transmit at maximum 4k*/
1634         len = len<=sizeof(tmp->ast_rd_buf)?len:sizeof(tmp->ast_rd_buf);
1635         
1636         misdn_ibuf_memcpy_r(tmp->ast_rd_buf, tmp->bc->astbuf,len);
1637         
1638         tmp->frame.frametype  = AST_FRAME_VOICE;
1639         tmp->frame.subclass = AST_FORMAT_ALAW;
1640         tmp->frame.datalen = len;
1641         tmp->frame.samples = len ;
1642         tmp->frame.mallocd =0 ;
1643         tmp->frame.offset= 0 ;
1644         tmp->frame.src = NULL;
1645         tmp->frame.data = tmp->ast_rd_buf ;
1646
1647         chan_misdn_trace_call(tmp->ast,3,"*->I: EVENT_READ len=%d\n",len);
1648         
1649         return &tmp->frame;
1650 }
1651
1652 int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
1653 {
1654         struct chan_list *p;
1655         int i  = 0;
1656         
1657         if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
1658         p = MISDN_ASTERISK_TECH_PVT(ast) ;
1659         
1660         if (!p->bc ) {
1661                 ast_log(LOG_WARNING, "private but no bc\n");
1662                 return -1;
1663         }
1664         
1665         if (p->bc->tone != TONE_NONE)
1666                 manager_send_tone(p->bc,TONE_NONE);
1667         
1668         
1669         if (p->holded ) {
1670                 chan_misdn_log(5, p->bc->port, "misdn_write: Returning because holded\n");
1671                 return 0;
1672         }
1673         
1674         if (p->notxtone) {
1675                 chan_misdn_log(5, p->bc->port, "misdn_write: Returning because notxone\n");
1676                 return 0;
1677         }
1678         
1679         if ( !(frame->subclass & prefformat)) {
1680                 chan_misdn_log(0, p->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
1681         }
1682         
1683         
1684 #if MISDN_DEBUG
1685         {
1686                 int i, max=5>frame->samples?frame->samples:5;
1687                 
1688                 printf("write2mISDN %p %d bytes: ", p, frame->samples);
1689                 
1690                 for (i=0; i<  max ; i++) printf("%2.2x ",((char*) frame->data)[i]);
1691                 printf ("\n");
1692         }
1693 #endif
1694         chan_misdn_trace_call(ast,3,"*->I: EVENT_WRITE len=%d\n",frame->samples);
1695         
1696         i= manager_tx2misdn_frm(p->bc, frame->data, frame->samples);
1697         
1698         return 0;
1699 }
1700
1701
1702 enum ast_bridge_result  misdn_bridge (struct ast_channel *c0,
1703                                       struct ast_channel *c1, int flags,
1704                                       struct ast_frame **fo,
1705                                       struct ast_channel **rc,
1706                                       int timeoutms)
1707
1708 {
1709         struct chan_list *ch1,*ch2;
1710         struct ast_channel *carr[2], *who;
1711         int to=-1;
1712         struct ast_frame *f;
1713   
1714         ch1=get_chan_by_ast(c0);
1715         ch2=get_chan_by_ast(c1);
1716
1717         carr[0]=c0;
1718         carr[1]=c1;
1719   
1720   
1721         if (ch1 && ch2 ) ;
1722         else
1723                 return -1;
1724   
1725
1726         int bridging;
1727         misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
1728         if (bridging) {
1729                 int ecwb;
1730                 misdn_cfg_get( ch1->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
1731                 if ( !ecwb ) {
1732                         chan_misdn_log(0, ch1->bc->port, "Disabling Echo Cancellor when Bridged\n");
1733                         ch1->bc->ec_enable=0;
1734                         manager_ec_disable(ch1->bc);
1735                 }
1736                 misdn_cfg_get( ch2->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
1737                 if ( !ecwb ) {
1738                         chan_misdn_log(0, ch2->bc->port, "Disabling Echo Cancellor when Bridged\n");
1739                         ch2->bc->ec_enable=0;
1740                         manager_ec_disable(ch2->bc);
1741                 }
1742                 
1743                 /* trying to make a mISDN_dsp conference */
1744                 chan_misdn_log(0, ch1->bc->port, "I SEND: Making conference with Number:%d\n", (ch1->bc->pid<<1) +1);
1745
1746                 misdn_lib_bridge(ch1->bc,ch2->bc);
1747         }
1748         
1749         chan_misdn_log(1, ch1->bc->port, "* Makeing Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
1750   
1751         while(1) {
1752                 to=-1;
1753                 who = ast_waitfor_n(carr, 2, &to);
1754
1755                 if (!who) {
1756                         ast_log(LOG_DEBUG,"misdn_bridge: empty read\n");
1757                         continue;
1758                 }
1759                 f = ast_read(who);
1760     
1761                 if (!f || f->frametype == AST_FRAME_CONTROL) {
1762                         /* got hangup .. */
1763                         *fo=f;
1764                         *rc=who;
1765       
1766                         break;
1767                 }
1768     
1769     
1770                 if (who == c0) {
1771                         ast_write(c1,f);
1772                 }
1773                 else {
1774                         ast_write(c0,f);
1775                 }
1776     
1777         }
1778   
1779         if (bridging) {
1780                 misdn_lib_split_bridge(ch1->bc,ch2->bc);
1781         }
1782   
1783         return 0;
1784 }
1785
1786 /** AST INDICATIONS END **/
1787
1788 static int start_bc_tones(struct chan_list* cl)
1789 {
1790         manager_bchannel_activate(cl->bc);
1791         manager_send_tone(cl->bc ,TONE_NONE);
1792         cl->notxtone=0;
1793         cl->norxtone=0;
1794         return 0;
1795 }
1796
1797 static int stop_bc_tones(struct chan_list *cl)
1798 {
1799         if (cl->bc) {
1800                 manager_bchannel_deactivate(cl->bc);
1801         }
1802         cl->notxtone=1;
1803         cl->norxtone=1;
1804         
1805         return 0;
1806 }
1807
1808
1809 struct chan_list *init_chan_list(void)
1810 {
1811         struct chan_list *cl=malloc(sizeof(struct chan_list));
1812         
1813         if (!cl) {
1814                 chan_misdn_log(0, 0, "misdn_request: malloc failed!");
1815                 return NULL;
1816         }
1817         
1818         memset(cl,0,sizeof(struct chan_list));
1819         
1820         return cl;
1821         
1822 }
1823
1824 static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
1825
1826 {
1827         struct ast_channel *tmp = NULL;
1828         char group[BUFFERSIZE]="";
1829         char buf[128];
1830         char buf2[128], *ext=NULL, *port_str;
1831         char *tokb=NULL, *p=NULL;
1832         int channel=0, port=0;
1833         struct misdn_bchannel *newbc = NULL;
1834         
1835         struct chan_list *cl=init_chan_list();
1836         
1837         sprintf(buf,"%s/%s",type,(char*)data);
1838         strncpy(buf2,data, 128);
1839         buf2[127] = 0;
1840         port_str=strtok_r(buf2,"/", &tokb);
1841
1842         ext=strtok_r(NULL,"/", &tokb);
1843         
1844         if (!ext) {
1845                 ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITH WRONG ARGS, check extension.conf\n",ext);
1846                 
1847                 return NULL;
1848         }
1849         
1850         if (port_str) {
1851                 if (port_str[0]=='g' && port_str[1]==':' ) {
1852                         /* We make a group call lets checkout which ports are in my group */
1853                         port_str += 2;
1854                         strncpy(group, port_str, BUFFERSIZE);
1855                         group[127] = 0;
1856                         chan_misdn_log(2, 0, " --> Group Call group: %s\n",group);
1857                 } 
1858                 else if ((p = strchr(port_str, ':'))) {
1859                         // we have a preselected channel
1860                         *p = 0;
1861                         channel = atoi(++p);
1862                         port = atoi(port_str);
1863                         chan_misdn_log(2, port, " --> Call on preselected Channel (%d) on Port %d\n", channel, port);
1864                 }
1865                 else {
1866                         port = atoi(port_str);
1867                 }
1868                 
1869                 
1870         } else {
1871                 ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extension.conf\n",ext);
1872                 return NULL;
1873         }
1874
1875         if (!ast_strlen_zero(group)) {
1876         
1877                 char cfg_group[BUFFERSIZE];
1878                 struct robin_list *rr = NULL;
1879
1880                 if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
1881                         chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...");
1882                         rr = get_robin_position(group);
1883                 }
1884                 
1885                 if (rr) {
1886                         int robin_channel = rr->channel;
1887                         int port_start;
1888                         int next_chan = 1;
1889
1890                         do {
1891                                 port_start = 0;
1892                                 for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start;
1893                                          port = misdn_cfg_get_next_port_spin(port)) {
1894
1895                                         if (!port_start)
1896                                                 port_start = port;
1897
1898                                         if (port >= port_start)
1899                                                 next_chan = 1;
1900                                         
1901                                         if (port < port_start && next_chan) {
1902                                                 if (++robin_channel >= MAX_BCHANS) {
1903                                                         robin_channel = 1;
1904                                                 }
1905                                                 next_chan = 0;
1906                                         }
1907
1908                                         misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
1909                                         
1910                                         if (!strcasecmp(cfg_group, group)) {
1911                                                 int l1, port_up;
1912                                         
1913                                                 misdn_cfg_get( 0, MISDN_GEN_L1_INFO_OK, &l1, sizeof(l1));
1914                                                 port_up = misdn_lib_port_up(port);
1915                                                 
1916                                                 if ((l1 && port_up) || !l1)     {
1917                                                         newbc = misdn_lib_get_free_bc(port, robin_channel);
1918                                                         if (newbc) {
1919                                                                 chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
1920                                                                 if (port_up)
1921                                                                         chan_misdn_log(4, port, "def_l1:%d, portup:%d\n", l1, port_up);
1922                                                                 rr->port = newbc->port;
1923                                                                 rr->channel = newbc->channel;
1924                                                                 break;
1925                                                         }
1926                                                 }
1927                                         }
1928                                 }
1929                         } while (!newbc && robin_channel != rr->channel);
1930                         
1931                         if (!newbc)
1932                                 chan_misdn_log(4, port, " Failed! No free channel in group %d!", group);
1933                 }
1934                 
1935                 else {          
1936                         for (port=misdn_cfg_get_next_port(0); port > 0;
1937                                  port=misdn_cfg_get_next_port(port)) {
1938                                 
1939                                 misdn_cfg_get( port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
1940                                 
1941                                 if (!strcasecmp(cfg_group, group)) {
1942                                         int l1, port_up;
1943                                         
1944                                         misdn_cfg_get( 0, MISDN_GEN_L1_INFO_OK, &l1, sizeof(l1));
1945                                         port_up = misdn_lib_port_up(port);
1946
1947                                         chan_misdn_log(4, port, "def_l1:%d, portup:%d\n", l1, port_up);
1948                                         
1949                                         if ((l1 && port_up) || !l1)     {
1950                                                 newbc = misdn_lib_get_free_bc(port, 0);
1951                                                 if (newbc)
1952                                                         break;
1953                                         }
1954                                 }
1955                         }
1956                 }
1957                 
1958         } else {
1959                 if (channel)
1960                         chan_misdn_log(1, port," --> preselected_channel: %d\n",channel);
1961                 newbc = misdn_lib_get_free_bc(port, channel);
1962         }
1963         
1964         if (!newbc) {
1965                 chan_misdn_log(1, 0, " --> ! No free channel chan ext:%s even after Group Call\n",ext);
1966                 chan_misdn_log(1, 0, " --> SEND: State Down\n");
1967                 return NULL;
1968         }
1969         
1970         cl->bc=newbc;
1971         
1972         tmp = misdn_new(cl, AST_STATE_RESERVED, buf, "default", ext, ext, format, port, channel);
1973         
1974         return tmp;
1975 }
1976
1977
1978 struct ast_channel_tech misdn_tech = {
1979         .type="mISDN",
1980         .description="Channel driver for mISDN Support (Bri/Pri)",
1981         .capabilities= AST_FORMAT_ALAW ,
1982         .requester=misdn_request,
1983         .send_digit=misdn_digit,
1984         .call=misdn_call,
1985         .bridge=misdn_bridge, 
1986         .hangup=misdn_hangup,
1987         .answer=misdn_answer,
1988         .read=misdn_read,
1989         .write=misdn_write,
1990         .indicate=misdn_indication,
1991         .fixup=misdn_fixup,
1992         .properties=0
1993         /* .transfer=misdn_transfer */
1994 };
1995
1996 struct ast_channel_tech misdn_tech_wo_bridge = {
1997         .type="mISDN",
1998         .description="Channel driver for mISDN Support (Bri/Pri)",
1999         .capabilities=AST_FORMAT_ALAW ,
2000         .requester=misdn_request,
2001         .send_digit=misdn_digit,
2002         .call=misdn_call,
2003         .hangup=misdn_hangup,
2004         .answer=misdn_answer,
2005         .read=misdn_read,
2006         .write=misdn_write,
2007         .indicate=misdn_indication,
2008         .fixup=misdn_fixup,
2009         .properties=0
2010         /* .transfer=misdn_transfer */
2011 };
2012
2013
2014 unsigned long glob_channel=0;
2015
2016 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)
2017 {
2018         struct ast_channel *tmp;
2019         
2020         tmp = ast_channel_alloc(0);
2021         
2022         if (tmp) {
2023                 chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s ctx:%s\n",exten,callerid, context);
2024                 
2025                 
2026                 if (c<=0) {
2027                         c=glob_channel++;
2028                         snprintf(tmp->name, sizeof(tmp->name), "%s/%d-u%d",
2029                                  type, port, c);
2030                 } else {
2031                         snprintf(tmp->name, sizeof(tmp->name), "%s/%d-%d",
2032                                  type, port, c);
2033                 }
2034                 
2035                 tmp->type = type;
2036     
2037                 tmp->nativeformats = prefformat;
2038                 tmp->readformat = format;
2039                 tmp->writeformat = format;
2040     
2041                 tmp->tech_pvt = chlist;
2042
2043                 int bridging;
2044                 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
2045                 if (bridging)
2046                         tmp->tech = &misdn_tech;
2047                 else
2048                         tmp->tech = &misdn_tech_wo_bridge;
2049     
2050     
2051                 tmp->writeformat = format;
2052                 tmp->readformat = format;
2053                 tmp->priority=1;
2054     
2055     
2056                 strncpy(tmp->context, context, sizeof(tmp->context)-1);
2057                 strncpy(tmp->exten, exten,  sizeof(tmp->exten) - 1);
2058
2059                 if (callerid) {
2060                         char *cid_name, *cid_num;
2061       
2062                         ast_callerid_parse(callerid, &cid_name, &cid_num);
2063                         if (cid_name)
2064                                 tmp->cid.cid_name=strdup(cid_name);
2065                         if (cid_num)
2066                                 tmp->cid.cid_num=strdup(cid_num);
2067                 }
2068
2069                 {
2070                         if (pipe(chlist->pipe)<0)
2071                                 perror("Pipe failed\n");
2072                         
2073                         tmp->fds[0]=chlist->pipe[0];
2074                         
2075                 }
2076                 
2077                 if (chlist->bc) {
2078                         int port=chlist->bc->port;
2079                         misdn_cfg_get( port, MISDN_CFG_LANGUAGE, tmp->language, sizeof(tmp->language));
2080                         
2081                         {
2082                                 char buf[256];
2083                                 ast_group_t pg,cg;
2084                                 
2085                                 misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
2086                                 misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
2087                                 
2088                                 chan_misdn_log(2, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
2089                                 tmp->pickupgroup=pg;
2090                                 tmp->callgroup=cg;
2091                         }
2092                         misdn_cfg_get(port, MISDN_CFG_TXGAIN, &chlist->bc->txgain, sizeof(int));
2093                         misdn_cfg_get(port, MISDN_CFG_RXGAIN, &chlist->bc->rxgain, sizeof(int));
2094                         chan_misdn_log(2, port, " --> rxgain:%d txgain:%d\n",chlist->bc->rxgain,chlist->bc->txgain);
2095                         
2096                 } else {
2097                         chan_misdn_log(3, 0, " --> Not Setting Pickupgroup, we have no bc yet\n");
2098                 }
2099                 
2100                 ast_setstate(tmp, state);
2101                 if (state == AST_STATE_RING)
2102                         tmp->rings = 1;
2103                 else
2104                         tmp->rings = 0;
2105         } else {
2106                 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
2107                 chan_misdn_log(0,0,"Unable to allocate channel structure\n");
2108         }
2109         
2110         return tmp;
2111 }
2112
2113
2114
2115 int misdn_tx2ast_frm(struct chan_list * tmp, char * buf,  int len )
2116 {
2117         struct ast_frame frame;
2118         
2119         /* If in hold state we drop frame .. */
2120         if (tmp->holded ) return 0;
2121
2122         switch(tmp->state) {
2123         case MISDN_CLEANING:
2124         case MISDN_EXTCANTMATCH:
2125         case MISDN_WAITING4DIGS:
2126                 return 0;
2127         default:
2128                 break;
2129         }
2130         
2131         if (tmp->norxtone) {
2132                 chan_misdn_log(3, tmp->bc->port, "misdn_tx2ast_frm: Returning because norxtone\n");
2133                 return 0;
2134         }
2135         
2136         frame.frametype  = AST_FRAME_VOICE;
2137         frame.subclass = AST_FORMAT_ALAW;
2138         frame.datalen = len;
2139         frame.samples = len ;
2140         frame.mallocd =0 ;
2141         frame.offset= 0 ;
2142         frame.src = NULL;
2143         frame.data = buf ;
2144         
2145         if (tmp->faxdetect || tmp->ast_dsp ) {
2146                 struct ast_frame *f,*f2;
2147                 if (tmp->trans)
2148                         f2=ast_translate(tmp->trans, &frame,0);
2149                 else {
2150                         chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
2151                         return 0;
2152                 }
2153                 
2154                 f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
2155                 if (f && (f->frametype == AST_FRAME_DTMF)) {
2156                         ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c", f->subclass);
2157                         if (f->subclass == 'f' && tmp->faxdetect) {
2158                                 /* Fax tone -- Handle and return NULL */
2159                                 struct ast_channel *ast = tmp->ast;
2160                                 if (!tmp->faxhandled) {
2161                                         tmp->faxhandled++;
2162                                         if (strcmp(ast->exten, "fax")) {
2163                                                 if (ast_exists_extension(ast, ast_strlen_zero(ast->macrocontext)? ast->context : ast->macrocontext, "fax", 1, AST_CID_P(ast))) {
2164                                                         if (option_verbose > 2)
2165                                                                 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
2166                                                         /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
2167                                                         pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
2168                                                         if (ast_async_goto(ast, ast->context, "fax", 1))
2169                                                                 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, ast->context);
2170                                                 } else
2171                                                         ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n",ast->context, ast->exten);
2172                                         } else
2173                                                 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
2174                                 } else
2175                                         ast_log(LOG_DEBUG, "Fax already handled\n");
2176                                 frame.frametype = AST_FRAME_NULL;
2177                                 frame.subclass = 0;
2178                                 f = &frame;
2179                         }  else if ( tmp->ast_dsp) {
2180                                 struct ast_frame fr;
2181                                 memset(&fr, 0 , sizeof(fr));
2182                                 fr.frametype = AST_FRAME_DTMF;
2183                                 fr.subclass = f->subclass ;
2184                                 fr.src=NULL;
2185                                 fr.data = NULL ;
2186                                 fr.datalen = 0;
2187                                 fr.samples = 0 ;
2188                                 fr.mallocd =0 ;
2189                                 fr.offset= 0 ;
2190                                 
2191                                 chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n",f->subclass);
2192                                 ast_queue_frame(tmp->ast, &fr);
2193                                 
2194                                 frame.frametype = AST_FRAME_NULL;
2195                                 frame.subclass = 0;
2196                                 f = &frame;
2197                         }
2198                 }
2199         }
2200         
2201         if (tmp && tmp->ast && MISDN_ASTERISK_PVT (tmp->ast) && MISDN_ASTERISK_TECH_PVT(tmp->ast) ) {
2202 #if MISDN_DEBUG
2203                 int i, max=5>len?len:5;
2204     
2205                 printf("write2* %p %d bytes: ",tmp, len);
2206     
2207                 for (i=0; i<  max ; i++) printf("%2.2x ",((char*) frame.data)[i]);
2208                 printf ("\n");
2209 #endif
2210                 chan_misdn_log(9, tmp->bc->port, "Queueing %d bytes 2 Asterisk\n",len);
2211                 
2212                 ast_queue_frame(tmp->ast,&frame);
2213                 
2214         }  else {
2215                 ast_log (LOG_WARNING, "No ast || ast->pvt || ch\n");
2216         }
2217         
2218         return 0;
2219 }
2220
2221 /** Channel Queue ***/
2222
2223 struct chan_list *find_chan_by_l3id(struct chan_list *list, unsigned long l3id)
2224 {
2225         struct chan_list *help=list;
2226         for (;help; help=help->next) {
2227                 if (help->l3id == l3id ) return help;
2228         }
2229   
2230         chan_misdn_log(4, list? (list->bc? list->bc->port : 0) : 0, "$$$ find_chan: No channel found with l3id:%x\n",l3id);
2231   
2232         return NULL;
2233 }
2234
2235 struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
2236 {
2237         struct chan_list *help=list;
2238         for (;help; help=help->next) {
2239                 if (help->bc == bc) return help;
2240         }
2241   
2242         chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
2243   
2244         return NULL;
2245 }
2246
2247
2248 struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
2249 {
2250         struct chan_list *help=list;
2251         
2252         chan_misdn_log(4, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
2253         for (;help; help=help->next) {
2254                 chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->bc->holded, help->bc->channel);
2255                 if (help->bc->port == bc->port
2256                     && help->bc->holded ) return help;
2257         }
2258         
2259         chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
2260   
2261         return NULL;
2262 }
2263
2264 void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
2265 {
2266         chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan);
2267   
2268         ast_mutex_lock(&cl_te_lock);
2269         if (!*list) {
2270                 *list = chan;
2271         } else {
2272                 struct chan_list *help=*list;
2273                 for (;help->next; help=help->next); 
2274                 help->next=chan;
2275         }
2276         chan->next=NULL;
2277         ast_mutex_unlock(&cl_te_lock);
2278 }
2279
2280 void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan) 
2281 {
2282         if (chan->dsp) 
2283                 ast_dsp_free(chan->dsp);
2284         if (chan->trans)
2285                 ast_translator_free_path(chan->trans);
2286         
2287
2288         ast_mutex_lock(&cl_te_lock);
2289         if (!*list) {
2290                 ast_mutex_unlock(&cl_te_lock);
2291                 return;
2292         }
2293   
2294         if (*list == chan) {
2295                 *list=(*list)->next;
2296                 ast_mutex_unlock(&cl_te_lock);
2297                 return ;
2298         }
2299   
2300         {
2301                 struct chan_list *help=*list;
2302                 for (;help->next; help=help->next) {
2303                         if (help->next == chan) {
2304                                 help->next=help->next->next;
2305                                 ast_mutex_unlock(&cl_te_lock);
2306                                 return;
2307                         }
2308                 }
2309         }
2310         
2311         ast_mutex_unlock(&cl_te_lock);
2312 }
2313
2314 /** Channel Queue End **/
2315
2316
2317
2318 /** Isdn asks us to release channel, pendant to misdn_hangup **/
2319 static void release_chan(struct misdn_bchannel *bc) {
2320         struct ast_channel *ast=NULL;
2321         
2322         {
2323                 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
2324                 if (!ch) ch=find_chan_by_l3id (cl_te, bc->l3_id);
2325                 
2326                 release_lock;
2327                 if (ch->ast) {
2328                         ast=ch->ast;
2329                 } 
2330                 release_unlock;
2331                 
2332                 chan_misdn_log(1, bc->port, "Trying to Release bc with l3id: %x\n",bc->l3_id);
2333                 if (ch) {
2334                         if (ast)
2335                                 chan_misdn_trace_call(ast,1,"I->*: EVENT_RELEASE\n");
2336                         
2337                         close(ch->pipe[0]);
2338                         close(ch->pipe[1]);
2339                         
2340                         if (ast && MISDN_ASTERISK_PVT(ast)) {
2341                                 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));
2342                                 chan_misdn_log(3, bc->port, " --> * State Down\n");
2343                                 /* copy cause */
2344                                 send_cause2ast(ast,bc);
2345                                 
2346                                 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
2347                                 
2348       
2349                                 if (ast->_state != AST_STATE_RESERVED) {
2350                                         chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
2351                                         ast_setstate(ast, AST_STATE_DOWN);
2352                                 }
2353                                 
2354                                 switch(ch->state) {
2355                                 case MISDN_EXTCANTMATCH:
2356                                 case MISDN_WAITING4DIGS:
2357                                 {
2358                                         chan_misdn_log(3,  bc->port, " --> * State Wait4dig | ExtCantMatch\n");
2359                                         ast_hangup(ast);
2360                                 }
2361                                 break;
2362                                 
2363                                 case MISDN_DIALING:
2364                                 case MISDN_CALLING_ACKNOWLEDGE:
2365                                 case MISDN_PROGRESS:
2366                                         chan_misdn_log(2,  bc->port, "* --> In State Dialin\n");
2367                                         chan_misdn_log(2,  bc->port, "* --> Queue Hangup\n");
2368                                         
2369
2370                                         ast_queue_hangup(ast);
2371                                         break;
2372                                 case MISDN_CALLING:
2373                                         
2374                                         chan_misdn_log(2,  bc->port, "* --> In State Callin\n");
2375                                         
2376                                         if (!bc->nt) {
2377                                                 chan_misdn_log(2,  bc->port, "* --> Queue Hangup\n");
2378                                                 ast_queue_hangup(ast);
2379                                         } else {
2380                                                 chan_misdn_log(2,  bc->port, "* --> Hangup\n");
2381                                                 ast_queue_hangup(ast);
2382                                                 //ast_hangup(ast);
2383                                         }
2384                                         break;
2385                                         
2386                                 case MISDN_CLEANING:
2387                                         /* this state comes out of ast so we mustnt call a ast function ! */
2388                                         chan_misdn_log(2,  bc->port, "* --> In StateCleaning\n");
2389                                         break;
2390                                 case MISDN_HOLD_DISCONNECT:
2391                                         chan_misdn_log(2,  bc->port, "* --> In HOLD_DISC\n");
2392                                         break;
2393                                 default:
2394                                         chan_misdn_log(2,  bc->port, "* --> In State Default\n");
2395                                         chan_misdn_log(2,  bc->port, "* --> Queue Hangup\n");
2396         
2397                                         
2398                                         if (ast && MISDN_ASTERISK_PVT(ast)) {
2399                                                 ast_queue_hangup(ast);
2400                                         } else {
2401                                                 chan_misdn_log (0,  bc->port, "!! Not really queued!\n");
2402                                         }
2403                                 }
2404                         }
2405                         cl_dequeue_chan(&cl_te, ch);
2406                         
2407                         free(ch);
2408                 } else {
2409                         /* chan is already cleaned, so exiting  */
2410                 }
2411         }
2412 }
2413 /*** release end **/
2414
2415 void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
2416 {
2417         chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan->ast->name, tmp_ch->ast->name);
2418         
2419         tmp_ch->state=MISDN_HOLD_DISCONNECT;
2420   
2421         ast_moh_stop(AST_BRIDGED_P(holded_chan->ast));
2422
2423         holded_chan->state=MISDN_CONNECTED;
2424         holded_chan->holded=0;
2425         misdn_lib_transfer(holded_chan->bc?holded_chan->bc:holded_chan->holded_bc);
2426         
2427         ast_channel_masquerade(holded_chan->ast, AST_BRIDGED_P(tmp_ch->ast));
2428 }
2429
2430
2431 void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast)
2432 {
2433         char predial[256]="";
2434         char *p = predial;
2435   
2436         struct ast_frame fr;
2437   
2438         strncpy(predial, ast->exten, sizeof(predial) -1 );
2439   
2440         ch->state=MISDN_DIALING;
2441         
2442         if (bc->nt) {
2443                 int ret; 
2444                 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
2445         } else {
2446                 int ret;
2447                 if ( misdn_lib_is_ptp(bc->port)) {
2448                         ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
2449                 } else {
2450                         ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
2451                 }
2452         }
2453
2454         manager_send_tone(bc,TONE_DIAL);  
2455   
2456         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));
2457   
2458         strncpy(ast->exten,"s", 2);
2459   
2460         if (ast_pbx_start(ast)<0) {
2461                 ast=NULL;
2462                 manager_send_tone(bc,TONE_BUSY);
2463                 if (bc->nt)
2464                         misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
2465                 else
2466                         misdn_lib_send_event(bc, EVENT_DISCONNECT );
2467         }
2468   
2469   
2470         while (!ast_strlen_zero(p) ) {
2471                 fr.frametype = AST_FRAME_DTMF;
2472                 fr.subclass = *p ;
2473                 fr.src=NULL;
2474                 fr.data = NULL ;
2475                 fr.datalen = 0;
2476                 fr.samples = 0 ;
2477                 fr.mallocd =0 ;
2478                 fr.offset= 0 ;
2479
2480                 if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
2481                         ast_queue_frame(ch->ast, &fr);
2482                 }
2483                 p++;
2484         }
2485 }
2486
2487
2488
2489 void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc) {
2490         
2491         ast->hangupcause=bc->cause;
2492         
2493         switch ( bc->cause) {
2494                 
2495         case 1: /** Congestion Cases **/
2496         case 2:
2497         case 3:
2498         case 4:
2499         case 22:
2500         case 27:
2501                 chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Congestion pid:%d\n", bc?bc->pid:-1);
2502                 
2503                 ast_queue_control(ast, AST_CONTROL_CONGESTION);
2504                 break;
2505                 
2506         case 21:
2507         case 17: /* user busy */
2508                 chan_misdn_log(1,  bc?bc->port:0, " --> * SEND: Queue Busy pid:%d\n", bc?bc->pid:-1);
2509                 
2510                 ast_queue_control(ast, AST_CONTROL_BUSY);
2511                 
2512                 break;
2513         }
2514 }
2515
2516 /************************************************************/
2517 /*  Receive Events from isdn_lib  here                     */
2518 /************************************************************/
2519 enum event_response_e
2520 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
2521 {
2522         struct chan_list *ch=find_chan_by_bc(cl_te, bc);
2523         
2524         if (!ch)
2525                 ch=find_chan_by_l3id(cl_te, bc->l3_id);
2526         
2527         if (event != EVENT_BCHAN_DATA) { /*  Debug Only Non-Bchan */
2528                 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);
2529                 misdn_lib_log_ies(bc);
2530         }
2531         
2532         if (event != EVENT_SETUP) {
2533                 if (!ch) {
2534                         if (event != EVENT_CLEANUP )
2535                                 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);
2536                         return -1;
2537                 }
2538         }
2539         
2540         if (ch ) {
2541                 switch (event) {
2542                 case EVENT_RELEASE:
2543                 case EVENT_RELEASE_COMPLETE:
2544                 case EVENT_CLEANUP:
2545                         break;
2546                 default:
2547                         if ( !ch->ast  || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
2548                                 if (event!=EVENT_BCHAN_DATA)
2549                                         ast_log(LOG_WARNING, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
2550                                 return -1;
2551                         }
2552                 }
2553         }
2554         
2555         
2556         switch (event) {
2557         case EVENT_NEW_L3ID:
2558                 ch->l3id=bc->l3_id;
2559                 break;
2560
2561         case EVENT_NEW_BC:
2562                 if (bc)
2563                         ch->bc=bc;
2564                 break;
2565                 
2566         case EVENT_DTMF_TONE:
2567         {
2568                 /*  sending INFOS as DTMF-Frames :) */
2569                 struct ast_frame fr;
2570                 memset(&fr, 0 , sizeof(fr));
2571                 fr.frametype = AST_FRAME_DTMF;
2572                 fr.subclass = bc->dtmf ;
2573                 fr.src=NULL;
2574                 fr.data = NULL ;
2575                 fr.datalen = 0;
2576                 fr.samples = 0 ;
2577                 fr.mallocd =0 ;
2578                 fr.offset= 0 ;
2579                 
2580                 chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
2581                 
2582                 ast_queue_frame(ch->ast, &fr);
2583         }
2584         break;
2585         case EVENT_STATUS:
2586                 break;
2587     
2588         case EVENT_INFORMATION:
2589         {
2590                 int stop_tone;
2591                 misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
2592                 if ( stop_tone && bc->tone != TONE_NONE) {
2593                         manager_send_tone(bc,TONE_NONE);
2594                 }
2595                 
2596                 if (ch->state == MISDN_WAITING4DIGS ) {
2597                         /*  Ok, incomplete Setup, waiting till extension exists */
2598                         {
2599                                 int l = sizeof(bc->dad);
2600                                 strncat(bc->dad,bc->info_dad, l);
2601                                 bc->dad[l-1] = 0;
2602                         }
2603                         
2604                         
2605                         {
2606                                 int l = sizeof(ch->ast->exten);
2607                                 strncpy(ch->ast->exten, bc->dad, l);
2608                                 ch->ast->exten[l-1] = 0;
2609                         }
2610 /*                      chan_misdn_log(5, bc->port, "Can Match Extension: dad:%s oad:%s\n",bc->dad,bc->oad);*/
2611                         
2612                         char bc_context[BUFFERSIZE];
2613                         misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
2614                         if(!ast_canmatch_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
2615                                 chan_misdn_log(0, bc->port, "Extension can never match, so disconnecting\n");
2616                                 manager_send_tone(bc,TONE_BUSY);
2617                                 ch->state=MISDN_EXTCANTMATCH;
2618                                 bc->out_cause=1;
2619                                 if (bc->nt)
2620                                         misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
2621                                 else
2622                                         misdn_lib_send_event(bc, EVENT_DISCONNECT );
2623                                 break;
2624                         }
2625                         if (ast_exists_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
2626                                 ch->state=MISDN_DIALING;
2627           
2628                                 manager_send_tone(bc,TONE_NONE);
2629 /*                              chan_misdn_log(1, bc->port, " --> * Starting Ast ctx:%s\n", ch->ast->context);*/
2630                                 if (ast_pbx_start(ch->ast)<0) {
2631                                         chan_misdn_log(0, bc->port, "ast_pbx_start returned < 0 in INFO\n");
2632                                         manager_send_tone(bc,TONE_BUSY);
2633                                         if (bc->nt)
2634                                                 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
2635                                         else
2636                                                 misdn_lib_send_event(bc, EVENT_DISCONNECT );
2637                                 }
2638                         }
2639         
2640                 } else {
2641                         /*  sending INFOS as DTMF-Frames :) */
2642                         struct ast_frame fr;
2643                         fr.frametype = AST_FRAME_DTMF;
2644                         fr.subclass = bc->info_dad[0] ;
2645                         fr.src=NULL;
2646                         fr.data = NULL ;
2647                         fr.datalen = 0;
2648                         fr.samples = 0 ;
2649                         fr.mallocd =0 ;
2650                         fr.offset= 0 ;
2651
2652                         
2653                         int digits;
2654                         misdn_cfg_get( 0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
2655                         if (ch->state != MISDN_CONNECTED ) {
2656                                 if (digits) {
2657                                         int l = sizeof(bc->dad);
2658                                         strncat(bc->dad,bc->info_dad, l);
2659                                         bc->dad[l-1] = 0;
2660                                         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                                 
2667                                 ast_queue_frame(ch->ast, &fr);
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         }