chan_lcr has now a lcr_request function which should work basically, we only need...
[lcr.git] / chan_lcr.c
1 /*****************************************************************************\
2 **                                                                           **
3 ** Linux Call Router                                                         **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** Asterisk socket client                                                    **
9 **                                                                           **
10 \*****************************************************************************/
11
12 /*
13
14 How does it work:
15
16 To connect, open a socket and send a MESSAGE_HELLO to admin socket with
17 the application name. This name is unique an can be used for routing calls.
18
19 To make a call, send a MESSAGE_NEWREF and a new reference is received.
20 When receiving a call, a new reference is received.
21 The reference is received with MESSAGE_NEWREF.
22
23 Make a MESSAGE_SETUP or receive a MESSAGE_SETUP with the reference.
24
25 To release call and reference, send or receive MESSAGE_RELEASE.
26 From that point on, the ref is not valid, so no other message may be sent
27 with that reference.
28
29 */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <stdarg.h>
35 #include <errno.h>
36 #include <sys/types.h>
37 #include <time.h>
38 #include <unistd.h>
39 #include <fcntl.h>
40 #include <sys/ioctl.h>
41 #include <sys/socket.h>
42 #include <sys/un.h>
43
44 #include <pthread.h>
45 #include <semaphore.h>
46
47 #include "extension.h"
48 #include "message.h"
49 #include "lcrsocket.h"
50 #include "cause.h"
51 #include "bchannel.h"
52 #include "chan_lcr.h"
53
54
55
56 #include <asterisk/module.h>
57 #include <asterisk/channel.h>
58 #include <asterisk/config.h>
59 #include <asterisk/logger.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/file.h>
70 #include <asterisk/callerid.h>
71 #include <asterisk/indications.h>
72 #include <asterisk/app.h>
73 #include <asterisk/features.h>
74 #include <asterisk/sched.h>
75
76 int lcr_debug=1;
77 int mISDN_created=1;
78
79 char lcr_type[]="LCR";
80
81
82 int lcr_sock = -1;
83
84 struct admin_list {
85         struct admin_list *next;
86         struct admin_msg msg;
87 } *admin_first = NULL;
88
89 /*
90  * channel and call instances
91  */
92 struct chan_call *call_first;
93
94 struct chan_call *find_call_ref(unsigned long ref)
95 {
96         struct chan_call *call = call_first;
97
98         while(call)
99         {
100                 if (call->ref == ref)
101                         break;
102                 call = call->next;
103         }
104         return(call);
105 }
106
107 struct chan_call *find_call_handle(unsigned long handle)
108 {
109         struct chan_call *call = call_first;
110
111         while(call)
112         {
113                 if (call->bchannel_handle == handle)
114                         break;
115                 call = call->next;
116         }
117         return(call);
118 }
119
120 struct chan_call *alloc_call(void)
121 {
122         struct chan_call **callp = &call_first;
123
124         while(*callp)
125                 callp = &((*callp)->next);
126
127         *callp = (struct chan_call *)malloc(sizeof(struct chan_call));
128         return(*callp);
129 }
130
131 void free_call(struct chan_call *call)
132 {
133         struct chan_call **temp = &call_first;
134
135         while(*temp)
136         {
137                 if (*temp == call)
138                 {
139                         *temp = (*temp)->next;
140                         free(call);
141                         return;
142                 }
143                 temp = &((*temp)->next);
144         }
145 }
146
147 unsigned short new_brige_id(void)
148 {
149         struct chan_call *call;
150         unsigned short id = 1;
151
152         /* search for lowest bridge id that is not in use and not 0 */
153         while(id)
154         {
155                 call = call_first;
156                 while(call)
157                 {
158                         if (call->bridge_id == id)
159                                 break;
160                         call = call->next;
161                 }
162                 if (!call)
163                         break;
164                 id++;
165         }
166         return(id);
167 }
168
169
170 /*
171  * receive bchannel data
172  */
173 void rx_data(struct bchannel *bchannel, unsigned char *data, int len)
174 {
175 }
176
177 void rx_dtmf(struct bchannel *bchannel, char tone)
178 {
179 }
180
181 /*
182  * enque message to LCR
183  */
184 int send_message(int message_type, unsigned long ref, union parameter *param)
185 {
186         struct admin_list *admin, **adminp;
187
188         adminp = &admin_first;
189         while(*adminp)
190                 adminp = &((*adminp)->next);
191         admin = (struct admin_list *)malloc(sizeof(struct admin_list));
192         *adminp = admin;
193
194         admin->msg.type = message_type;
195         admin->msg.ref = ref;
196         memcpy(&admin->msg.param, param, sizeof(union parameter));
197
198         return(0);
199 }
200
201 /*
202  * message received from LCR
203  */
204 int receive_message(int message_type, unsigned long ref, union parameter *param)
205 {
206         union parameter newparam;
207         struct bchannel *bchannel;
208         struct chan_call *call;
209
210         memset(&newparam, 0, sizeof(union parameter));
211
212         /* handle bchannel message*/
213         if (message_type == MESSAGE_BCHANNEL)
214         {
215                 switch(param->bchannel.type)
216                 {
217                         case BCHANNEL_ASSIGN:
218                         if ((bchannel = find_bchannel_handle(param->bchannel.handle)))
219                         {
220                                 fprintf(stderr, "error: bchannel handle %x already assigned.\n", (int)param->bchannel.handle);
221                                 return(-1);
222                         }
223                         /* create bchannel */
224                         bchannel = alloc_bchannel(param->bchannel.handle);
225                         if (!bchannel)
226                         {
227                                 fprintf(stderr, "error: alloc bchannel handle %x failed.\n", (int)param->bchannel.handle);
228                                 return(-1);
229                         }
230
231                         /* configure channel */
232                         bchannel->b_tx_gain = param->bchannel.tx_gain;
233                         bchannel->b_rx_gain = param->bchannel.rx_gain;
234                         strncpy(bchannel->b_pipeline, param->bchannel.pipeline, sizeof(bchannel->b_pipeline)-1);
235                         if (param->bchannel.crypt_len)
236                         {
237                                 bchannel->b_crypt_len = param->bchannel.crypt_len;
238                                 bchannel->b_crypt_type = param->bchannel.crypt_type;
239                                 memcpy(bchannel->b_crypt_key, param->bchannel.crypt, param->bchannel.crypt_len);
240                         }
241                         bchannel->b_txdata = 0;
242                         bchannel->b_dtmf = 1;
243                         bchannel->b_tx_dejitter = 1;
244
245                         /* in case, ref is not set, this bchannel instance must
246                          * be created until it is removed again by LCR */
247                         /* link to call */
248                         if ((call = find_call_ref(ref)))
249                         {
250                                 bchannel->ref = ref;
251                                 call->bchannel_handle = param->bchannel.handle;
252 #warning hier muesen alle stati gesetzt werden falls sie vor dem b-kanal verfügbar waren
253                                 bchannel_join(bchannel, call->bridge_id);
254                         }
255                         if (bchannel_create(bchannel))
256                                 bchannel_activate(bchannel, 1);
257
258                         /* acknowledge */
259                         newparam.bchannel.type = BCHANNEL_ASSIGN_ACK;
260                         newparam.bchannel.handle = param->bchannel.handle;
261                         send_message(MESSAGE_BCHANNEL, 0, &newparam);
262                         break;
263
264                         case BCHANNEL_REMOVE:
265                         if (!(bchannel = find_bchannel_handle(param->bchannel.handle)))
266                         {
267                                 #warning alle fprintf nach ast_log
268                                 fprintf(stderr, "error: bchannel handle %x not assigned.\n", (int)param->bchannel.handle);
269                                 return(-1);
270                         }
271                         /* unlink from call */
272                         if ((call = find_call_ref(bchannel->ref)))
273                         {
274                                 call->bchannel_handle = 0;
275                         }
276                         /* destroy and remove bchannel */
277                         free_bchannel(bchannel);
278
279                         /* acknowledge */
280                         newparam.bchannel.type = BCHANNEL_REMOVE_ACK;
281                         newparam.bchannel.handle = param->bchannel.handle;
282                         send_message(MESSAGE_BCHANNEL, 0, &newparam);
283                         
284                         break;
285
286                         default:
287                         fprintf(stderr, "received unknown bchannel message %d\n", param->bchannel.type);
288                 }
289                 return(0);
290         }
291
292         /* handle new ref */
293         if (message_type == MESSAGE_NEWREF)
294         {
295                 if (param->direction)
296                 {
297                         /* new ref from lcr */
298                         if (!ref || find_call_ref(ref))
299                         {
300                                 fprintf(stderr, "illegal new ref %d received\n", ref);
301                                 return(-1);
302                         }
303                         call = alloc_call();
304                         call->ref = ref;
305                 } else
306                 {
307                         /* new ref, as requested from this remote application */
308                         call = find_call_ref(0);
309                         if (!call)
310                         {
311                                 /* send release, if ref does not exist */
312                                 newparam.disconnectinfo.cause = CAUSE_NORMAL;
313                                 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
314                                 send_message(MESSAGE_RELEASE, ref, &newparam);
315                                 return(0);
316                         }
317                         call->ref = ref;
318 #warning process call (send setup, if pending)
319                 }
320                 return(0);
321         }
322
323         /* check ref */
324         if (!ref)
325         {
326                 fprintf(stderr, "received message %d without ref\n", message_type);
327                 return(-1);
328         }
329         call = find_call_ref(ref);
330         if (!call)
331         {
332                 /* ignore ref that is not used (anymore) */
333                 return(0);
334         }
335
336         /* handle messages */
337         switch(message_type)
338         {
339                 case MESSAGE_SETUP:
340 #warning todo
341                 break;
342
343                 case MESSAGE_OVERLAP:
344 #warning todo
345                 break;
346
347                 case MESSAGE_PROCEEDING:
348 #warning todo
349                 break;
350
351                 case MESSAGE_ALERTING:
352 #warning todo
353                 break;
354
355                 case MESSAGE_CONNECT:
356 #warning todo
357                 break;
358
359                 case MESSAGE_DISCONNECT:
360 #warning todo
361                 break;
362
363                 case MESSAGE_RELEASE:
364 #warning todo
365                 free_call(call);
366                 return(0);
367
368                 case MESSAGE_INFORMATION:
369 #warning todo
370                 break;
371
372                 case MESSAGE_FACILITY:
373 #warning todo
374                 break;
375
376                 case MESSAGE_PATTERN:
377 #warning todo
378                 break;
379
380                 case MESSAGE_NOPATTERN:
381 #warning todo
382                 break;
383
384                 case MESSAGE_AUDIOPATH:
385 #warning todo
386                 break;
387
388                 default:
389 #warning unhandled
390         }
391         return(0);
392 }
393
394
395 /* asterisk handler
396  * warning! not thread safe
397  * returns -1 for socket error, 0 for no work, 1 for work
398  */
399 int handle_socket(void)
400 {
401         int work = 0;
402         int len;
403         struct admin_message msg;
404         struct admin_list *admin;
405
406         int sock;
407
408         #warning SOCKET FEHLT!
409         /* read from socket */
410         len = read(sock, &msg, sizeof(msg));
411         if (len == 0)
412         {
413                 printf("Socket closed\n");
414                 return(-1); // socket closed
415         }
416         if (len > 0)
417         {
418                 if (len != sizeof(msg))
419                 {
420                         fprintf(stderr, "Socket short read (%d)\n", len);
421                         return(-1); // socket error
422                 }
423                 if (msg.message != ADMIN_MESSAGE)
424                 {
425                         fprintf(stderr, "Socket received illegal message %d\n", msg.message);
426                         return(-1); // socket error
427                 }
428                 receive_message(msg.u.msg.type, msg.u.msg.ref, &msg.u.msg.param);
429                 printf("message received %d\n", msg.u.msg.type);
430                 work = 1;
431         } else
432         {
433                 if (errno != EWOULDBLOCK)
434                 {
435                         fprintf(stderr, "Socket error %d\n", errno);
436                         return(-1);
437                 }
438         }
439
440         /* write to socket */
441         if (!admin_first)
442                 return(work);
443         admin = admin_first;
444         len = write(sock, &admin->msg, sizeof(msg));
445         if (len == 0)
446         {
447                 printf("Socket closed\n");
448                 return(-1); // socket closed
449         }
450         if (len > 0)
451         {
452                 if (len != sizeof(msg))
453                 {
454                         fprintf(stderr, "Socket short write (%d)\n", len);
455                         return(-1); // socket error
456                 }
457                 /* free head */
458                 admin_first = admin->next;
459                 free(admin);
460
461                 work = 1;
462         } else
463         {
464                 if (errno != EWOULDBLOCK)
465                 {
466                         fprintf(stderr, "Socket error %d\n", errno);
467                         return(-1);
468                 }
469         }
470
471         return(work);
472 }
473
474 /*
475  * open and close socket
476  */
477 int open_socket(void)
478 {
479         int ret;
480         int sock;
481         char *socket_name = SOCKET_NAME;
482         int conn;
483         struct sockaddr_un sock_address;
484         unsigned long on = 1;
485         union parameter param;
486
487         /* open socket */
488         if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
489         {
490                 ast_log(LOG_ERROR, "Failed to create socket.\n");
491                 return(sock);
492         }
493
494         /* set socket address and name */
495         memset(&sock_address, 0, sizeof(sock_address));
496         sock_address.sun_family = PF_UNIX;
497         strcpy(sock_address.sun_path, socket_name);
498
499         /* connect socket */
500         if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
501         {
502                 close(sock);
503                 ast_log(LOG_ERROR, "Failed to connect to socket \"%s\". Is LCR running?\n", sock_address.sun_path);
504                 return(conn);
505         }
506
507         /* set non-blocking io */
508         if ((ret = ioctl(sock, FIONBIO, (unsigned char *)(&on))) < 0)
509         {
510                 close(sock);
511                 ast_log(LOG_ERROR, "Failed to set socket into non-blocking IO.\n");
512                 return(ret);
513         }
514
515         /* enque hello message */
516         memset(&param, 0, sizeof(param));
517         strcpy(param.hello.application, "asterisk");
518         send_message(MESSAGE_HELLO, 0, &param);
519
520         return(sock);
521 }
522
523 void close_socket(int sock)
524 {
525         /* close socket */
526         if (socket >= 0)        
527                 close(sock);
528 }
529
530
531 void lcr_thread(void)
532 {
533         int work;
534
535         while(42)
536         {
537                 work = 0;
538
539                 /* handle socket */
540                 int ret = handle_socket();
541                 if (ret < 0)
542                         break;
543                 if (ret)
544                         work = 1;
545
546                 /* handle mISDN */
547                 ret = bchannel_handle();
548                 if (ret)
549                         work = 1;
550                 
551                 if (!work)
552                         usleep(30000);
553         }
554 }
555
556
557 static struct ast_channel *lcr_ast_new(struct chan_call *call, char *exten, char *callerid, int ref);
558
559 static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause)
560 {
561         struct ast_channel *ast=NULL;
562
563         char buf[128];
564         char *port_str, *ext, *p;
565         int port;
566
567         ast_copy_string(buf, data, sizeof(buf)-1);
568         p=buf;
569         port_str=strsep(&p, "/");
570         ext=strsep(&p, "/");
571         ast_verbose("portstr:%s ext:%s\n",port_str, ext);
572
573         sprintf(buf,"%s/%s",lcr_type,(char*)data);
574
575         struct chan_call *call=alloc_call();
576
577         if (call) {
578 #warning hier muss jetzt wohl eine Ref angefordert werden!
579                 ast=lcr_ast_new(call, ext, NULL, 0 );
580
581                 if (ast) {
582                         call->ast=ast;
583                 } else {
584                         ast_log(LOG_WARNING, "Could not create new Asterisk Channel\n");
585                         free_call(call);
586                 }
587         } else {
588                 ast_log(LOG_WARNING, "Could not create new Lcr Call Handle\n");
589         }
590
591         return ast;
592 }
593
594
595 /* call from asterisk (new instance) */
596 static int lcr_call(struct ast_channel *ast, char *dest, int timeout)
597 {
598         struct chan_call *call=ast->tech_pvt;
599
600         if (!call) return -1;
601
602         char buf[128];
603         char *port_str, *dad, *p;
604
605         ast_copy_string(buf, dest, sizeof(buf)-1);
606         p=buf;
607         port_str=strsep(&p, "/");
608         dad=strsep(&p, "/");
609
610         if (lcr_debug)
611                 ast_verbose("Call: ext:%s dest:(%s) -> dad(%s) \n", ast->exten,dest, dad);
612
613 #warning hier müssen wi eine der geholten REFs nehmen und ein SETUP schicken, die INFOS zum SETUP stehen im Ast pointer drin, bzw. werden hier übergeben.
614         
615         return 0; 
616 }
617
618 static int lcr_answer(struct ast_channel *c)
619 {
620         struct chan_call *call=c->tech_pvt;
621         return 0;
622 }
623
624 static int lcr_hangup(struct ast_channel *c)
625 {
626         struct chan_call *call=c->tech_pvt;
627         c->tech_pvt=NULL;
628 }
629
630
631 static int lcr_write(struct ast_channel *c, struct ast_frame *f)
632 {
633         struct chan_call *callm= c->tech_pvt;
634 }
635
636
637 static struct ast_frame *lcr_read(struct ast_channel *c)
638 {
639         struct chan_call *call = c->tech_pvt;
640 }
641
642 static int lcr_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen)
643 {
644         int res = -1;
645
646         switch (cond) {
647                 case AST_CONTROL_BUSY:
648                 case AST_CONTROL_CONGESTION:
649                 case AST_CONTROL_RINGING:
650                         return -1;
651                 case -1:
652                         return 0;
653
654                 case AST_CONTROL_VIDUPDATE:
655                         res = -1;
656                         break;
657                 case AST_CONTROL_HOLD:
658                         ast_verbose(" << Console Has Been Placed on Hold >> \n");
659                         //ast_moh_start(c, data, g->mohinterpret);
660                         break;
661                 case AST_CONTROL_UNHOLD:
662                         ast_verbose(" << Console Has Been Retrieved from Hold >> \n");
663                         //ast_moh_stop(c);
664                         break;
665
666                 default:
667                         ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name);
668                         return -1;
669         }
670
671         return 0;
672 }
673
674 static struct ast_channel_tech lcr_tech = {
675         .type=lcr_type,
676         .description="Channel driver for connecting to Linux-Call-Router",
677         .capabilities=AST_FORMAT_ALAW,
678         .requester=lcr_request,
679 //      .send_digit=lcr_digit,
680         .call=lcr_call,
681 //      .bridge=lcr_bridge, 
682         .hangup=lcr_hangup,
683         .answer=lcr_answer,
684         .read=lcr_read,
685         .write=lcr_write,
686         .indicate=lcr_indicate,
687 //      .fixup=lcr_fixup,
688 //      .send_text=lcr_send_text,
689         .properties=0
690 };
691
692 #warning das muss mal aus der config datei gelesen werden:
693 char lcr_context[]="from-lcr";
694
695 static struct ast_channel *lcr_ast_new(struct chan_call *call, char *exten, char *callerid, int ref)
696 {
697         struct ast_channel *tmp;
698         char *cid_name = 0, *cid_num = 0;
699
700
701         if (callerid)
702                 ast_callerid_parse(callerid, &cid_name, &cid_num);
703
704         tmp = ast_channel_alloc(1, AST_STATE_RESERVED, cid_num, cid_name, "", exten, "", 0, "%s/%d", lcr_type,  ref);
705
706         if (tmp) {
707                 tmp->tech = &lcr_tech;
708                 tmp->writeformat = AST_FORMAT_ALAW;
709                 tmp->readformat = AST_FORMAT_ALAW;
710
711                 ast_copy_string(tmp->context, lcr_context, AST_MAX_CONTEXT);
712
713         }
714
715         return tmp;
716 }
717
718
719
720 /*
721  * cli
722  */
723 static int lcr_show_lcr (int fd, int argc, char *argv[])
724 {
725 }
726
727 static int lcr_show_calls (int fd, int argc, char *argv[])
728 {
729 }
730
731 static int lcr_reload_routing (int fd, int argc, char *argv[])
732 {
733 }
734
735 static int lcr_reload_interfaces (int fd, int argc, char *argv[])
736 {
737 }
738
739 static int lcr_port_block (int fd, int argc, char *argv[])
740 {
741 }
742
743 static int lcr_port_unblock (int fd, int argc, char *argv[])
744 {
745 }
746
747 static int lcr_port_unload (int fd, int argc, char *argv[])
748 {
749 }
750
751 static struct ast_cli_entry cli_show_lcr =
752 { {"lcr", "show", "lcr", NULL},
753  lcr_show_lcr,
754  "Shows current states of LCR core",
755  "Usage: lcr show lcr\n",
756 };
757
758 static struct ast_cli_entry cli_show_calls =
759 { {"lcr", "show", "calls", NULL},
760  lcr_show_calls,
761  "Shows current calls made by LCR and Asterisk",
762  "Usage: lcr show calls\n",
763 };
764
765 static struct ast_cli_entry cli_reload_routing =
766 { {"lcr", "reload", "routing", NULL},
767  lcr_reload_routing,
768  "Reloads routing conf of LCR, current uncomplete calls will be disconnected",
769  "Usage: lcr reload routing\n",
770 };
771
772 static struct ast_cli_entry cli_reload_interfaces =
773 { {"lcr", "reload", "interfaces", NULL},
774  lcr_reload_interfaces,
775  "Reloads interfaces conf of LCR",
776  "Usage: lcr reload interfaces\n",
777 };
778
779 static struct ast_cli_entry cli_port_block =
780 { {"lcr", "port", "block", NULL},
781  lcr_port_block,
782  "Blocks LCR port for further calls",
783  "Usage: lcr port block \"<port>\"\n",
784 };
785
786 static struct ast_cli_entry cli_port_unblock =
787 { {"lcr", "port", "unblock", NULL},
788  lcr_port_unblock,
789  "Unblocks or loads LCR port, port is opened my mISDN",
790  "Usage: lcr port unblock \"<port>\"\n",
791 };
792
793 static struct ast_cli_entry cli_port_unload =
794 { {"lcr", "port", "unload", NULL},
795  lcr_port_unload,
796  "Unloads LCR port, port is closes by mISDN",
797  "Usage: lcr port unload \"<port>\"\n",
798 };
799
800
801 /*
802  * module loading and destruction
803  */
804 int load_module(void)
805 {
806 //      ast_mutex_init(&release_lock);
807
808 //      lcr_cfg_update_ptp();
809
810         if (!(lcr_sock = open_socket())) {
811                 ast_log(LOG_ERROR, "Unable to connect\n");
812                 lcr_sock = -1;
813                 /* continue with closed socket */
814         }
815
816         if (!bchannel_initialize()) {
817                 ast_log(LOG_ERROR, "Unable to open mISDN device\n");
818                 return -1;
819         }
820         mISDN_created = 1;
821
822         if (ast_channel_register(&lcr_tech)) {
823                 ast_log(LOG_ERROR, "Unable to register channel class\n");
824                 return -1;
825         }
826  
827 #if 0   
828         ast_cli_register(&cli_show_lcr);
829         ast_cli_register(&cli_show_calls);
830
831         ast_cli_register(&cli_reload_routing);
832         ast_cli_register(&cli_reload_interfaces);
833         ast_cli_register(&cli_port_block);
834         ast_cli_register(&cli_port_unblock);
835         ast_cli_register(&cli_port_unload);
836   
837         ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
838                                  "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
839                                  "Sets mISDN opts. and optargs\n"
840                                  "\n"
841                                  "The available options are:\n"
842                                  "    d - Send display text on called phone, text is the optparam\n"
843                                  "    n - don't detect dtmf tones on called channel\n"
844                                  "    h - make digital outgoing call\n" 
845                                  "    c - make crypted outgoing call, param is keyindex\n"
846                                  "    e - perform echo cancelation on this channel,\n"
847                                  "        takes taps as arguments (32,64,128,256)\n"
848                                  "    s - send Non Inband DTMF as inband\n"
849                                  "   vr - rxgain control\n"
850                                  "   vt - txgain control\n"
851                 );
852
853         
854         lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
855
856         chan_lcr_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
857 =======
858         //lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
859 #endif
860
861         return 0;
862 }
863
864 int unload_module(void)
865 {
866         /* First, take us out of the channel loop */
867         ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
868         
869         
870         ast_channel_unregister(&lcr_tech);
871
872         if (mISDN_created) {
873                 bchannel_deinitialize();
874                 mISDN_created = 0;
875         }
876
877         if (lcr_sock >= 0) {
878                 close(lcr_sock);
879                 lcr_sock = -1;
880         }
881
882         return 0;
883 }
884
885 static int reload_module(void)
886 {
887 //      reload_config();
888         return 0;
889 }
890
891
892 ast_mutex_t usecnt_lock;
893 int usecnt;
894
895 int usecount(void)
896 {
897         int res;
898         ast_mutex_lock(&usecnt_lock);
899         res = usecnt;
900         ast_mutex_unlock(&usecnt_lock);
901         return res;
902 }
903
904
905 char *desc="Channel driver for lcr";
906
907 char *description(void)
908 {
909         return desc;
910 }
911
912 char *key(void)
913 {
914         return ASTERISK_GPL_KEY;
915 }
916
917 #define AST_MODULE "chan_lcr"
918 AST_MODULE_INFO(ASTERISK_GPL_KEY,
919                                 AST_MODFLAG_DEFAULT,
920                                 "Channel driver for lcr",
921                                 .load = load_module,
922                                 .unload = unload_module,
923                                 .reload = reload_module,
924                            );
925