Merged revisions 64515 via svnmerge from
[asterisk/asterisk.git] / channels / chan_misdn.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  * 
4  * Copyright (C) 2004 - 2006, 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  *
25  * \author Christian Richter <crich@beronet.com>
26  *
27  * \extref MISDN http://www.misdn.org/
28  *
29  * \ingroup channel_drivers
30  */
31
32 /*** MODULEINFO
33         <depend>isdnnet</depend>
34         <depend>misdn</depend>
35         <depend>suppserv</depend>
36  ***/
37 #include "asterisk.h"
38
39 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
40
41 #include <stdio.h>
42 #include <pthread.h>
43 #include <string.h>
44 #include <sys/socket.h>
45 #include <sys/time.h>
46 #include <errno.h>
47 #include <unistd.h>
48 #include <stdlib.h>
49 #include <arpa/inet.h>
50 #include <fcntl.h>
51 #include <sys/ioctl.h>
52 #include <signal.h>
53 #include <sys/file.h>
54 #include <semaphore.h>
55
56 #include "asterisk/channel.h"
57 #include "asterisk/config.h"
58 #include "asterisk/logger.h"
59 #include "asterisk/module.h"
60 #include "asterisk/pbx.h"
61 #include "asterisk/options.h"
62 #include "asterisk/io.h"
63 #include "asterisk/frame.h"
64 #include "asterisk/translate.h"
65 #include "asterisk/cli.h"
66 #include "asterisk/musiconhold.h"
67 #include "asterisk/dsp.h"
68 #include "asterisk/translate.h"
69 #include "asterisk/config.h"
70 #include "asterisk/file.h"
71 #include "asterisk/callerid.h"
72 #include "asterisk/indications.h"
73 #include "asterisk/app.h"
74 #include "asterisk/features.h"
75 #include "asterisk/term.h"
76 #include "asterisk/sched.h"
77 #include "asterisk/stringfields.h"
78
79 #include "chan_misdn_config.h"
80 #include "isdn_lib.h"
81
82 char global_tracefile[BUFFERSIZE+1];
83
84 static int g_config_initialized=0;
85
86 struct misdn_jb{
87         int size;
88         int upper_threshold;
89         char *samples, *ok;
90         int wp,rp;
91         int state_empty;
92         int state_full;
93         int state_buffer;
94         int bytes_wrote;
95         ast_mutex_t mutexjb;
96 };
97
98
99
100 /*! \brief allocates the jb-structure and initialise the elements*/
101 struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
102
103 /*! \brief frees the data and destroys the given jitterbuffer struct */
104 void misdn_jb_destroy(struct misdn_jb *jb);
105
106 /*! \brief fills the jitterbuffer with len data returns < 0 if there was an
107 error (bufferoverun). */
108 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);
109
110 /*! \brief gets len bytes out of the jitterbuffer if available, else only the
111 available data is returned and the return value indicates the number
112 of data. */
113 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len);
114
115
116 enum misdn_chan_state {
117         MISDN_NOTHING=0,        /*!< at beginning */
118         MISDN_WAITING4DIGS, /*!<  when waiting for infos */
119         MISDN_EXTCANTMATCH, /*!<  when asterisk couldnt match our ext */
120         MISDN_INCOMING_SETUP, /*!<  for incoming setups*/
121         MISDN_DIALING, /*!<  when pbx_start */
122         MISDN_PROGRESS, /*!<  we got a progress */
123         MISDN_PROCEEDING, /*!<  we got a progress */
124         MISDN_CALLING, /*!<  when misdn_call is called */
125         MISDN_CALLING_ACKNOWLEDGE, /*!<  when we get SETUP_ACK */
126         MISDN_ALERTING, /*!<  when Alerting */
127         MISDN_BUSY, /*!<  when BUSY */
128         MISDN_CONNECTED, /*!<  when connected */
129         MISDN_PRECONNECTED, /*!<  when connected */
130         MISDN_DISCONNECTED, /*!<  when connected */
131         MISDN_RELEASED, /*!<  when connected */
132         MISDN_BRIDGED, /*!<  when bridged */
133         MISDN_CLEANING, /*!< when hangup from * but we were connected before */
134         MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
135         MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of */
136         /* misdn_hangup */
137         MISDN_HOLDED, /*!< if this chan is holded */
138         MISDN_HOLD_DISCONNECT, /*!< if this chan is holded */
139   
140 };
141
142 #define ORG_AST 1
143 #define ORG_MISDN 2
144
145 struct hold_info {
146         int port;
147         int channel;
148 };
149
150 struct chan_list {
151   
152         char allowed_bearers[BUFFERSIZE+1];
153         
154         enum misdn_chan_state state;
155         int need_queue_hangup;
156         int need_hangup;
157         int need_busy;
158         
159         int originator;
160         int noautorespond_on_setup;
161         
162         int norxtone;
163         int notxtone; 
164
165         int toggle_ec;
166         
167         int incoming_early_audio;
168
169         int ignore_dtmf;
170
171         int pipe[2];
172         char ast_rd_buf[4096];
173         struct ast_frame frame;
174
175         int faxdetect; /*!<  0:no 1:yes 2:yes+nojump */
176         int faxdetect_timeout;
177         struct timeval faxdetect_tv;
178         int faxhandled;
179
180         int ast_dsp;
181
182         int jb_len;
183         int jb_upper_threshold;
184         struct misdn_jb *jb;
185         
186         struct ast_dsp *dsp;
187         struct ast_trans_pvt *trans;
188   
189         struct ast_channel * ast;
190
191         int dummy;
192   
193         struct misdn_bchannel *bc;
194
195         struct hold_info hold_info;
196
197         unsigned int l3id;
198         int addr;
199
200         char context[BUFFERSIZE];
201
202         int zero_read_cnt;
203         int dropped_frame_cnt;
204
205         int far_alerting;
206
207         int nttimeout;
208
209         int other_pid;
210         struct chan_list *other_ch;
211
212         const struct ind_tone_zone_sound *ts;
213         
214         int overlap_dial;
215         int overlap_dial_task;
216         ast_mutex_t overlap_tv_lock;
217         struct timeval overlap_tv;
218   
219         struct chan_list *peer;
220         struct chan_list *next;
221         struct chan_list *prev;
222         struct chan_list *first;
223 };
224
225
226
227 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
228 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
229
230 struct robin_list {
231         char *group;
232         int port;
233         int channel;
234         struct robin_list *next;
235         struct robin_list *prev;
236 };
237 static struct robin_list *robin = NULL;
238
239
240
241 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
242
243
244
245 static inline void free_robin_list_r (struct robin_list *r)
246 {
247         if (r) {
248                 if (r->next) free_robin_list_r(r->next);
249                 if (r->group) free(r->group);
250                 free(r);
251         }
252 }
253
254 static void free_robin_list ( void )
255 {
256         free_robin_list_r(robin);
257         robin = NULL;
258 }
259
260 static struct robin_list* get_robin_position (char *group) 
261 {
262         struct robin_list *iter = robin;
263         for (; iter; iter = iter->next) {
264                 if (!strcasecmp(iter->group, group))
265                         return iter;
266         }
267         struct robin_list *new = (struct robin_list *)calloc(1, sizeof(struct robin_list));
268         new->group = strndup(group, strlen(group));
269         new->channel = 1;
270         if (robin) {
271                 new->next = robin;
272                 robin->prev = new;
273         }
274         robin = new;
275         return robin;
276 }
277
278
279 /*! \brief the main schedule context for stuff like l1 watcher, overlap dial, ... */
280 static struct sched_context *misdn_tasks = NULL;
281 static pthread_t misdn_tasks_thread;
282
283 static int *misdn_ports;
284
285 static void chan_misdn_log(int level, int port, char *tmpl, ...);
286
287 static struct ast_channel *misdn_new(struct chan_list *cl, int state,  char *exten, char *callerid, int format, int port, int c);
288 static void send_digit_to_chan(struct chan_list *cl, char digit );
289
290 static void hangup_chan(struct chan_list *ch);
291 static int pbx_start_chan(struct chan_list *ch);
292
293 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
294 #define MISDN_ASTERISK_PVT(ast) 1
295
296 #include <asterisk/strings.h>
297
298 /* #define MISDN_DEBUG 1 */
299
300 static const char misdn_type[] = "mISDN";
301
302 static int tracing = 0 ;
303
304 /*! \brief Only alaw and mulaw is allowed for now */
305 static int prefformat =  AST_FORMAT_ALAW ; /*  AST_FORMAT_SLINEAR ;  AST_FORMAT_ULAW | */
306
307 static int *misdn_debug;
308 static int *misdn_debug_only;
309 static int max_ports;
310
311 static int *misdn_in_calls;
312 static int *misdn_out_calls;
313
314
315 struct chan_list dummy_cl;
316
317 struct chan_list *cl_te=NULL;
318 ast_mutex_t cl_te_lock;
319
320 static enum event_response_e
321 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
322
323 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch);
324
325 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan);
326 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);
327 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);
328 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid);
329
330
331
332 static int dialtone_indicate(struct chan_list *cl);
333 static int hanguptone_indicate(struct chan_list *cl);
334 static int stop_indicate(struct chan_list *cl);
335
336 static int start_bc_tones(struct chan_list *cl);
337 static int stop_bc_tones(struct chan_list *cl);
338 static void release_chan(struct misdn_bchannel *bc);
339
340 static int misdn_check_l2l1(struct ast_channel *chan, void *data);
341 static int misdn_set_opt_exec(struct ast_channel *chan, void *data);
342 static int misdn_facility_exec(struct ast_channel *chan, void *data);
343
344 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
345
346
347 void debug_numplan(int port, int numplan, char *type);
348
349
350 int add_out_calls(int port);
351 int add_in_calls(int port);
352
353
354 #ifdef MISDN_1_2
355 static int update_pipeline_config(struct misdn_bchannel *bc);
356 #else
357 static int update_ec_config(struct misdn_bchannel *bc);
358 #endif
359
360
361
362
363 /*protos*/ 
364
365 int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len); 
366
367 /*************** Helpers *****************/
368
369 static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
370 {
371         struct chan_list *tmp;
372   
373         for (tmp=cl_te; tmp; tmp = tmp->next) {
374                 if ( tmp->ast == ast ) return tmp;
375         }
376   
377         return NULL;
378 }
379
380 static struct chan_list * get_chan_by_ast_name(char *name)
381 {
382         struct chan_list *tmp;
383   
384         for (tmp=cl_te; tmp; tmp = tmp->next) {
385                 if ( tmp->ast  && strcmp(tmp->ast->name,name) == 0) return tmp;
386         }
387   
388         return NULL;
389 }
390
391
392
393 struct allowed_bearers {
394         int cap;
395         int val;
396         char *name;
397 };
398
399 struct allowed_bearers allowed_bearers_array[]={
400         {INFO_CAPABILITY_SPEECH,1,"speech"},
401         {INFO_CAPABILITY_AUDIO_3_1K,2,"3_1khz"},
402         {INFO_CAPABILITY_DIGITAL_UNRESTRICTED,4,"digital_unrestricted"},
403         {INFO_CAPABILITY_DIGITAL_RESTRICTED,8,"digital_restriced"},
404         {INFO_CAPABILITY_VIDEO,16,"video"}
405 };
406
407 static char *bearer2str(int cap) {
408         static char *bearers[]={
409                 "Speech",
410                 "Audio 3.1k",
411                 "Unres Digital",
412                 "Res Digital",
413                 "Video",
414                 "Unknown Bearer"
415         };
416         
417         switch (cap) {
418         case INFO_CAPABILITY_SPEECH:
419                 return bearers[0];
420                 break;
421         case INFO_CAPABILITY_AUDIO_3_1K:
422                 return bearers[1];
423                 break;
424         case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
425                 return bearers[2];
426                 break;
427         case INFO_CAPABILITY_DIGITAL_RESTRICTED:
428                 return bearers[3];
429                 break;
430         case INFO_CAPABILITY_VIDEO:
431                 return bearers[4];
432                 break;
433         default:
434                 return bearers[5];
435                 break;
436         }
437 }
438
439
440 static void print_facility(struct FacParm *fac, struct misdn_bchannel *bc)
441 {
442         switch (fac->Function) {
443         case Fac_CD:
444                 chan_misdn_log(1,bc->port," --> calldeflect to: %s, screened: %s\n", fac->u.CDeflection.DeflectedToNumber,
445                                            fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
446                 break;
447         case Fac_AOCDCurrency:
448                 if (fac->u.AOCDcur.chargeNotAvailable)
449                         chan_misdn_log(1,bc->port," --> AOCD currency: charge not available\n");
450                 else if (fac->u.AOCDcur.freeOfCharge)
451                         chan_misdn_log(1,bc->port," --> AOCD currency: free of charge\n");
452                 else if (fac->u.AOCDchu.billingId >= 0)
453                         chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d billingId:%d\n",
454                                                    fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
455                                                    (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
456                 else
457                         chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d\n",
458                                                    fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
459                                                    (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
460                 break;
461         case Fac_AOCDChargingUnit:
462                 if (fac->u.AOCDchu.chargeNotAvailable)
463                         chan_misdn_log(1,bc->port," --> AOCD charging unit: charge not available\n");
464                 else if (fac->u.AOCDchu.freeOfCharge)
465                         chan_misdn_log(1,bc->port," --> AOCD charging unit: free of charge\n");
466                 else if (fac->u.AOCDchu.billingId >= 0)
467                         chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
468                                                    fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
469                 else
470                         chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
471                                                    fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
472                 break;
473         default:
474                 chan_misdn_log(1,bc->port," --> unknown\n");
475         }
476 }
477
478 static void print_bearer(struct misdn_bchannel *bc) 
479 {
480         
481         chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
482         
483         switch(bc->law) {
484         case INFO_CODEC_ALAW:
485                 chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
486                 break;
487         case INFO_CODEC_ULAW:
488                 chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
489                 break;
490         }
491 }
492
493 static void export_aoc_vars(int originator, struct ast_channel *ast, struct misdn_bchannel *bc)
494 {
495         char buf[128];
496
497         if (!bc->AOCD_need_export || !ast)
498                 return;
499
500         if (originator == ORG_AST) {
501                 ast = ast_bridged_channel(ast);
502                 if (!ast)
503                         return;
504         }
505
506         switch (bc->AOCDtype) {
507         case Fac_AOCDCurrency:
508                 pbx_builtin_setvar_helper(ast, "AOCD_Type", "currency");
509                 if (bc->AOCD.currency.chargeNotAvailable)
510                         pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
511                 else {
512                         pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
513                         if (bc->AOCD.currency.freeOfCharge)
514                                 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
515                         else {
516                                 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
517                                 if (snprintf(buf, sizeof(buf), "%d %s", bc->AOCD.currency.currencyAmount * bc->AOCD.currency.multiplier, bc->AOCD.currency.currency) < sizeof(buf)) {
518                                         pbx_builtin_setvar_helper(ast, "AOCD_Amount", buf);
519                                         if (bc->AOCD.currency.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.currency.billingId) < sizeof(buf))
520                                                 pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
521                                 }
522                         }
523                 }
524                 break;
525         case Fac_AOCDChargingUnit:
526                 pbx_builtin_setvar_helper(ast, "AOCD_Type", "charging_unit");
527                 if (bc->AOCD.chargingUnit.chargeNotAvailable)
528                         pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
529                 else {
530                         pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
531                         if (bc->AOCD.chargingUnit.freeOfCharge)
532                                 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
533                         else {
534                                 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
535                                 if (snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.recordedUnits) < sizeof(buf)) {
536                                         pbx_builtin_setvar_helper(ast, "AOCD_RecordedUnits", buf);
537                                         if (bc->AOCD.chargingUnit.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.billingId) < sizeof(buf))
538                                                 pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
539                                 }
540                         }
541                 }
542                 break;
543         default:
544                 break;
545         }
546         
547         bc->AOCD_need_export = 0;
548 }
549
550 /*************** Helpers END *************/
551
552 static void sighandler(int sig)
553 {}
554
555 static void* misdn_tasks_thread_func (void *data)
556 {
557         int wait;
558         struct sigaction sa;
559
560         sa.sa_handler = sighandler;
561         sa.sa_flags = SA_NODEFER;
562         sigemptyset(&sa.sa_mask);
563         sigaddset(&sa.sa_mask, SIGUSR1);
564         sigaction(SIGUSR1, &sa, NULL);
565         
566         sem_post((sem_t *)data);
567
568         while (1) {
569                 wait = ast_sched_wait(misdn_tasks);
570                 if (wait < 0)
571                         wait = 8000;
572                 if (poll(NULL, 0, wait) < 0)
573                         chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
574                 ast_sched_runq(misdn_tasks);
575         }
576         return NULL;
577 }
578
579 static void misdn_tasks_init (void)
580 {
581         sem_t blocker;
582         int i = 5;
583
584         if (sem_init(&blocker, 0, 0)) {
585                 perror("chan_misdn: Failed to initialize semaphore!");
586                 exit(1);
587         }
588
589         chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
590         
591         misdn_tasks = sched_context_create();
592         pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker);
593
594         while (sem_wait(&blocker) && --i);
595         sem_destroy(&blocker);
596 }
597
598 static void misdn_tasks_destroy (void)
599 {
600         if (misdn_tasks) {
601                 chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
602                 if ( pthread_cancel(misdn_tasks_thread) == 0 ) {
603                         cb_log(4, 0, "Joining misdn_tasks thread\n");
604                         pthread_join(misdn_tasks_thread, NULL);
605                 }
606                 sched_context_destroy(misdn_tasks);
607         }
608 }
609
610 static inline void misdn_tasks_wakeup (void)
611 {
612         pthread_kill(misdn_tasks_thread, SIGUSR1);
613 }
614
615 static inline int _misdn_tasks_add_variable (int timeout, ast_sched_cb callback, void *data, int variable)
616 {
617         int task_id;
618
619         if (!misdn_tasks) {
620                 misdn_tasks_init();
621         }
622         task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
623         misdn_tasks_wakeup();
624
625         return task_id;
626 }
627
628 static int misdn_tasks_add (int timeout, ast_sched_cb callback, void *data)
629 {
630         return _misdn_tasks_add_variable(timeout, callback, data, 0);
631 }
632
633 static int misdn_tasks_add_variable (int timeout, ast_sched_cb callback, void *data)
634 {
635         return _misdn_tasks_add_variable(timeout, callback, data, 1);
636 }
637
638 static void misdn_tasks_remove (int task_id)
639 {
640         ast_sched_del(misdn_tasks, task_id);
641 }
642
643 static int misdn_l1_task (void *data)
644 {
645         misdn_lib_isdn_l1watcher(*(int *)data);
646         chan_misdn_log(5, *(int *)data, "L1watcher timeout\n");
647         return 1;
648 }
649
650 static int misdn_overlap_dial_task (void *data)
651 {
652         struct timeval tv_end, tv_now;
653         int diff;
654         struct chan_list *ch = (struct chan_list *)data;
655
656         chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state);
657
658         if (ch->state != MISDN_WAITING4DIGS) {
659                 ch->overlap_dial_task = -1;
660                 return 0;
661         }
662         
663         ast_mutex_lock(&ch->overlap_tv_lock);
664         tv_end = ch->overlap_tv;
665         ast_mutex_unlock(&ch->overlap_tv_lock);
666         
667         tv_end.tv_sec += ch->overlap_dial;
668         tv_now = ast_tvnow();
669
670         diff = ast_tvdiff_ms(tv_end, tv_now);
671
672         if (diff <= 100) {
673                 /* if we are 100ms near the timeout, we are satisfied.. */
674                 stop_indicate(ch);
675                 if (ast_exists_extension(ch->ast, ch->context, ch->bc->dad, 1, ch->bc->oad)) {
676                         ch->state=MISDN_DIALING;
677                         if (pbx_start_chan(ch) < 0) {
678                                 chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
679                                 goto misdn_overlap_dial_task_disconnect;
680                         }
681                 } else {
682 misdn_overlap_dial_task_disconnect:
683                         hanguptone_indicate(ch);
684                         if (ch->bc->nt)
685                                 misdn_lib_send_event(ch->bc, EVENT_RELEASE_COMPLETE );
686                         else
687                                 misdn_lib_send_event(ch->bc, EVENT_RELEASE);
688                 }
689                 ch->overlap_dial_task = -1;
690                 return 0;
691         } else
692                 return diff;
693 }
694
695 static void send_digit_to_chan(struct chan_list *cl, char digit )
696 {
697         static const char* dtmf_tones[] = {
698                 "!941+1336/100,!0/100", /* 0 */
699                 "!697+1209/100,!0/100", /* 1 */
700                 "!697+1336/100,!0/100", /* 2 */
701                 "!697+1477/100,!0/100", /* 3 */
702                 "!770+1209/100,!0/100", /* 4 */
703                 "!770+1336/100,!0/100", /* 5 */
704                 "!770+1477/100,!0/100", /* 6 */
705                 "!852+1209/100,!0/100", /* 7 */
706                 "!852+1336/100,!0/100", /* 8 */
707                 "!852+1477/100,!0/100", /* 9 */
708                 "!697+1633/100,!0/100", /* A */
709                 "!770+1633/100,!0/100", /* B */
710                 "!852+1633/100,!0/100", /* C */
711                 "!941+1633/100,!0/100", /* D */
712                 "!941+1209/100,!0/100", /* * */
713                 "!941+1477/100,!0/100" };       /* # */
714         struct ast_channel *chan=cl->ast; 
715   
716         if (digit >= '0' && digit <='9')
717                 ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
718         else if (digit >= 'A' && digit <= 'D')
719                 ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
720         else if (digit == '*')
721                 ast_playtones_start(chan,0,dtmf_tones[14], 0);
722         else if (digit == '#')
723                 ast_playtones_start(chan,0,dtmf_tones[15], 0);
724         else {
725                 /* not handled */
726                 if (option_debug)
727                         ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
728         }
729 }
730 /*** CLI HANDLING ***/
731 static int misdn_set_debug(int fd, int argc, char *argv[])
732 {
733         if (argc != 4 && argc != 5 && argc != 6 && argc != 7)
734                 return RESULT_SHOWUSAGE; 
735
736         int level = atoi(argv[3]);
737
738         switch (argc) {
739                 case 4: 
740                 case 5: {
741                                         int only = 0;
742                                         if (argc == 5) {
743                                                 if (strncasecmp(argv[4], "only", strlen(argv[4])))
744                                                         return RESULT_SHOWUSAGE;
745                                                 else
746                                                         only = 1;
747                                         }
748                                         int i;
749                                         for (i=0; i<=max_ports; i++) {
750                                                 misdn_debug[i] = level;
751                                                 misdn_debug_only[i] = only;
752                                         }
753                                         ast_cli(fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
754                                 }
755                                 break;
756                 case 6: 
757                 case 7: {
758                                         if (strncasecmp(argv[4], "port", strlen(argv[4])))
759                                                 return RESULT_SHOWUSAGE;
760                                         int port = atoi(argv[5]);
761                                         if (port <= 0 || port > max_ports) {
762                                                 switch (max_ports) {
763                                                         case 0:
764                                                                 ast_cli(fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
765                                                                 break;
766                                                         case 1:
767                                                                 ast_cli(fd, "port number not valid! only port 1 is availble.\n");
768                                                                 break;
769                                                         default:
770                                                                 ast_cli(fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
771                                                         }
772                                                         return 0;
773                                         }
774                                         if (argc == 7) {
775                                                 if (strncasecmp(argv[6], "only", strlen(argv[6])))
776                                                         return RESULT_SHOWUSAGE;
777                                                 else
778                                                         misdn_debug_only[port] = 1;
779                                         } else
780                                                 misdn_debug_only[port] = 0;
781                                         misdn_debug[port] = level;
782                                         ast_cli(fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
783                                 }
784         }
785         return 0;
786 }
787
788 static int misdn_set_crypt_debug(int fd, int argc, char *argv[])
789 {
790         if (argc != 5) return RESULT_SHOWUSAGE; 
791
792         return 0;
793 }
794
795
796 static int misdn_port_block(int fd, int argc, char *argv[])
797 {
798         int port;
799   
800         if (argc != 4)
801                 return RESULT_SHOWUSAGE;
802   
803         port = atoi(argv[3]);
804
805         misdn_lib_port_block(port);
806
807         return 0;
808 }
809
810 static int misdn_port_unblock(int fd, int argc, char *argv[])
811 {
812         int port;
813   
814         if (argc != 4)
815                 return RESULT_SHOWUSAGE;
816   
817         port = atoi(argv[3]);
818
819         misdn_lib_port_unblock(port);
820
821         return 0;
822 }
823
824
825 static int misdn_restart_port (int fd, int argc, char *argv[])
826 {
827         int port;
828   
829         if (argc != 4)
830                 return RESULT_SHOWUSAGE;
831   
832         port = atoi(argv[3]);
833
834         misdn_lib_port_restart(port);
835
836         return 0;
837 }
838
839 static int misdn_restart_pid (int fd, int argc, char *argv[])
840 {
841         int pid;
842   
843         if (argc != 4)
844                 return RESULT_SHOWUSAGE;
845   
846         pid = atoi(argv[3]);
847
848         misdn_lib_pid_restart(pid);
849
850         return 0;
851 }
852
853 static int misdn_port_up (int fd, int argc, char *argv[])
854 {
855         int port;
856         
857         if (argc != 4)
858                 return RESULT_SHOWUSAGE;
859         
860         port = atoi(argv[3]);
861         
862         misdn_lib_get_port_up(port);
863   
864         return 0;
865 }
866
867 static int misdn_port_down (int fd, int argc, char *argv[])
868 {
869         int port;
870         
871         if (argc != 4)
872                 return RESULT_SHOWUSAGE;
873         
874         port = atoi(argv[3]);
875         
876         misdn_lib_get_port_down(port);
877   
878         return 0;
879 }
880
881 static inline void show_config_description (int fd, enum misdn_cfg_elements elem)
882 {
883         char section[BUFFERSIZE];
884         char name[BUFFERSIZE];
885         char desc[BUFFERSIZE];
886         char def[BUFFERSIZE];
887         char tmp[BUFFERSIZE];
888
889         misdn_cfg_get_name(elem, tmp, sizeof(tmp));
890         term_color(name, tmp, COLOR_BRWHITE, 0, sizeof(tmp));
891         misdn_cfg_get_desc(elem, desc, sizeof(desc), def, sizeof(def));
892
893         if (elem < MISDN_CFG_LAST)
894                 term_color(section, "PORTS SECTION", COLOR_YELLOW, 0, sizeof(section));
895         else
896                 term_color(section, "GENERAL SECTION", COLOR_YELLOW, 0, sizeof(section));
897
898         if (*def)
899                 ast_cli(fd, "[%s] %s   (Default: %s)\n\t%s\n", section, name, def, desc);
900         else
901                 ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc);
902 }
903
904 static int misdn_show_config (int fd, int argc, char *argv[])
905 {
906         char buffer[BUFFERSIZE];
907         enum misdn_cfg_elements elem;
908         int linebreak;
909         int onlyport = -1;
910         int ok = 0;
911
912         if (argc >= 4) {
913                 if (!strcmp(argv[3], "description")) {
914                         if (argc == 5) {
915                                 enum misdn_cfg_elements elem = misdn_cfg_get_elem (argv[4]);
916                                 if (elem == MISDN_CFG_FIRST)
917                                         ast_cli(fd, "Unknown element: %s\n", argv[4]);
918                                 else
919                                         show_config_description(fd, elem);
920                                 return 0;
921                         }
922                         return RESULT_SHOWUSAGE;
923                 }
924                 if (!strcmp(argv[3], "descriptions")) {
925                         if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "general"))) {
926                                 for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
927                                         show_config_description(fd, elem);
928                                         ast_cli(fd, "\n");
929                                 }
930                                 ok = 1;
931                         }
932                         if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "ports"))) {
933                                 for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST - 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem) {
934                                         show_config_description(fd, elem);
935                                         ast_cli(fd, "\n");
936                                 }
937                                 ok = 1;
938                         }
939                         return ok ? 0 : RESULT_SHOWUSAGE;
940                 }
941                 if (!sscanf(argv[3], "%d", &onlyport) || onlyport < 0) {
942                         ast_cli(fd, "Unknown option: %s\n", argv[3]);
943                         return RESULT_SHOWUSAGE;
944                 }
945         }
946         
947         if (argc == 3 || onlyport == 0) {
948                 ast_cli(fd,"Misdn General-Config: \n"); 
949                 for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
950                         misdn_cfg_get_config_string( 0, elem, buffer, BUFFERSIZE);
951                         ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
952                 }
953                 ast_cli(fd, "\n");
954         }
955
956         if (onlyport < 0) {
957                 int port = misdn_cfg_get_next_port(0);
958                 for (; port > 0; port = misdn_cfg_get_next_port(port)) {
959                         ast_cli(fd, "\n[PORT %d]\n", port);
960                         for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
961                                 misdn_cfg_get_config_string( port, elem, buffer, BUFFERSIZE);
962                                 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
963                         }       
964                         ast_cli(fd, "\n");
965                 }
966         }
967         
968         if (onlyport > 0) {
969                 if (misdn_cfg_is_port_valid(onlyport)) {
970                         ast_cli(fd, "[PORT %d]\n", onlyport);
971                         for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
972                                 misdn_cfg_get_config_string(onlyport, elem, buffer, BUFFERSIZE);
973                                 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
974                         }       
975                         ast_cli(fd, "\n");
976                 } else {
977                         ast_cli(fd, "Port %d is not active!\n", onlyport);
978                 }
979         }
980         return 0;
981 }
982
983 struct state_struct {
984         enum misdn_chan_state state;
985         char txt[255] ;
986 } ;
987
988 static struct state_struct state_array[] = {
989         {MISDN_NOTHING,"NOTHING"}, /* at beginning */
990         {MISDN_WAITING4DIGS,"WAITING4DIGS"}, /*  when waiting for infos */
991         {MISDN_EXTCANTMATCH,"EXTCANTMATCH"}, /*  when asterisk couldnt match our ext */
992         {MISDN_INCOMING_SETUP,"INCOMING SETUP"}, /*  when pbx_start */
993         {MISDN_DIALING,"DIALING"}, /*  when pbx_start */
994         {MISDN_PROGRESS,"PROGRESS"}, /*  when pbx_start */
995         {MISDN_PROCEEDING,"PROCEEDING"}, /*  when pbx_start */
996         {MISDN_CALLING,"CALLING"}, /*  when misdn_call is called */
997         {MISDN_CALLING_ACKNOWLEDGE,"CALLING_ACKNOWLEDGE"}, /*  when misdn_call is called */
998         {MISDN_ALERTING,"ALERTING"}, /*  when Alerting */
999         {MISDN_BUSY,"BUSY"}, /*  when BUSY */
1000         {MISDN_CONNECTED,"CONNECTED"}, /*  when connected */
1001         {MISDN_PRECONNECTED,"PRECONNECTED"}, /*  when connected */
1002         {MISDN_DISCONNECTED,"DISCONNECTED"}, /*  when connected */
1003         {MISDN_RELEASED,"RELEASED"}, /*  when connected */
1004         {MISDN_BRIDGED,"BRIDGED"}, /*  when bridged */
1005         {MISDN_CLEANING,"CLEANING"}, /* when hangup from * but we were connected before */
1006         {MISDN_HUNGUP_FROM_MISDN,"HUNGUP_FROM_MISDN"}, /* when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
1007         {MISDN_HOLDED,"HOLDED"}, /* when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
1008         {MISDN_HOLD_DISCONNECT,"HOLD_DISCONNECT"}, /* when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
1009         {MISDN_HUNGUP_FROM_AST,"HUNGUP_FROM_AST"} /* when DISCONNECT/RELEASE/REL_COMP came out of */
1010         /* misdn_hangup */
1011 };
1012
1013 static char *misdn_get_ch_state(struct chan_list *p) 
1014 {
1015         int i;
1016         static char state[8];
1017         
1018         if( !p) return NULL;
1019   
1020         for (i=0; i< sizeof(state_array)/sizeof(struct state_struct); i++) {
1021                 if ( state_array[i].state == p->state) return state_array[i].txt; 
1022         }
1023
1024         sprintf(state,"%d",p->state) ;
1025
1026         return state;
1027 }
1028
1029
1030
1031 static void reload_config(void)
1032 {
1033         int i, cfg_debug;
1034
1035         if (!g_config_initialized) {
1036                 ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
1037                 return ;
1038         }
1039         
1040         free_robin_list();
1041         misdn_cfg_reload();
1042         misdn_cfg_update_ptp();
1043         misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
1044         misdn_cfg_get( 0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(int));
1045
1046         for (i = 0;  i <= max_ports; i++) {
1047                 misdn_debug[i] = cfg_debug;
1048                 misdn_debug_only[i] = 0;
1049         }
1050 }
1051
1052 static int misdn_reload (int fd, int argc, char *argv[])
1053 {
1054         ast_cli(fd, "Reloading mISDN Config\n");
1055         reload_config();
1056         return 0;
1057 }
1058
1059 static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel* bc)
1060 {
1061         struct ast_channel *ast=help->ast;
1062         ast_cli(fd,
1063                 "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
1064
1065                 bc->pid, bc->port, bc->channel,
1066                 bc->nt?"NT":"TE",
1067                 help->originator == ORG_AST?"*":"I",
1068                 ast?ast->exten:NULL,
1069                 ast?ast->cid.cid_num:NULL,
1070                 bc->rad,
1071                 ast?ast->context:NULL,
1072                 misdn_get_ch_state(help)
1073                 );
1074         if (misdn_debug[bc->port] > 0)
1075                 ast_cli(fd,
1076                         "  --> astname: %s\n"
1077                         "  --> ch_l3id: %x\n"
1078                         "  --> ch_addr: %x\n"
1079                         "  --> bc_addr: %x\n"
1080                         "  --> bc_l3id: %x\n"
1081                         "  --> display: %s\n"
1082                         "  --> activated: %d\n"
1083                         "  --> state: %s\n"
1084                         "  --> capability: %s\n"
1085 #ifdef MISDN_1_2
1086                         "  --> pipeline: %s\n"
1087 #else
1088                         "  --> echo_cancel: %d\n"
1089 #endif
1090                         "  --> notone : rx %d tx:%d\n"
1091                         "  --> bc_hold: %d\n",
1092                         help->ast->name,
1093                         help->l3id,
1094                         help->addr,
1095                         bc->addr,
1096                         bc?bc->l3_id:-1,
1097                         bc->display,
1098                         
1099                         bc->active,
1100                         bc_state2str(bc->bc_state),
1101                         bearer2str(bc->capability),
1102 #ifdef MISDN_1_2
1103                         bc->pipeline,
1104 #else
1105                         bc->ec_enable,
1106 #endif
1107
1108                         help->norxtone,help->notxtone,
1109                         bc->holded
1110                         );
1111   
1112 }
1113
1114 static int misdn_show_cls (int fd, int argc, char *argv[])
1115 {
1116         struct chan_list *help=cl_te;
1117   
1118         ast_cli(fd,"Chan List: %p\n",cl_te); 
1119   
1120         for (;help; help=help->next) {
1121                 struct misdn_bchannel *bc=help->bc;   
1122                 struct ast_channel *ast=help->ast;
1123                 if (misdn_debug[0] > 2) ast_cli(fd, "Bc:%p Ast:%p\n", bc, ast);
1124                 if (bc) {
1125                         print_bc_info(fd, help, bc);
1126                 } else {
1127                         if (help->state == MISDN_HOLDED) {
1128                                 ast_cli(fd, "ITS A HOLDED BC:\n");
1129                                 ast_cli(fd, " --> l3_id: %x\n"
1130                                                 " --> dad:%s oad:%s\n"
1131                                                 " --> hold_port: %d\n"
1132                                                 " --> hold_channel: %d\n"
1133                                 
1134                                                 ,help->l3id
1135                                                 ,ast->exten
1136                                                 ,ast->cid.cid_num
1137                                                 ,help->hold_info.port
1138                                                 ,help->hold_info.channel
1139                                                 );
1140                         } else {
1141                                 ast_cli(fd,"* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, ast->cid.cid_num);
1142                         }
1143                 }
1144         }
1145   
1146   
1147         return 0;
1148 }
1149
1150 static int misdn_show_cl (int fd, int argc, char *argv[])
1151 {
1152         struct chan_list *help=cl_te;
1153
1154         if (argc != 4)
1155                 return RESULT_SHOWUSAGE;
1156   
1157         for (;help; help=help->next) {
1158                 struct misdn_bchannel *bc=help->bc;   
1159                 struct ast_channel *ast=help->ast;
1160     
1161                 if (bc && ast) {
1162                         if (!strcasecmp(ast->name,argv[3])) {
1163                                 print_bc_info(fd, help, bc);
1164                                 break; 
1165                         }
1166                 } 
1167         }
1168   
1169   
1170         return 0;
1171 }
1172
1173 ast_mutex_t lock;
1174 int MAXTICS=8;
1175
1176 static int misdn_set_tics (int fd, int argc, char *argv[])
1177 {
1178         if (argc != 4)
1179                 return RESULT_SHOWUSAGE;
1180   
1181         MAXTICS=atoi(argv[3]);
1182   
1183         return 0;
1184 }
1185
1186 static int misdn_show_stacks (int fd, int argc, char *argv[])
1187 {
1188         int port;
1189
1190         ast_cli(fd, "BEGIN STACK_LIST:\n");
1191
1192         for (port=misdn_cfg_get_next_port(0); port > 0;
1193              port=misdn_cfg_get_next_port(port)) {
1194                 char buf[128];
1195                 get_show_stack_details(port,buf);
1196                 ast_cli(fd,"  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
1197         }
1198                 
1199         return 0;
1200 }
1201
1202
1203 static int misdn_show_ports_stats (int fd, int argc, char *argv[])
1204 {
1205         int port;
1206
1207         ast_cli(fd, "Port\tin_calls\tout_calls\n");
1208         
1209         for (port=misdn_cfg_get_next_port(0); port > 0;
1210              port=misdn_cfg_get_next_port(port)) {
1211                 ast_cli(fd,"%d\t%d\t\t%d\n",port,misdn_in_calls[port],misdn_out_calls[port]);
1212         }
1213         ast_cli(fd,"\n");
1214         
1215         return 0;
1216
1217 }
1218
1219
1220 static int misdn_show_port (int fd, int argc, char *argv[])
1221 {
1222         int port;
1223         
1224         if (argc != 4)
1225                 return RESULT_SHOWUSAGE;
1226   
1227         port = atoi(argv[3]);
1228   
1229         ast_cli(fd, "BEGIN STACK_LIST:\n");
1230
1231         char buf[128];
1232         get_show_stack_details(port,buf);
1233         ast_cli(fd,"  %s  Debug:%d%s\n",buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
1234
1235         
1236         return 0;
1237 }
1238
1239 static int misdn_send_cd (int fd, int argc, char *argv[])
1240 {
1241         char *channame; 
1242         char *nr; 
1243   
1244         if (argc != 5)
1245                 return RESULT_SHOWUSAGE;
1246   
1247         channame = argv[3];
1248         nr = argv[4];
1249
1250         ast_cli(fd, "Sending Calldeflection (%s) to %s\n",nr, channame);
1251         
1252         {
1253                 struct chan_list *tmp=get_chan_by_ast_name(channame);
1254                 
1255                 if (!tmp) {
1256                         ast_cli(fd, "Sending CD with nr %s to %s failed: Channel does not exist.\n",nr, channame);
1257                         return 0; 
1258                 } else {
1259                         if (strlen(nr) >= 15) {
1260                                 ast_cli(fd, "Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n",nr, channame);
1261                                 return 0; 
1262                         }
1263                         tmp->bc->fac_out.Function = Fac_CD;
1264                         strncpy((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber));
1265                         misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
1266                 }
1267         }
1268   
1269         return 0; 
1270 }
1271
1272 static int misdn_send_digit (int fd, int argc, char *argv[])
1273 {
1274         char *channame; 
1275         char *msg; 
1276   
1277         if (argc != 5)
1278                 return RESULT_SHOWUSAGE;
1279   
1280         channame = argv[3];
1281         msg = argv[4];
1282
1283         ast_cli(fd, "Sending %s to %s\n",msg, channame);
1284   
1285         {
1286                 struct chan_list *tmp=get_chan_by_ast_name(channame);
1287     
1288                 if (!tmp) {
1289                         ast_cli(fd, "Sending %s to %s failed Channel does not exist\n",msg, channame);
1290                         return 0; 
1291                 } else {
1292 #if 1
1293                         int i;
1294                         int msglen = strlen(msg);
1295                         for (i=0; i<msglen; i++) {
1296                                 ast_cli(fd, "Sending: %c\n",msg[i]);
1297                                 send_digit_to_chan(tmp, msg[i]);
1298                                 /* res = ast_safe_sleep(tmp->ast, 250); */
1299                                 usleep(250000);
1300                                 /* res = ast_waitfor(tmp->ast,100); */
1301                         }
1302 #else
1303                         int res;
1304                         res = ast_dtmf_stream(tmp->ast,NULL,msg,250);
1305 #endif
1306                 }
1307         }
1308   
1309         return 0; 
1310 }
1311
1312 static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
1313 {
1314         char *channame; 
1315
1316         if (argc != 4)
1317                 return RESULT_SHOWUSAGE;
1318         
1319         channame = argv[3];
1320   
1321         ast_cli(fd, "Toggling EchoCancel on %s\n", channame);
1322   
1323         {
1324                 struct chan_list *tmp=get_chan_by_ast_name(channame);
1325     
1326                 if (!tmp) {
1327                         ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
1328                         return 0; 
1329                 } else {
1330                         
1331                         tmp->toggle_ec=tmp->toggle_ec?0:1;
1332
1333                         if (tmp->toggle_ec) {
1334 #ifdef MISDN_1_2
1335                                 update_pipeline_config(tmp->bc);
1336 #else
1337                                 update_ec_config(tmp->bc);
1338 #endif
1339                                 manager_ec_enable(tmp->bc);
1340                         } else {
1341                                 manager_ec_disable(tmp->bc);
1342                         }
1343                 }
1344         }
1345   
1346         return 0; 
1347 }
1348
1349 static int misdn_send_display (int fd, int argc, char *argv[])
1350 {
1351         char *channame; 
1352         char *msg; 
1353   
1354         if (argc != 5)
1355                 return RESULT_SHOWUSAGE;
1356   
1357         channame = argv[3];
1358         msg = argv[4];
1359
1360         ast_cli(fd, "Sending %s to %s\n",msg, channame);
1361         {
1362                 struct chan_list *tmp;
1363                 tmp=get_chan_by_ast_name(channame);
1364     
1365                 if (tmp && tmp->bc) {
1366                         ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
1367                         misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
1368                 } else {
1369                         ast_cli(fd,"No such channel %s\n",channame);
1370                         return RESULT_FAILURE;
1371                 }
1372         }
1373
1374         return RESULT_SUCCESS ;
1375 }
1376
1377 static char *complete_ch_helper(const char *line, const char *word, int pos, int state, int rpos)
1378 {
1379         struct ast_channel *c;
1380         int which=0;
1381         char *ret;
1382         if (pos != rpos)
1383                 return NULL;
1384         c = ast_channel_walk_locked(NULL);
1385         while(c) {
1386                 if (!strncasecmp(word, c->name, strlen(word))) {
1387                         if (++which > state)
1388                                 break;
1389                 }
1390                 ast_mutex_unlock(&c->lock);
1391                 c = ast_channel_walk_locked(c);
1392         }
1393         if (c) {
1394                 ret = strdup(c->name);
1395                 ast_mutex_unlock(&c->lock);
1396         } else
1397                 ret = NULL;
1398         return ret;
1399 }
1400
1401 static char *complete_ch(const char *line, const char *word, int pos, int state)
1402 {
1403         return complete_ch_helper(line, word, pos, state, 3);
1404 }
1405
1406 static char *complete_debug_port (const char *line, const char *word, int pos, int state)
1407 {
1408         if (state)
1409                 return NULL;
1410
1411         switch (pos) {
1412         case 4: if (*word == 'p')
1413                                 return strdup("port");
1414                         else if (*word == 'o')
1415                                 return strdup("only");
1416                         break;
1417         case 6: if (*word == 'o')
1418                                 return strdup("only");
1419                         break;
1420         }
1421         return NULL;
1422 }
1423
1424 static char *complete_show_config (const char *line, const char *word, int pos, int state)
1425 {
1426         char buffer[BUFFERSIZE];
1427         enum misdn_cfg_elements elem;
1428         int wordlen = strlen(word);
1429         int which = 0;
1430         int port = 0;
1431
1432         switch (pos) {
1433         case 3: if ((!strncmp(word, "description", wordlen)) && (++which > state))
1434                                 return strdup("description");
1435                         if ((!strncmp(word, "descriptions", wordlen)) && (++which > state))
1436                                 return strdup("descriptions");
1437                         if ((!strncmp(word, "0", wordlen)) && (++which > state))
1438                                 return strdup("0");
1439                         while ((port = misdn_cfg_get_next_port(port)) != -1) {
1440                                 snprintf(buffer, sizeof(buffer), "%d", port);
1441                                 if ((!strncmp(word, buffer, wordlen)) && (++which > state)) {
1442                                         return strdup(buffer);
1443                                 }
1444                         }
1445                         break;
1446         case 4:
1447                         if (strstr(line, "description ")) {
1448                                 for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
1449                                         if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST))
1450                                                 continue;
1451                                         misdn_cfg_get_name(elem, buffer, BUFFERSIZE);
1452                                         if (!wordlen || !strncmp(word, buffer, wordlen)) {
1453                                                 if (++which > state)
1454                                                         return strdup(buffer);
1455                                         }
1456                                 }
1457                         } else if (strstr(line, "descriptions ")) {
1458                                 if ((!wordlen || !strncmp(word, "general", wordlen)) && (++which > state))
1459                                         return strdup("general");
1460                                 if ((!wordlen || !strncmp(word, "ports", wordlen)) && (++which > state))
1461                                         return strdup("ports");
1462                         }
1463                         break;
1464         }
1465         return NULL;
1466 }
1467
1468 static struct ast_cli_entry chan_misdn_clis[] = {
1469         { {"misdn","send","calldeflect", NULL}, misdn_send_cd, "Sends CallDeflection to mISDN Channel",
1470                 "Usage: misdn send calldeflect <channel> \"<nr>\" \n", complete_ch },
1471         { {"misdn","send","digit", NULL}, misdn_send_digit,     "Sends DTMF Digit to mISDN Channel",
1472                 "Usage: misdn send digit <channel> \"<msg>\" \n"
1473                 "       Send <digit> to <channel> as DTMF Tone\n"
1474                 "       when channel is a mISDN channel\n", complete_ch },
1475         { {"misdn","toggle","echocancel", NULL}, misdn_toggle_echocancel, "Toggles EchoCancel on mISDN Channel",
1476                 "Usage: misdn toggle echocancel <channel>\n", complete_ch },
1477         { {"misdn","send","display", NULL}, misdn_send_display, "Sends Text to mISDN Channel", 
1478                 "Usage: misdn send display <channel> \"<msg>\" \n"
1479                 "       Send <msg> to <channel> as Display Message\n"
1480                 "       when channel is a mISDN channel\n", complete_ch },
1481         { {"misdn","show","config", NULL}, misdn_show_config, "Shows internal mISDN config, read from cfg-file",
1482                 "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
1483                 "       Use 0 for <port> to only print the general config.\n", complete_show_config },
1484         { {"misdn","reload", NULL}, misdn_reload, "Reloads internal mISDN config, read from cfg-file",
1485                 "Usage: misdn reload\n" },
1486         { {"misdn","set","tics", NULL}, misdn_set_tics, "", 
1487                 "\n" },
1488         { {"misdn","show","channels", NULL}, misdn_show_cls, "Shows internal mISDN chan_list",
1489                 "Usage: misdn show channels\n" },
1490         { {"misdn","show","channel", NULL}, misdn_show_cl, "Shows internal mISDN chan_list",
1491                 "Usage: misdn show channels\n", complete_ch },
1492         { {"misdn","port","block", NULL}, misdn_port_block, "Blocks the given port",
1493                 "Usage: misdn port block\n" },
1494         { {"misdn","port","unblock", NULL}, misdn_port_unblock, "Unblocks the given port",
1495                 "Usage: misdn port unblock\n" },
1496         { {"misdn","restart","port", NULL}, misdn_restart_port, "Restarts the given port",
1497                 "Usage: misdn restart port\n" },
1498         { {"misdn","restart","pid", NULL}, misdn_restart_pid, "Restarts the given pid",
1499                 "Usage: misdn restart pid\n" },
1500         { {"misdn","port","up", NULL}, misdn_port_up, "Tries to establish L1 on the given port",
1501                 "Usage: misdn port up <port>\n" },
1502         { {"misdn","port","down", NULL}, misdn_port_down, "Tries to deacivate the L1 on the given port",
1503                 "Usage: misdn port down <port>\n" },
1504         { {"misdn","show","stacks", NULL}, misdn_show_stacks, "Shows internal mISDN stack_list",
1505                 "Usage: misdn show stacks\n" },
1506         { {"misdn","show","ports","stats", NULL}, misdn_show_ports_stats, "Shows chan_misdns call statistics per port",
1507                 "Usage: misdn show port stats\n" },
1508         { {"misdn","show","port", NULL}, misdn_show_port, "Shows detailed information for given port",
1509                 "Usage: misdn show port <port>\n" },
1510         { {"misdn","set","debug", NULL}, misdn_set_debug, "Sets Debuglevel of chan_misdn",
1511                 "Usage: misdn set debug <level> [only] | [port <port> [only]]\n", complete_debug_port },
1512         { {"misdn","set","crypt","debug", NULL}, misdn_set_crypt_debug, "Sets CryptDebuglevel of chan_misdn, at the moment, level={1,2}",
1513                 "Usage: misdn set crypt debug <level>\n" }
1514 };
1515
1516 static int update_config (struct chan_list *ch, int orig) 
1517 {
1518         if (!ch) {
1519                 ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
1520                 return -1;
1521         }
1522         
1523         struct ast_channel *ast=ch->ast;
1524         struct misdn_bchannel *bc=ch->bc;
1525         if (! ast || ! bc ) {
1526                 ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
1527                 return -1;
1528         }
1529         
1530         int port=bc->port;
1531         
1532         chan_misdn_log(7,port,"update_config: Getting Config\n");
1533
1534         int hdlc=0;
1535         misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
1536         
1537         if (hdlc) {
1538                 switch (bc->capability) {
1539                 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
1540                 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
1541                         chan_misdn_log(1,bc->port," --> CONF HDLC\n");
1542                         bc->hdlc=1;
1543                         break;
1544                 }
1545                 
1546         }
1547         
1548         
1549         int pres, screen;
1550                         
1551         misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int));
1552         misdn_cfg_get( port, MISDN_CFG_SCREEN, &screen, sizeof(int));
1553         chan_misdn_log(2,port," --> pres: %d screen: %d\n",pres, screen);
1554                 
1555         if ( (pres + screen) < 0 ) {
1556
1557                 chan_misdn_log(2,port," --> pres: %x\n", ast->cid.cid_pres);
1558                         
1559                 switch (ast->cid.cid_pres & 0x60){
1560                                 
1561                 case AST_PRES_RESTRICTED:
1562                         bc->pres=1;
1563                         chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
1564                         break;
1565                                 
1566                                 
1567                 case AST_PRES_UNAVAILABLE:
1568                         bc->pres=2;
1569                         chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
1570                         break;
1571                                 
1572                 default:
1573                         bc->pres=0;
1574                         chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
1575                 }
1576                         
1577                 switch (ast->cid.cid_pres & 0x3){
1578                                 
1579                 case AST_PRES_USER_NUMBER_UNSCREENED:
1580                         bc->screen=0;
1581                         chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
1582                         break;
1583
1584                 case AST_PRES_USER_NUMBER_PASSED_SCREEN:
1585                         bc->screen=1;
1586                         chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
1587                         break;
1588                 case AST_PRES_USER_NUMBER_FAILED_SCREEN:
1589                         bc->screen=2;
1590                         chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
1591                         break;
1592                                 
1593                 case AST_PRES_NETWORK_NUMBER:
1594                         bc->screen=3;
1595                         chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
1596                         break;
1597                                 
1598                 default:
1599                         bc->screen=0;
1600                         chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
1601                 }
1602
1603                         
1604         } else {
1605                 bc->screen=screen;
1606                 bc->pres=pres;
1607         }
1608
1609         return 0;
1610         
1611 }
1612
1613
1614
1615
1616 static void config_jitterbuffer(struct chan_list *ch)
1617 {
1618         struct misdn_bchannel *bc=ch->bc;
1619         int len=ch->jb_len, threshold=ch->jb_upper_threshold;
1620         
1621         chan_misdn_log(5,bc->port, "config_jb: Called\n");
1622         
1623         if ( ! len ) {
1624                 chan_misdn_log(1,bc->port, "config_jb: Deactivating Jitterbuffer\n");
1625                 bc->nojitter=1;
1626         } else {
1627                 
1628                 if (len <=100 || len > 8000) {
1629                         chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
1630                         len=1000;
1631                 }
1632                 
1633                 if ( threshold > len ) {
1634                         chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
1635                 }
1636                 
1637                 if ( ch->jb) {
1638                         cb_log(0,bc->port,"config_jb: We've got a Jitterbuffer Already on this port.\n");
1639                         misdn_jb_destroy(ch->jb);
1640                         ch->jb=NULL;
1641                 }
1642                 
1643                 ch->jb=misdn_jb_init(len, threshold);
1644
1645                 if (!ch->jb ) 
1646                         bc->nojitter=1;
1647         }
1648 }
1649
1650
1651 void debug_numplan(int port, int numplan, char *type)
1652 {
1653         switch (numplan) {
1654         case NUMPLAN_INTERNATIONAL:
1655                 chan_misdn_log(2, port, " --> %s: International\n",type);
1656                 break;
1657         case NUMPLAN_NATIONAL:
1658                 chan_misdn_log(2, port, " --> %s: National\n",type);
1659                 break;
1660         case NUMPLAN_SUBSCRIBER:
1661                 chan_misdn_log(2, port, " --> %s: Subscriber\n",type);
1662                 break;
1663         case NUMPLAN_UNKNOWN:
1664                 chan_misdn_log(2, port, " --> %s: Unknown\n",type);
1665                 break;
1666                 /* Maybe we should cut off the prefix if present ? */
1667         default:
1668                 chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
1669                 break;
1670         }
1671 }
1672
1673
1674
1675
1676 #ifdef MISDN_1_2
1677 static int update_pipeline_config(struct misdn_bchannel *bc)
1678 {
1679         int ec;
1680
1681         misdn_cfg_get(bc->port, MISDN_CFG_PIPELINE, bc->pipeline, sizeof(bc->pipeline));
1682
1683         if (*bc->pipeline)
1684                 return 0;
1685
1686         misdn_cfg_get(bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
1687         if (ec == 1)
1688                 snprintf(bc->pipeline, sizeof(bc->pipeline) - 1, "mg2ec");
1689         else if (ec > 1)
1690                 snprintf(bc->pipeline, sizeof(bc->pipeline) - 1, "mg2ec(deftaps=%d)", ec);
1691
1692         return 0;
1693 }
1694 #else
1695 static int update_ec_config(struct misdn_bchannel *bc)
1696 {
1697         int ec;
1698         int port=bc->port;
1699                 
1700         misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
1701         
1702         if (ec == 1 ) {
1703                 bc->ec_enable=1;
1704         } else if ( ec > 1 ) {
1705                 bc->ec_enable=1;
1706                 bc->ec_deftaps=ec;
1707         }
1708
1709         return 0;
1710 }
1711 #endif
1712
1713
1714 static int read_config(struct chan_list *ch, int orig) {
1715
1716         if (!ch) {
1717                 ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
1718                 return -1;
1719         }
1720
1721         struct ast_channel *ast=ch->ast;
1722         struct misdn_bchannel *bc=ch->bc;
1723         if (! ast || ! bc ) {
1724                 ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
1725                 return -1;
1726         }
1727         
1728         int port=bc->port;
1729         
1730         chan_misdn_log(1,port,"read_config: Getting Config\n");
1731
1732         char lang[BUFFERSIZE+1];
1733         
1734
1735         misdn_cfg_get( port, MISDN_CFG_LANGUAGE, lang, BUFFERSIZE);
1736         ast_string_field_set(ast, language, lang);
1737
1738         char localmusicclass[BUFFERSIZE+1];
1739         
1740         misdn_cfg_get( port, MISDN_CFG_MUSICCLASS, localmusicclass, BUFFERSIZE);
1741         ast_string_field_set(ast, musicclass, localmusicclass);
1742         
1743         
1744         misdn_cfg_get( port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(int));
1745         misdn_cfg_get( port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(int));
1746         
1747         misdn_cfg_get( port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(int));
1748         
1749         misdn_cfg_get( port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(int));
1750
1751         misdn_cfg_get( port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(int));
1752         misdn_cfg_get( port, MISDN_CFG_NTTIMEOUT, &ch->nttimeout, sizeof(int));
1753         
1754         misdn_cfg_get( port, MISDN_CFG_NOAUTORESPOND_ON_SETUP, &ch->noautorespond_on_setup, sizeof(int));
1755         
1756         misdn_cfg_get( port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(int));
1757
1758         misdn_cfg_get( port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, BUFFERSIZE);
1759         
1760         char faxdetect[BUFFERSIZE+1];
1761         misdn_cfg_get( port, MISDN_CFG_FAXDETECT, faxdetect, BUFFERSIZE);
1762         
1763         int hdlc=0;
1764         misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
1765         
1766         if (hdlc) {
1767                 switch (bc->capability) {
1768                 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
1769                 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
1770                         chan_misdn_log(1,bc->port," --> CONF HDLC\n");
1771                         bc->hdlc=1;
1772                         break;
1773                 }
1774                 
1775         }
1776         /*Initialize new Jitterbuffer*/
1777         {
1778                 misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(int));
1779                 misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(int));
1780                 
1781                 config_jitterbuffer(ch);
1782         }
1783         
1784         misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
1785         
1786         ast_copy_string (ast->context,ch->context,sizeof(ast->context));        
1787
1788 #ifdef MISDN_1_2
1789         update_pipeline_config(bc);
1790 #else
1791         update_ec_config(bc);
1792 #endif
1793
1794         {
1795                 int eb3;
1796                 
1797                 misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
1798                 bc->early_bconnect=eb3;
1799         }
1800         
1801         port=bc->port;
1802         
1803         {
1804                 char buf[256];
1805                 ast_group_t pg,cg;
1806                 
1807                 misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
1808                 misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
1809                 
1810                 chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
1811                 ast->pickupgroup=pg;
1812                 ast->callgroup=cg;
1813         }
1814         
1815         if ( orig  == ORG_AST) {
1816                 misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(int));
1817                 
1818                 if (strstr(faxdetect, "outgoing") || strstr(faxdetect, "both")) {
1819                         if (strstr(faxdetect, "nojump"))
1820                                 ch->faxdetect=2;
1821                         else
1822                                 ch->faxdetect=1;
1823                 }
1824
1825                 {
1826                         char callerid[BUFFERSIZE+1];
1827                         misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
1828                         if ( ! ast_strlen_zero(callerid) ) {
1829                                 chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
1830                                 {
1831                                         int l = sizeof(bc->oad);
1832                                         strncpy(bc->oad,callerid, l);
1833                                         bc->oad[l-1] = 0;
1834                                 }
1835
1836                         }
1837
1838                         
1839                         misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(int));
1840                         misdn_cfg_get( port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(int));
1841                         misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
1842                         debug_numplan(port, bc->dnumplan,"TON");
1843                         debug_numplan(port, bc->onumplan,"LTON");
1844                         debug_numplan(port, bc->cpnnumplan,"CTON");
1845                 }
1846
1847                 ch->overlap_dial = 0;
1848         } else { /** ORIGINATOR MISDN **/
1849                 if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
1850                         if (strstr(faxdetect, "nojump"))
1851                                 ch->faxdetect=2;
1852                         else
1853                                 ch->faxdetect=1;
1854                 }
1855         
1856                 misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
1857                 debug_numplan(port, bc->cpnnumplan,"CTON");
1858                 
1859                 char prefix[BUFFERSIZE+1]="";
1860                 switch( bc->onumplan ) {
1861                 case NUMPLAN_INTERNATIONAL:
1862                         misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
1863                         break;
1864                         
1865                 case NUMPLAN_NATIONAL:
1866                         misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
1867                         break;
1868                 default:
1869                         break;
1870                 }
1871                 
1872                 {
1873                         int l = strlen(prefix) + strlen(bc->oad);
1874                         char tmp[l+1];
1875                         strcpy(tmp,prefix);
1876                         strcat(tmp,bc->oad);
1877                         strcpy(bc->oad,tmp);
1878                 }
1879                 
1880                 if (!ast_strlen_zero(bc->dad)) {
1881                         ast_copy_string(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
1882                 }
1883                 
1884                 if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
1885                         ast_copy_string(bc->dad,bc->keypad, sizeof(bc->dad));
1886                 }
1887
1888                 prefix[0] = 0;
1889                 
1890                 switch( bc->dnumplan ) {
1891                 case NUMPLAN_INTERNATIONAL:
1892                         misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
1893                         break;
1894                 case NUMPLAN_NATIONAL:
1895                         misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
1896                         break;
1897                 default:
1898                         break;
1899                 }
1900                 
1901                 {
1902                         int l = strlen(prefix) + strlen(bc->dad);
1903                         char tmp[l+1];
1904                         strcpy(tmp,prefix);
1905                         strcat(tmp,bc->dad);
1906                         strcpy(bc->dad,tmp);
1907                 }
1908                 
1909                 if ( strcmp(bc->dad,ast->exten)) {
1910                         ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
1911                 }
1912                 
1913                 ast_set_callerid(ast, bc->oad, NULL, bc->oad);
1914                 
1915                 if ( !ast_strlen_zero(bc->rad) ) {
1916                         if (ast->cid.cid_rdnis)
1917                                 free(ast->cid.cid_rdnis);
1918                         ast->cid.cid_rdnis = strdup(bc->rad);
1919                 }
1920         
1921                 misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
1922                 ast_mutex_init(&ch->overlap_tv_lock);
1923         } /* ORIG MISDN END */
1924
1925         ch->overlap_dial_task = -1;
1926         
1927         if (ch->faxdetect) {
1928                 misdn_cfg_get( port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
1929                 if (!ch->dsp)
1930                         ch->dsp = ast_dsp_new();
1931                 if (ch->dsp)
1932                         ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT | DSP_FEATURE_FAX_DETECT);
1933                 if (!ch->trans)
1934                         ch->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
1935         }
1936
1937         /* AOCD initialization */
1938         bc->AOCDtype = Fac_None;
1939
1940         return 0;
1941 }
1942
1943
1944 /*****************************/
1945 /*** AST Indications Start ***/
1946 /*****************************/
1947
1948 static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
1949 {
1950         int port=0;
1951         int r;
1952         struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
1953         struct misdn_bchannel *newbc;
1954         char *opts=NULL, *ext,*tokb;
1955         char dest_cp[256];
1956
1957         {
1958                 strncpy(dest_cp,dest,sizeof(dest_cp)-1);
1959                 dest_cp[sizeof(dest_cp)]=0;
1960                 
1961                 ext=strtok_r(dest_cp,"/",&tokb);
1962                 
1963                 if (ext) {
1964                         ext=strtok_r(NULL,"/",&tokb);
1965                         if (ext) {
1966                                 opts=strtok_r(NULL,"/",&tokb);
1967                         } else {
1968                                 chan_misdn_log(0,0,"misdn_call: No Extension given!\n");
1969                                 return -1;
1970                         }
1971                 }
1972         }
1973
1974         if (!ast) {
1975                 ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
1976                 return -1;
1977         }
1978
1979         if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest  ) {
1980                 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1981                 ast->hangupcause=41;
1982                 ast_setstate(ast, AST_STATE_DOWN);
1983                 return -1;
1984         }
1985
1986         if (!ch) {
1987                 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1988                 ast->hangupcause=41;
1989                 ast_setstate(ast, AST_STATE_DOWN);
1990                 return -1;
1991         }
1992         
1993         newbc=ch->bc;
1994         
1995         if (!newbc) {
1996                 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1997                 ast->hangupcause=41;
1998                 ast_setstate(ast, AST_STATE_DOWN);
1999                 return -1;
2000         }
2001         
2002         port=newbc->port;
2003
2004
2005         int exceed;
2006         if ((exceed=add_out_calls(port))) {
2007                 char tmp[16];
2008                 sprintf(tmp,"%d",exceed);
2009                 pbx_builtin_setvar_helper(ast,"MAX_OVERFLOW",tmp);
2010                 return -1;
2011         }
2012         
2013         chan_misdn_log(1, port, "* CALL: %s\n",dest);
2014         
2015         chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
2016         
2017         chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten);
2018         if (ast->exten) {
2019                 int l = sizeof(newbc->dad);
2020                 strncpy(ast->exten,ext,sizeof(ast->exten));
2021
2022                 strncpy(newbc->dad,ext,l);
2023
2024                 newbc->dad[l-1] = 0;
2025         }
2026
2027         if (ast->cid.cid_rdnis)  
2028                 strcpy(newbc->rad, ast->cid.cid_rdnis);
2029         else 
2030                 newbc->rad[0]=0;
2031
2032         chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",ast->cid.cid_num);
2033         if (ast_strlen_zero(newbc->oad) && ast->cid.cid_num ) {
2034
2035                 if (ast->cid.cid_num) {
2036                         int l = sizeof(newbc->oad);
2037                         strncpy(newbc->oad,ast->cid.cid_num, l);
2038                         newbc->oad[l-1] = 0;
2039                 }
2040         }
2041
2042         {
2043                 struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
2044                 if (!ch) { ast_verbose("No chan_list in misdn_call\n"); return -1;}
2045                 
2046                 newbc->capability=ast->transfercapability;
2047                 pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability));
2048                 if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
2049                         chan_misdn_log(2, port, " --> * Call with flag Digital\n");
2050                 }
2051                 
2052
2053                 /* update screening and presentation */ 
2054                 update_config(ch,ORG_AST);
2055                 
2056                 /* fill in some ies from channel vary*/
2057                 import_ch(ast, newbc, ch);
2058                 
2059                 /* Finally The Options Override Everything */
2060                 if (opts)
2061                         misdn_set_opt_exec(ast,opts);
2062                 else
2063                         chan_misdn_log(2,port,"NO OPTS GIVEN\n");
2064
2065                 /*check for bridging*/
2066                 int bridging;
2067                 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
2068                 if (bridging && ch->other_ch) {
2069 #ifdef MISDN_1_2
2070                         chan_misdn_log(1, port, "Disabling EC (aka Pipeline) on both Sides\n");
2071                         *ch->bc->pipeline=0;
2072                         *ch->other_ch->bc->pipeline=0;
2073 #else
2074                         chan_misdn_log(1, port, "Disabling EC on both Sides\n");
2075                         ch->bc->ec_enable=0;
2076                         ch->other_ch->bc->ec_enable=0;
2077 #endif
2078                 }
2079                 
2080                 r=misdn_lib_send_event( newbc, EVENT_SETUP );
2081                 
2082                 /** we should have l3id after sending setup **/
2083                 ch->l3id=newbc->l3_id;
2084         }
2085         
2086         if ( r == -ENOCHAN  ) {
2087                 chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
2088                 chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n",newbc?newbc->pid:-1);
2089                 ast->hangupcause=34;
2090                 ast_setstate(ast, AST_STATE_DOWN);
2091                 return -1;
2092         }
2093         
2094         chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
2095
2096         ast_setstate(ast, AST_STATE_DIALING);
2097         ast->hangupcause=16;
2098         
2099         if (newbc->nt) stop_bc_tones(ch);
2100
2101         ch->state=MISDN_CALLING;
2102         
2103         return 0; 
2104 }
2105
2106
2107 static int misdn_answer(struct ast_channel *ast)
2108 {
2109         struct chan_list *p;
2110
2111         
2112         if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
2113         
2114         chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n");
2115         
2116         if (!p) {
2117                 ast_log(LOG_WARNING, " --> Channel not connected ??\n");
2118                 ast_queue_hangup(ast);
2119         }
2120
2121         if (!p->bc) {
2122                 chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n");
2123
2124                 ast_queue_hangup(ast);
2125         }
2126
2127         {
2128                 const char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
2129                 
2130                 if (tmp_key ) {
2131                         chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
2132                         {
2133                                 int l = sizeof(p->bc->crypt_key);
2134                                 strncpy(p->bc->crypt_key,tmp_key, l);
2135                                 p->bc->crypt_key[l-1] = 0;
2136                         }
2137                 } else {
2138                         chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
2139                 }
2140     
2141         }
2142
2143         {
2144                 const char *nodsp=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
2145                 if (nodsp) {
2146                         chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
2147                         p->bc->nodsp=1;
2148                         p->bc->hdlc=0;
2149                         p->bc->nojitter=1;
2150                 }
2151         }
2152         
2153         p->state = MISDN_CONNECTED;
2154         stop_indicate(p);
2155
2156         if ( ast_strlen_zero(p->bc->cad) ) {
2157                 chan_misdn_log(2,p->bc->port," --> empty cad using dad\n");
2158                 ast_copy_string(p->bc->cad,p->bc->dad,sizeof(p->bc->cad));
2159         }
2160
2161         misdn_lib_send_event( p->bc, EVENT_CONNECT);
2162         start_bc_tones(p);
2163         
2164         return 0;
2165 }
2166
2167 static int misdn_digit_begin(struct ast_channel *chan, char digit)
2168 {
2169         /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
2170         return 0;
2171 }
2172
2173 static int misdn_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
2174 {
2175         struct chan_list *p;
2176         
2177         if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) return -1;
2178
2179         struct misdn_bchannel *bc=p->bc;
2180         chan_misdn_log(1, bc?bc->port:0, "* IND : Digit %c\n",digit);
2181         
2182         if (!bc) {
2183                 ast_log(LOG_WARNING, " --> !! Got Digit Event withut having bchannel Object\n");
2184                 return -1;
2185         }
2186         
2187         switch (p->state ) {
2188                 case MISDN_CALLING:
2189                 {
2190                         
2191                         char buf[8];
2192                         buf[0]=digit;
2193                         buf[1]=0;
2194                         
2195                         int l = sizeof(bc->infos_pending);
2196                         strncat(bc->infos_pending,buf,l);
2197                         bc->infos_pending[l-1] = 0;
2198                 }
2199                 break;
2200                 case MISDN_CALLING_ACKNOWLEDGE:
2201                 {
2202                         bc->info_dad[0]=digit;
2203                         bc->info_dad[1]=0;
2204                         
2205                         {
2206                                 int l = sizeof(bc->dad);
2207                                 strncat(bc->dad,bc->info_dad, l - strlen(bc->dad));
2208                                 bc->dad[l-1] = 0;
2209                 }
2210                         {
2211                                 int l = sizeof(p->ast->exten);
2212                                 strncpy(p->ast->exten, bc->dad, l);
2213                                 p->ast->exten[l-1] = 0;
2214                         }
2215                         
2216                         misdn_lib_send_event( bc, EVENT_INFORMATION);
2217                 }
2218                 break;
2219                 
2220                 default:
2221                         if ( bc->send_dtmf ) {
2222                                 send_digit_to_chan(p,digit);
2223                         }
2224                 break;
2225         }
2226         
2227         return 0;
2228 }
2229
2230
2231 static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
2232 {
2233         struct chan_list *p;
2234         
2235         if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
2236         
2237         chan_misdn_log(1, p->bc?p->bc->port:0, "* IND: Got Fixup State:%s L3id:%x\n", misdn_get_ch_state(p), p->l3id);
2238         
2239         p->ast = ast ;
2240   
2241         return 0;
2242 }
2243
2244
2245
2246 static int misdn_indication(struct ast_channel *ast, int cond, const void *data, size_t datalen)
2247 {
2248         struct chan_list *p;
2249
2250   
2251         if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
2252                 ast_log(LOG_WARNING, "Returnded -1 in misdn_indication\n");
2253                 return -1;
2254         }
2255         
2256         if (!p->bc ) {
2257                 chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten);
2258                 ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
2259                 return -1;
2260         }
2261         
2262         chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] from %s\n",cond, ast->exten);
2263         
2264         switch (cond) {
2265         case AST_CONTROL_BUSY:
2266                 chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n",p->bc?p->bc->pid:-1);
2267                 ast_setstate(ast,AST_STATE_BUSY);
2268
2269                 p->bc->out_cause=17;
2270                 if (p->state != MISDN_CONNECTED) {
2271                         start_bc_tones(p);
2272                         misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
2273                 } else {
2274                         chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name);
2275                 }
2276                 return -1;
2277                 break;
2278         case AST_CONTROL_RING:
2279                 chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
2280                 return -1;
2281                 break;
2282                 
2283         case AST_CONTROL_RINGING:
2284                 chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
2285                 switch (p->state) {
2286                         case MISDN_ALERTING:
2287                                 chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoreing it\n",p->bc?p->bc->pid:-1);
2288                                 break;
2289                         case MISDN_CONNECTED:
2290                                 chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n",p->bc?p->bc->pid:-1);
2291                                 return -1;
2292                                 break;
2293                         default:
2294                                 p->state=MISDN_ALERTING;
2295                                 chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
2296                                 misdn_lib_send_event( p->bc, EVENT_ALERTING);
2297                         
2298                                 if (p->other_ch && p->other_ch->bc) {
2299                                         if (misdn_inband_avail(p->other_ch->bc)) {
2300                                                 chan_misdn_log(2,p->bc->port, " --> other End is mISDN and has inband info available\n");
2301                                                 break;
2302                                         }
2303
2304                                         if (!p->other_ch->bc->nt) {
2305                                                 chan_misdn_log(2,p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
2306                                                 break;
2307                                         }
2308                                 }
2309
2310                                 chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
2311                                 ast_setstate(ast,AST_STATE_RINGING);
2312                         
2313                                 if ( !p->bc->nt && (p->originator==ORG_MISDN) && !p->incoming_early_audio ) 
2314                                         chan_misdn_log(2,p->bc->port, " --> incoming_early_audio off\n");
2315                                 else 
2316                                         return -1;
2317                 }
2318                 break;
2319         case AST_CONTROL_ANSWER:
2320                 chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1);
2321                 start_bc_tones(p);
2322                 break;
2323         case AST_CONTROL_TAKEOFFHOOK:
2324                 chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1);
2325                 return -1;
2326                 break;
2327         case AST_CONTROL_OFFHOOK:
2328                 chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1);
2329                 return -1;
2330                 break; 
2331         case AST_CONTROL_FLASH:
2332                 chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1);
2333                 break;
2334         case AST_CONTROL_PROGRESS:
2335                 chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n",p->bc?p->bc->pid:-1);
2336                 misdn_lib_send_event( p->bc, EVENT_PROGRESS);
2337                 break;
2338         case AST_CONTROL_PROCEEDING:
2339                 chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n",p->bc?p->bc->pid:-1);
2340                 misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
2341                 break;
2342         case AST_CONTROL_CONGESTION:
2343                 chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n",p->bc?p->bc->pid:-1);
2344
2345                 p->bc->out_cause=42;
2346                 start_bc_tones(p);
2347                 misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
2348
2349                 if (p->bc->nt) {
2350                         hanguptone_indicate(p);
2351                 }
2352                 break;
2353         case -1 :
2354                 chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n",p->bc?p->bc->pid:-1);
2355                 
2356                 stop_indicate(p);
2357
2358                 if (p->state == MISDN_CONNECTED) 
2359                         start_bc_tones(p);
2360
2361                 break;
2362
2363         case AST_CONTROL_HOLD:
2364                 chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n",p->bc?p->bc->pid:-1);
2365                 break;
2366         case AST_CONTROL_UNHOLD:
2367                 chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1);
2368                 break;
2369         default:
2370                 chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
2371         }
2372   
2373         return 0;
2374 }
2375
2376 static int misdn_hangup(struct ast_channel *ast)
2377 {
2378         struct chan_list *p;
2379         struct misdn_bchannel *bc=NULL;
2380
2381         if (option_debug)
2382                 ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
2383         
2384         if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
2385         
2386         if (!p) {
2387                 chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
2388                 return 0 ;
2389         }
2390         
2391         bc=p->bc;
2392
2393         MISDN_ASTERISK_TECH_PVT(ast)=NULL;
2394         p->ast=NULL;
2395
2396         if (ast->_state == AST_STATE_RESERVED || 
2397                 p->state == MISDN_NOTHING || 
2398                 p->state == MISDN_HOLDED || 
2399                 p->state == MISDN_HOLD_DISCONNECT ) {
2400
2401                 CLEAN_CH:
2402                 /* between request and call */
2403                 if (option_debug)
2404                         ast_log(LOG_DEBUG, "State Reserved (or nothing) => chanIsAvail\n");
2405                 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
2406                 
2407                 cl_dequeue_chan(&cl_te, p);
2408                 close(p->pipe[0]);
2409                 close(p->pipe[1]);
2410                 free(p);
2411                 
2412                 if (bc)
2413                         misdn_lib_release(bc);
2414                 
2415                 return 0;
2416         }
2417
2418         if (!bc) {
2419                 ast_log(LOG_WARNING,"Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p), p->l3id);
2420                 goto CLEAN_CH;
2421         }
2422
2423
2424         p->need_hangup=0;
2425         p->need_queue_hangup=0;
2426         p->need_busy=0;
2427
2428
2429         if (!p->bc->nt) 
2430                 stop_bc_tones(p);
2431
2432         
2433         {
2434                 const char *varcause=NULL;
2435                 bc->out_cause=ast->hangupcause?ast->hangupcause:16;
2436                 
2437                 if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
2438                      (varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
2439                         int tmpcause=atoi(varcause);
2440                         bc->out_cause=tmpcause?tmpcause:16;
2441                 }
2442     
2443                 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.cid_num, misdn_get_ch_state(p));
2444                 chan_misdn_log(3, bc->port, " --> l3id:%x\n",p->l3id);
2445                 chan_misdn_log(3, bc->port, " --> cause:%d\n",bc->cause);
2446                 chan_misdn_log(2, bc->port, " --> out_cause:%d\n",bc->out_cause);
2447                 chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
2448                 
2449                 switch (p->state) {
2450                 case MISDN_INCOMING_SETUP:
2451                 case MISDN_CALLING:
2452                         p->state=MISDN_CLEANING;
2453                         misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
2454                         break;
2455                 case MISDN_HOLDED:
2456                 case MISDN_DIALING:
2457                         start_bc_tones(p);
2458                         hanguptone_indicate(p);
2459                 
2460                         if (bc->need_disconnect)
2461                                 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2462                         break;
2463
2464                 case MISDN_CALLING_ACKNOWLEDGE:
2465                         start_bc_tones(p);
2466                         hanguptone_indicate(p);
2467                 
2468                         if (bc->need_disconnect)
2469                                 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2470                         break;
2471       
2472                 case MISDN_ALERTING:
2473                 case MISDN_PROGRESS:
2474                 case MISDN_PROCEEDING:
2475                         if (p->originator != ORG_AST) 
2476                                 hanguptone_indicate(p);
2477       
2478                         /*p->state=MISDN_CLEANING;*/
2479                         if (bc->need_disconnect)
2480                                 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2481                         break;
2482                 case MISDN_CONNECTED:
2483                 case MISDN_PRECONNECTED:
2484                         /*  Alerting or Disconect */
2485                         if (p->bc->nt) {
2486                                 start_bc_tones(p);
2487                                 hanguptone_indicate(p);
2488                                 p->bc->progress_indicator=8;
2489                         }
2490                         if (bc->need_disconnect)
2491                                 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2492
2493                         /*p->state=MISDN_CLEANING;*/
2494                         break;
2495                 case MISDN_DISCONNECTED:
2496                         misdn_lib_send_event( bc, EVENT_RELEASE);
2497                         p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
2498                         break;
2499
2500                 case MISDN_RELEASED:
2501                 case MISDN_CLEANING:
2502                         p->state=MISDN_CLEANING;
2503                         break;
2504
2505                 case MISDN_BUSY:
2506                         break;
2507       
2508                 case MISDN_HOLD_DISCONNECT:
2509                         /* need to send release here */
2510                         chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause);
2511                         chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause);
2512                         
2513                         bc->out_cause=-1;
2514                         misdn_lib_send_event(bc,EVENT_RELEASE);
2515                         p->state=MISDN_CLEANING;
2516                         break;
2517                 default:
2518                         if (bc->nt) {
2519                                 bc->out_cause=-1;
2520                                 misdn_lib_send_event(bc, EVENT_RELEASE);
2521                                 p->state=MISDN_CLEANING; 
2522                         } else {
2523                                 if (bc->need_disconnect)
2524                                         misdn_lib_send_event(bc, EVENT_DISCONNECT);
2525                         }
2526                 }
2527
2528                 p->state=MISDN_CLEANING;
2529     
2530         }
2531         
2532
2533         chan_misdn_log(3, bc->port, " --> Channel: %s hanguped new state:%s\n",ast->name,misdn_get_ch_state(p));
2534         
2535         return 0;
2536 }
2537
2538
2539 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
2540 {
2541         struct ast_frame *f,*f2;
2542  
2543         if (tmp->trans) {
2544                 f2 = ast_translate(tmp->trans, frame, 0);
2545                 f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
2546         } else {
2547                 chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
2548                 return NULL;
2549         }
2550
2551  
2552         if (!f || (f->frametype != AST_FRAME_DTMF))
2553                 return frame;
2554  
2555         if (option_debug)
2556                 ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c\n", f->subclass);
2557  
2558         if (tmp->faxdetect && (f->subclass == 'f')) {
2559                 /* Fax tone -- Handle and return NULL */
2560                 if (!tmp->faxhandled) {
2561                         struct ast_channel *ast = tmp->ast;
2562                         tmp->faxhandled++;
2563                         chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast->name);
2564                         tmp->bc->rxgain = 0;
2565                         isdn_lib_update_rxgain(tmp->bc);
2566                         tmp->bc->txgain = 0;
2567                         isdn_lib_update_txgain(tmp->bc);
2568 #ifdef MISDN_1_2
2569                         *tmp->bc->pipeline = 0;
2570 #else
2571                         tmp->bc->ec_enable = 0;
2572 #endif
2573                         isdn_lib_update_ec(tmp->bc);
2574                         isdn_lib_stop_dtmf(tmp->bc);
2575                         switch (tmp->faxdetect) {
2576                         case 1:
2577                                 if (strcmp(ast->exten, "fax")) {
2578                                         char *context;
2579                                         char context_tmp[BUFFERSIZE];
2580                                         misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
2581                                         context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp;
2582                                         if (ast_exists_extension(ast, context, "fax", 1, ast->cid.cid_num)) {
2583                                                 if (option_verbose > 2)
2584                                                         ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
2585                                                 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
2586                                                 pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
2587                                                 if (ast_async_goto(ast, context, "fax", 1))
2588                                                         ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
2589                                         } else
2590                                                 ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten);
2591                                 } else {
2592                                         if (option_debug)
2593                                                 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
2594                                 }
2595                                 break;
2596                         case 2:
2597                                 ast_verbose(VERBOSE_PREFIX_3 "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
2598                                 break;
2599                         }
2600                 } else {
2601                         if (option_debug)
2602                                 ast_log(LOG_DEBUG, "Fax already handled\n");
2603                 }
2604         }
2605         
2606         if (tmp->ast_dsp && (f->subclass != 'f')) {
2607                 chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass);
2608         }
2609
2610         return frame;
2611 }
2612
2613
2614 static struct ast_frame  *misdn_read(struct ast_channel *ast)
2615 {
2616         struct chan_list *tmp;
2617         int len;
2618         
2619         if (!ast) {
2620                 chan_misdn_log(1,0,"misdn_read called without ast\n");
2621                 return NULL;
2622         }
2623         if (!(tmp=MISDN_ASTERISK_TECH_PVT(ast))) {
2624                 chan_misdn_log(1,0,"misdn_read called without ast->pvt\n");
2625                 return NULL;
2626         }
2627
2628         if (!tmp->bc && !(tmp->state==MISDN_HOLDED)) {
2629                 chan_misdn_log(1,0,"misdn_read called without bc\n");
2630                 return NULL;
2631         }
2632
2633         len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
2634
2635         if (len<=0) {
2636                 /* we hangup here, since our pipe is closed */
2637                 chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
2638                 return NULL;
2639         }
2640
2641         tmp->frame.frametype  = AST_FRAME_VOICE;
2642         tmp->frame.subclass = AST_FORMAT_ALAW;
2643         tmp->frame.datalen = len;
2644         tmp->frame.samples = len;
2645         tmp->frame.mallocd = 0;
2646         tmp->frame.offset = 0;
2647         tmp->frame.delivery= ast_tv(0,0) ;
2648         tmp->frame.src = NULL;
2649         tmp->frame.data = tmp->ast_rd_buf;
2650
2651         if (tmp->faxdetect && !tmp->faxhandled) {
2652                 if (tmp->faxdetect_timeout) {
2653                         if (ast_tvzero(tmp->faxdetect_tv)) {
2654                                 tmp->faxdetect_tv = ast_tvnow();
2655                                 chan_misdn_log(2,tmp->bc->port,"faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
2656                                 return process_ast_dsp(tmp, &tmp->frame);
2657                         } else {
2658                                 struct timeval tv_now = ast_tvnow();
2659                                 int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
2660                                 if (diff <= (tmp->faxdetect_timeout * 1000)) {
2661                                         chan_misdn_log(5,tmp->bc->port,"faxdetect: detecting ...\n");
2662                                         return process_ast_dsp(tmp, &tmp->frame);
2663                                 } else {
2664                                         chan_misdn_log(2,tmp->bc->port,"faxdetect: stopping detection (time ran out) ...\n");
2665                                         tmp->faxdetect = 0;
2666                                         return &tmp->frame;
2667                                 }
2668                         }
2669                 } else {
2670                         chan_misdn_log(5,tmp->bc->port,"faxdetect: detecting ... (no timeout)\n");
2671                         return process_ast_dsp(tmp, &tmp->frame);
2672                 }
2673         } else {
2674                 if (tmp->ast_dsp)
2675                         return process_ast_dsp(tmp, &tmp->frame);
2676                 else
2677                         return &tmp->frame;
2678         }
2679 }
2680
2681
2682 static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
2683 {
2684         struct chan_list *ch;
2685         int i  = 0;
2686         
2687         if (!ast || ! (ch=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
2688
2689         if (ch->state == MISDN_HOLDED) {
2690                 chan_misdn_log(7, 0, "misdn_write: Returning because holded\n");
2691                 return 0;
2692         }
2693         
2694         if (!ch->bc ) {
2695                 ast_log(LOG_WARNING, "private but no bc\n");
2696                 return -1;
2697         }
2698         
2699         if (ch->notxtone) {
2700                 chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxone\n");
2701                 return 0;
2702         }
2703
2704
2705         if ( !frame->subclass) {
2706                 chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
2707                 return 0;
2708         }
2709         
2710         if ( !(frame->subclass & prefformat)) {
2711                 
2712                 chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
2713                 return 0;
2714         }
2715         
2716
2717         if ( !frame->samples ) {
2718                 chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
2719                 
2720                 if (!strcmp(frame->src,"ast_prod")) {
2721                         chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
2722
2723                         if (ch->ts) {
2724                                 chan_misdn_log(4,ch->bc->port,"Starting Playtones\n");
2725                                 misdn_lib_tone_generator_start(ch->bc);
2726                         }
2727                         return 0;
2728                 }
2729
2730                 return -1;
2731         }
2732
2733         if ( ! ch->bc->addr ) {
2734                 chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
2735                 return 0;
2736         }
2737         
2738 #ifdef MISDN_DEBUG
2739         {
2740                 int i, max=5>frame->samples?frame->samples:5;
2741                 
2742                 printf("write2mISDN %p %d bytes: ", p, frame->samples);
2743                 
2744                 for (i=0; i<  max ; i++) printf("%2.2x ",((char*) frame->data)[i]);
2745                 printf ("\n");
2746         }
2747 #endif
2748
2749
2750         switch (ch->bc->bc_state) {
2751                 case BCHAN_ACTIVATED:
2752                 case BCHAN_BRIDGED:
2753                         break;
2754                 default:
2755                 if (!ch->dropped_frame_cnt)
2756                         chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n",frame->samples,ch->bc->addr, ast->exten, ast->cid.cid_num,misdn_get_ch_state( ch), ch->bc->bc_state, ch->bc->l3_id);
2757                 
2758                 ch->dropped_frame_cnt++;
2759                 if (ch->dropped_frame_cnt > 100) {
2760                         ch->dropped_frame_cnt=0;
2761                         chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x  dropped > 100 frames!\n",frame->samples,ch->bc->addr);
2762
2763                 }
2764
2765                 return 0;
2766         }
2767
2768         chan_misdn_log(9, ch->bc->port, "Sending :%d bytes 2 MISDN\n",frame->samples);
2769         if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
2770                 /* Buffered Transmit (triggert by read from isdn side)*/
2771                 if (misdn_jb_fill(ch->jb,frame->data,frame->samples) < 0) {
2772                         if (ch->bc->active)
2773                                 cb_log(0,ch->bc->port,"Misdn Jitterbuffer Overflow.\n");
2774                 }
2775                 
2776         } else {
2777                 /*transmit without jitterbuffer*/
2778                 i=misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples);
2779         }
2780
2781         
2782         
2783         return 0;
2784 }
2785
2786
2787
2788
2789 static enum ast_bridge_result  misdn_bridge (struct ast_channel *c0,
2790                                       struct ast_channel *c1, int flags,
2791                                       struct ast_frame **fo,
2792                                       struct ast_channel **rc,
2793                                       int timeoutms)
2794
2795 {
2796         struct chan_list *ch1,*ch2;
2797         struct ast_channel *carr[2], *who;
2798         int to=-1;
2799         struct ast_frame *f;
2800   
2801         ch1=get_chan_by_ast(c0);
2802         ch2=get_chan_by_ast(c1);
2803
2804         carr[0]=c0;
2805         carr[1]=c1;
2806   
2807         if (ch1 && ch2 ) ;
2808         else
2809                 return -1;
2810
2811         int bridging;
2812         misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
2813         if (bridging) {
2814                 /* trying to make a mISDN_dsp conference */
2815                 chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid +1);
2816                 misdn_lib_bridge(ch1->bc,ch2->bc);
2817         }
2818         
2819         if (option_verbose > 2) 
2820                 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
2821
2822         chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
2823  
2824         if (! (flags&AST_BRIDGE_DTMF_CHANNEL_0) )
2825                 ch1->ignore_dtmf=1;
2826
2827         if (! (flags&AST_BRIDGE_DTMF_CHANNEL_1) )
2828                 ch2->ignore_dtmf=1;
2829
2830         while(1) {
2831                 to=-1;
2832                 who = ast_waitfor_n(carr, 2, &to);
2833
2834                 if (!who) {
2835                         ast_log(LOG_NOTICE,"misdn_bridge: empty read, breaking out\n");
2836                         break;
2837                 }
2838                 f = ast_read(who);
2839     
2840                 if (!f || f->frametype == AST_FRAME_CONTROL) {
2841                         /* got hangup .. */
2842
2843                         if (!f) 
2844                                 chan_misdn_log(4,ch1->bc->port,"Read Null Frame\n");
2845                         else
2846                                 chan_misdn_log(4,ch1->bc->port,"Read Frame Controll class:%d\n",f->subclass);
2847                         
2848                         *fo=f;
2849                         *rc=who;
2850       
2851                         break;
2852                 }
2853                 
2854                 if ( f->frametype == AST_FRAME_DTMF ) {
2855                         chan_misdn_log(1,0,"Read DTMF %d from %s\n",f->subclass, who->exten);
2856
2857                         *fo=f;
2858                         *rc=who;
2859                         break;
2860                 }
2861         
2862 #if 0
2863                 if (f->frametype == AST_FRAME_VOICE) {
2864                         chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
2865         
2866                         continue;
2867                 }
2868 #endif
2869
2870                 if (who == c0) {
2871                         ast_write(c1,f);
2872                 }
2873                 else {
2874                         ast_write(c0,f);
2875                 }
2876     
2877         }
2878         
2879         chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
2880         
2881         misdn_lib_split_bridge(ch1->bc,ch2->bc);
2882         
2883         
2884         return AST_BRIDGE_COMPLETE;
2885 }
2886
2887 /** AST INDICATIONS END **/
2888
2889 static int dialtone_indicate(struct chan_list *cl)
2890 {
2891         const struct ind_tone_zone_sound *ts= NULL;
2892         struct ast_channel *ast=cl->ast;
2893
2894         if (!ast) {
2895                 chan_misdn_log(0,cl->bc->port,"No Ast in dialtone_indicate\n");
2896                 return -1;
2897         }
2898
2899         int nd=0;
2900         misdn_cfg_get( cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
2901
2902         if (nd) {
2903                 chan_misdn_log(1,cl->bc->port,"Not sending Dialtone, because config wants it\n");
2904                 return 0;
2905         }
2906         
2907         chan_misdn_log(3,cl->bc->port," --> Dial\n");
2908         ts=ast_get_indication_tone(ast->zone,"dial");
2909         cl->ts=ts;      
2910         
2911         if (ts) {
2912                 cl->notxtone=0;
2913                 cl->norxtone=0;
2914                 /* This prods us in misdn_write */
2915                 ast_playtones_start(ast,0, ts->data, 0);
2916         }
2917
2918         return 0;
2919 }
2920
2921 static int hanguptone_indicate(struct chan_list *cl)
2922 {
2923         misdn_lib_send_tone(cl->bc,TONE_HANGUP);
2924         return 0;
2925 }
2926
2927 static int stop_indicate(struct chan_list *cl)
2928 {
2929         struct ast_channel *ast=cl->ast;
2930
2931         if (!ast) {
2932                 chan_misdn_log(0,cl->bc->port,"No Ast in stop_indicate\n");
2933                 return -1;
2934         }
2935
2936         chan_misdn_log(3,cl->bc->port," --> None\n");
2937         misdn_lib_tone_generator_stop(cl->bc);
2938         ast_playtones_stop(ast);
2939         /*ast_deactivate_generator(ast);*/
2940         
2941         return 0;
2942 }
2943
2944
2945 static int start_bc_tones(struct chan_list* cl)
2946 {
2947         misdn_lib_tone_generator_stop(cl->bc);
2948         cl->notxtone=0;
2949         cl->norxtone=0;
2950         return 0;
2951 }
2952
2953 static int stop_bc_tones(struct chan_list *cl)
2954 {
2955         if (!cl) return -1;
2956
2957         cl->notxtone=1;
2958         cl->norxtone=1;
2959         
2960         return 0;
2961 }
2962
2963
2964 static struct chan_list *init_chan_list(int orig)
2965 {
2966         struct chan_list *cl=malloc(sizeof(struct chan_list));
2967         
2968         if (!cl) {
2969                 chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
2970                 return NULL;
2971         }
2972         
2973         memset(cl,0,sizeof(struct chan_list));
2974
2975         cl->originator=orig;
2976         cl->need_queue_hangup=1;
2977         cl->need_hangup=1;
2978         cl->need_busy=1;
2979         cl->overlap_dial_task=-1;
2980         
2981         return cl;
2982         
2983 }
2984
2985 static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
2986
2987 {
2988         struct ast_channel *tmp = NULL;
2989         char group[BUFFERSIZE+1]="";
2990         char buf[128];
2991         char buf2[128], *ext=NULL, *port_str;
2992         char *tokb=NULL, *p=NULL;
2993         int channel=0, port=0;
2994         struct misdn_bchannel *newbc = NULL;
2995         int dec=0;
2996         
2997         struct chan_list *cl=init_chan_list(ORG_AST);
2998         
2999         sprintf(buf,"%s/%s",misdn_type,(char*)data);
3000         ast_copy_string(buf2,data, 128);
3001         
3002         port_str=strtok_r(buf2,"/", &tokb);
3003
3004         ext=strtok_r(NULL,"/", &tokb);
3005
3006         if (port_str) {
3007                 if (port_str[0]=='g' && port_str[1]==':' ) {
3008                         /* We make a group call lets checkout which ports are in my group */
3009                         port_str += 2;
3010                         strncpy(group, port_str, BUFFERSIZE);
3011                         group[127] = 0;
3012                         chan_misdn_log(2, 0, " --> Group Call group: %s\n",group);
3013                 } 
3014                 else if ((p = strchr(port_str, ':'))) {
3015                         /* we have a preselected channel */
3016                         *p = 0;
3017                         channel = atoi(++p);
3018                         port = atoi(port_str);
3019                         chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
3020                 }
3021                 else {
3022                         port = atoi(port_str);
3023                 }
3024         } else {
3025                 ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extension.conf\n",ext);
3026                 return NULL;
3027         }
3028
3029         if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
3030                 chan_misdn_log(4, port, " --> STARTING STANDARDDEC...\n");
3031                 dec=1;
3032         }
3033
3034         if (!ast_strlen_zero(group)) {
3035         
3036                 char cfg_group[BUFFERSIZE+1];
3037                 struct robin_list *rr = NULL;
3038
3039                 if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
3040                         chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
3041                         rr = get_robin_position(group);
3042                 }
3043                 
3044                         
3045                 if (rr) {
3046                         int robin_channel = rr->channel;
3047                         int port_start;
3048                         int next_chan = 1;
3049
3050                         do {
3051                                 port_start = 0;
3052                                 for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start;
3053                                          port = misdn_cfg_get_next_port_spin(port)) {
3054
3055                                         if (!port_start)
3056                                                 port_start = port;
3057
3058                                         if (port >= port_start)
3059                                                 next_chan = 1;
3060                                         
3061                                         if (port <= port_start && next_chan) {
3062                                                 int maxbchans=misdn_lib_get_maxchans(port);
3063                                                 if (++robin_channel >= maxbchans) {
3064                                                         robin_channel = 1;
3065                                                 }
3066                                                 next_chan = 0;
3067                                         }
3068
3069                                         misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
3070                                         
3071                                         if (!strcasecmp(cfg_group, group)) {
3072                                                 int port_up;
3073                                                 int check;
3074                                                 misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
3075                                                 port_up = misdn_lib_port_up(port, check);
3076
3077                                                 if (check && !port_up) 
3078                                                         chan_misdn_log(1,port,"L1 is not Up on this Port\n");
3079                                                 
3080                                                 if (check && port_up<0) {
3081                                                         ast_log(LOG_WARNING,"This port (%d) is blocked\n", port);
3082                                                 }
3083                                                 
3084                                                 
3085                                                 if ( port_up>0 )        {
3086                                                         newbc = misdn_lib_get_free_bc(port, robin_channel,0, 0);
3087                                                         if (newbc) {
3088                                                                 chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
3089                                                                 if (port_up)
3090                                                                         chan_misdn_log(4, port, "portup:%d\n",  port_up);
3091                                                                 rr->port = newbc->port;
3092                                                                 rr->channel = newbc->channel;
3093                                                                 break;
3094                                                         }
3095                                                 }
3096                                         }
3097                                 }
3098                         } while (!newbc && robin_channel != rr->channel);
3099                         
3100                 } else {                
3101                         for (port=misdn_cfg_get_next_port(0); port > 0;
3102                                  port=misdn_cfg_get_next_port(port)) {
3103                                 
3104                                 misdn_cfg_get( port, MISDN_CFG_GROUPNA