1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** Asterisk socket client **
10 \*****************************************************************************/
16 To connect, open an LCR socket and send a MESSAGE_HELLO to socket with
17 the application name. This name is unique an can be used for routing calls.
18 Now the channel driver is linked to LCR and can receive and make calls.
21 Call is initiated by LCR:
23 If a call is received from LCR, a MESSAGE_NEWREF is received first.
24 A new chan_call instance is created. The call reference (ref) is given by
25 MESSAGE_NEWREF. The state is CHAN_LCR_STATE_IN_PREPARE.
26 After receiving MESSAGE_SETUP from LCR, the ast_channel instance is created
27 using ast_channel_alloc(1). The setup information is given to asterisk.
28 The new Asterisk instance pointer (ast) is stored to chan_call structure.
29 The state changes to CHAN_LCR_STATE_IN_SETUP.
32 Call is initiated by Asterisk:
34 If a call is reveiced from Asterisk, a new chan_call instance is created.
35 The new Asterisk instance pointer (ast) is stored to chan_call structure.
36 A MESSASGE_NEWREF is sent to LCR requesting a new call reference (ref).
37 The current call ref is set to 0, the state is CHAN_LCR_STATE_OUT_PREPARE.
38 Further dialing information is queued.
39 After the new callref is received by special MESSAGE_NEWREF reply, new ref
40 is stored in the chan_call structure.
41 The setup information is sent to LCR using MESSAGE_SETUP.
42 The state changes to CHAN_LCR_STATE_OUT_SETUP.
47 During call process, messages are received and sent.
48 The state changes accordingly.
49 Any message is allowed to be sent to LCR at any time except MESSAGE_RELEASE.
50 If a MESSAGE_OVERLAP is received, further dialing is required.
51 Queued dialing information, if any, is sent to LCR using MESSAGE_DIALING.
52 In this case, the state changes to CHAN_LCR_STATE_OUT_DIALING.
55 Call is released by LCR:
57 A MESSAGE_RELEASE is received with the call reference (ref) to be released.
58 The current ref is set to 0, to indicate released reference.
59 The state changes to CHAN_LCR_STATE_RELEASE.
60 ast_queue_hangup() is called, if asterisk instance (ast) exists, if not,
61 the chan_call instance is destroyed.
62 After lcr_hangup() is called-back by Asterisk, the chan_call instance
63 is destroyed, because the current ref is set to 0 and the state equals
64 CHAN_LCR_STATE_RELEASE.
65 If the ref is 0 and the state is not CHAN_LCR_STATE_RELEASE, see the proceedure
66 "Call is released by Asterisk".
69 Call is released by Asterisk:
71 lcr_hangup() is called-back by Asterisk. If the call reference (ref) is set,
72 a MESSAGE_RELEASE is sent to LCR and the chan_call instance is destroyed.
73 If the ref is 0 and the state is not CHAN_LCR_STATE_RELEASE, the new state is
74 set to CHAN_LCR_STATE_RELEASE.
75 Later, if the MESSAGE_NEWREF reply is received, a MESSAGE_RELEASE is sent to
76 LCR and the chan_call instance is destroyed.
77 If the ref is 0 and the state is CHAN_LCR_STATE_RELEASE, see the proceedure
78 "Call is released by LCR".
82 locking asterisk process and handler
83 reconnect after socket closed, release all calls.
84 debug of call handling
85 denke an alle info-elements in jeder message (from asterisk & from lcr)
93 #include <sys/types.h>
97 #include <sys/ioctl.h>
98 #include <sys/socket.h>
102 #include <semaphore.h>
104 #include "extension.h"
106 #include "lcrsocket.h"
108 #include "bchannel.h"
109 #include "chan_lcr.h"
113 #include <asterisk/module.h>
114 #include <asterisk/channel.h>
115 #include <asterisk/config.h>
116 #include <asterisk/logger.h>
117 #include <asterisk/pbx.h>
118 #include <asterisk/options.h>
119 #include <asterisk/io.h>
120 #include <asterisk/frame.h>
121 #include <asterisk/translate.h>
122 #include <asterisk/cli.h>
123 #include <asterisk/musiconhold.h>
124 #include <asterisk/dsp.h>
125 #include <asterisk/translate.h>
126 #include <asterisk/file.h>
127 #include <asterisk/callerid.h>
128 #include <asterisk/indications.h>
129 #include <asterisk/app.h>
130 #include <asterisk/features.h>
131 #include <asterisk/sched.h>
133 CHAN_LCR_STATE // state description structure
142 struct admin_list *next;
143 struct admin_msg msg;
144 } *admin_first = NULL;
147 * channel and call instances
149 struct chan_call *call_first;
151 struct chan_call *find_call_ref(unsigned long ref)
153 struct chan_call *call = call_first;
157 if (call->ref == ref)
164 struct chan_call *find_call_handle(unsigned long handle)
166 struct chan_call *call = call_first;
170 if (call->bchannel_handle == handle)
177 struct chan_call *alloc_call(void)
179 struct chan_call **callp = &call_first;
182 callp = &((*callp)->next);
184 *callp = (struct chan_call *)malloc(sizeof(struct chan_call));
186 memset(*callp, 0, sizeof(struct chan_call));
190 void free_call(struct chan_call *call)
192 struct chan_call **temp = &call_first;
198 *temp = (*temp)->next;
202 temp = &((*temp)->next);
206 unsigned short new_brige_id(void)
208 struct chan_call *call;
209 unsigned short id = 1;
211 /* search for lowest bridge id that is not in use and not 0 */
217 if (call->bridge_id == id)
230 * receive bchannel data
232 void rx_data(struct bchannel *bchannel, unsigned char *data, int len)
236 void rx_dtmf(struct bchannel *bchannel, char tone)
241 * enque message to LCR
243 int send_message(int message_type, unsigned long ref, union parameter *param)
245 struct admin_list *admin, **adminp;
247 adminp = &admin_first;
249 adminp = &((*adminp)->next);
250 admin = (struct admin_list *)malloc(sizeof(struct admin_list));
253 admin->msg.type = message_type;
254 admin->msg.ref = ref;
255 memcpy(&admin->msg.param, param, sizeof(union parameter));
261 * incoming setup from LCR
263 static void lcr_in_setup(struct chan_call *call, int message_type, union parameter *param)
265 struct ast_channel *ast;
266 union parameter newparam;
268 /* create asterisk channel instrance */
269 ast = ast_channel_alloc(1);
273 memset(&newparam, 0, sizeof(union parameter));
274 newparam.disconnectinfo.cause = CAUSE_RESSOURCEUNAVAIL;
275 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
276 send_message(MESSAGE_RELEASE, call->ref, &newparam);
281 /* set ast pointer */
284 /* fill setup information */
285 #warning todo: setup-info reinschreiben
287 /* send setup to asterisk */
288 #warning todo: setup bei der asterisk triggern
291 call->state = CHAN_LCR_STATE_IN_SETUP;
295 * incoming setup acknowledge from LCR
297 static void lcr_in_overlap(struct chan_call *call, int message_type, union parameter *param)
299 /* send pending digits in dialque */
301 send_dialing_to_lcr(call);
302 /* change to overlap state */
303 call->state = CHAN_LCR_STATE_OUT_DIALING;
307 * incoming proceeding from LCR
309 static void lcr_in_proceeding(struct chan_call *call, int message_type, union parameter *param)
312 call->state = CHAN_LCR_STATE_OUT_PROCEEDING;
313 /* send event to asterisk */
318 * incoming alerting from LCR
320 static void lcr_in_alerting(struct chan_call *call, int message_type, union parameter *param)
323 call->state = CHAN_LCR_STATE_OUT_ALERTING;
324 /* send event to asterisk */
329 * incoming connect from LCR
331 static void lcr_in_connect(struct chan_call *call, int message_type, union parameter *param)
334 call->state = CHAN_LCR_STATE_CONNECT;
335 /* copy connectinfo */
337 /* send event to asterisk */
342 * incoming disconnect from LCR
344 static void lcr_in_disconnect(struct chan_call *call, int message_type, union parameter *param)
347 call->state = CHAN_LCR_STATE_IN_DISCONNECT;
348 /* copy disconnect info */
350 /* send event to asterisk */
355 * incoming setup acknowledge from LCR
357 static void lcr_in_release(struct chan_call *call, int message_type, union parameter *param)
361 /* change to release state */
362 call->state = CHAN_LCR_STATE_RELEASE;
363 /* copy release info */
365 /* if we have an asterisk instance, send hangup, else we are done */
368 ast_queue_hangup(call->ast);
377 * incoming information from LCR
379 static void lcr_in_information(struct chan_call *call, int message_type, union parameter *param)
382 todo and write them, maybe queue them for asterisk
383 /* send event to asterisk */
388 * incoming information from LCR
390 static void lcr_in_facility(struct chan_call *call, int message_type, union parameter *param)
392 /* copy progress info */
393 todo and write them, maybe queue them for asterisk
394 /* send event to asterisk */
396 or maybe use bride info to forward facility.
400 * message received from LCR
402 int receive_message(int message_type, unsigned long ref, union parameter *param)
404 union parameter newparam;
405 struct bchannel *bchannel;
406 struct chan_call *call;
408 memset(&newparam, 0, sizeof(union parameter));
410 /* handle bchannel message*/
411 if (message_type == MESSAGE_BCHANNEL)
413 switch(param->bchannel.type)
415 case BCHANNEL_ASSIGN:
416 if ((bchannel = find_bchannel_handle(param->bchannel.handle)))
418 fprintf(stderr, "error: bchannel handle %x already assigned.\n", (int)param->bchannel.handle);
421 /* create bchannel */
422 bchannel = alloc_bchannel(param->bchannel.handle);
425 fprintf(stderr, "error: alloc bchannel handle %x failed.\n", (int)param->bchannel.handle);
429 /* configure channel */
430 bchannel->b_tx_gain = param->bchannel.tx_gain;
431 bchannel->b_rx_gain = param->bchannel.rx_gain;
432 strncpy(bchannel->b_pipeline, param->bchannel.pipeline, sizeof(bchannel->b_pipeline)-1);
433 if (param->bchannel.crypt_len)
435 bchannel->b_crypt_len = param->bchannel.crypt_len;
436 bchannel->b_crypt_type = param->bchannel.crypt_type;
437 memcpy(bchannel->b_crypt_key, param->bchannel.crypt, param->bchannel.crypt_len);
439 bchannel->b_txdata = 0;
440 bchannel->b_dtmf = 1;
441 bchannel->b_tx_dejitter = 1;
443 /* in case, ref is not set, this bchannel instance must
444 * be created until it is removed again by LCR */
446 if ((call = find_call_ref(ref)))
449 call->bchannel_handle = param->bchannel.handle;
450 #warning hier muesen alle stati gesetzt werden falls sie vor dem b-kanal verfügbar waren
451 bchannel_join(bchannel, call->bridge_id);
453 if (bchannel_create(bchannel))
454 bchannel_activate(bchannel, 1);
457 newparam.bchannel.type = BCHANNEL_ASSIGN_ACK;
458 newparam.bchannel.handle = param->bchannel.handle;
459 send_message(MESSAGE_BCHANNEL, 0, &newparam);
462 case BCHANNEL_REMOVE:
463 if (!(bchannel = find_bchannel_handle(param->bchannel.handle)))
465 #warning alle fprintf nach ast_log
466 fprintf(stderr, "error: bchannel handle %x not assigned.\n", (int)param->bchannel.handle);
469 /* unlink from call */
470 if ((call = find_call_ref(bchannel->ref)))
472 call->bchannel_handle = 0;
474 /* destroy and remove bchannel */
475 free_bchannel(bchannel);
478 newparam.bchannel.type = BCHANNEL_REMOVE_ACK;
479 newparam.bchannel.handle = param->bchannel.handle;
480 send_message(MESSAGE_BCHANNEL, 0, &newparam);
485 fprintf(stderr, "received unknown bchannel message %d\n", param->bchannel.type);
491 if (message_type == MESSAGE_NEWREF)
493 if (param->direction)
495 /* new ref from lcr */
496 if (!ref || find_call_ref(ref))
498 fprintf(stderr, "illegal new ref %d received\n", ref);
501 /* allocate new call instance */
504 call->state = CHAN_LCR_STATE_IN_PREPARE;
507 /* wait for setup (or release from asterisk) */
510 /* new ref, as requested from this remote application */
511 call = find_call_ref(0);
514 /* send release, if ref does not exist */
515 newparam.disconnectinfo.cause = CAUSE_NORMAL;
516 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
517 send_message(MESSAGE_RELEASE, ref, &newparam);
522 /* send pending setup info */
523 if (call->state == CHAN_LCR_STATE_OUT_PREPARE)
524 send_setup_to_lcr(call);
525 /* release if asterisk has signed off */
526 else if (call->state == CHAN_LCR_STATE_RELEASE)
529 newparam.disconnectinfo.cause = todo
530 newparam.disconnectinfo.location = todo
531 send_message(MESSAGE_RELEASE, ref, &newparam);
543 fprintf(stderr, "received message %d without ref\n", message_type);
546 call = find_call_ref(ref);
549 /* ignore ref that is not used (anymore) */
553 /* handle messages */
557 lcr_in_setup(call, message_type, param);
560 case MESSAGE_OVERLAP:
561 lcr_in_overlap(call, message_type, param);
564 case MESSAGE_PROCEEDING:
565 lcr_in_proceeding(call, message_type, param);
568 case MESSAGE_ALERTING:
569 lcr_in_alerting(call, message_type, param);
572 case MESSAGE_CONNECT:
573 lcr_in_connect(call, message_type, param);
576 case MESSAGE_DISCONNECT:
577 lcr_in_disconnect(call, message_type, param);
580 case MESSAGE_RELEASE:
581 lcr_in_release(call, message_type, param);
584 case MESSAGE_INFORMATION:
585 lcr_in_disconnect(call, message_type, param);
588 case MESSAGE_FACILITY:
589 lcr_in_disconnect(call, message_type, param);
592 case MESSAGE_PATTERN:
596 case MESSAGE_NOPATTERN:
600 case MESSAGE_AUDIOPATH:
612 * warning! not thread safe
613 * returns -1 for socket error, 0 for no work, 1 for work
615 int handle_socket(void)
619 struct admin_message msg;
620 struct admin_list *admin;
624 #warning SOCKET FEHLT!
625 /* read from socket */
626 len = read(sock, &msg, sizeof(msg));
629 printf("Socket closed\n");
630 return(-1); // socket closed
634 if (len != sizeof(msg))
636 fprintf(stderr, "Socket short read (%d)\n", len);
637 return(-1); // socket error
639 if (msg.message != ADMIN_MESSAGE)
641 fprintf(stderr, "Socket received illegal message %d\n", msg.message);
642 return(-1); // socket error
644 receive_message(msg.u.msg.type, msg.u.msg.ref, &msg.u.msg.param);
645 printf("message received %d\n", msg.u.msg.type);
649 if (errno != EWOULDBLOCK)
651 fprintf(stderr, "Socket error %d\n", errno);
656 /* write to socket */
660 len = write(sock, &admin->msg, sizeof(msg));
663 printf("Socket closed\n");
664 return(-1); // socket closed
668 if (len != sizeof(msg))
670 fprintf(stderr, "Socket short write (%d)\n", len);
671 return(-1); // socket error
674 admin_first = admin->next;
680 if (errno != EWOULDBLOCK)
682 fprintf(stderr, "Socket error %d\n", errno);
691 * open and close socket
693 int open_socket(void)
697 char *socket_name = SOCKET_NAME;
699 struct sockaddr_un sock_address;
700 unsigned long on = 1;
701 union parameter param;
704 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
706 ast_log(LOG_ERROR, "Failed to create socket.\n");
710 /* set socket address and name */
711 memset(&sock_address, 0, sizeof(sock_address));
712 sock_address.sun_family = PF_UNIX;
713 strcpy(sock_address.sun_path, socket_name);
716 if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
719 ast_log(LOG_ERROR, "Failed to connect to socket \"%s\". Is LCR running?\n", sock_address.sun_path);
723 /* set non-blocking io */
724 if ((ret = ioctl(sock, FIONBIO, (unsigned char *)(&on))) < 0)
727 ast_log(LOG_ERROR, "Failed to set socket into non-blocking IO.\n");
731 /* enque hello message */
732 memset(¶m, 0, sizeof(param));
733 strcpy(param.hello.application, "asterisk");
734 send_message(MESSAGE_HELLO, 0, ¶m);
739 void close_socket(int sock)
747 hander thread muss noch
748 socket muss per timer fuer das öffnen checken
749 void lcr_thread(void)
758 int ret = handle_socket();
765 ret = bchannel_handle();
775 * send setup info to LCR
776 * this function is called, when asterisk call is received and ref is received
778 static void send_setup_to_lcr(struct chan_call *call)
780 if (!ast || !call->ref)
783 /* send setup message to LCR */
784 memset(&newparam, 0, sizeof(union parameter));
785 newparam.setup.xxxxxx =
786 send_message(MESSAGE_SETUP, call->ref, &newparam);
787 /* change to outgoing setup state */
788 call->state = CHAN_LCR_STATE_OUT_SETUP;
792 * send dialing info to LCR
793 * this function is called, when setup acknowledge is received and dialing
796 static void send_dialing_to_lcr(struct chan_call *call)
798 if (!ast || !call->ref || !call->dialque)
801 /* send setup message to LCR */
802 memset(&newparam, 0, sizeof(union parameter));
803 strncpy(newparam.dialinginfo.id, call->dialque, sizeof(newparam.dialinginfo.id)-1);
804 call->dialque[0] = '\0';
805 send_message(MESSAGE_INFORMATION, call->ref, &newparam);
809 * new asterisk instance
811 static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause)
813 /* create call instance */
817 /* failed to create instance */
820 /* create asterisk channel instrance */
821 ast = ast_channel_alloc(1);
825 /* failed to create instance */
829 ast->tech_pvt = call;
831 /* send MESSAGE_NEWREF */
832 memset(&newparam, 0, sizeof(union parameter));
833 newparam.direction = 0; /* request from app */
834 send_message(MESSAGE_NEWREF, 0, &newparam);
836 call->state = CHAN_LCR_STATE_OUT_PREPARE;
842 static int lcr_call(struct ast_channel *ast, char *dest, int timeout)
844 struct lcr_pvt *lcr=ast->tech_pvt;
849 char *port_str, *dad, *p;
852 ast_copy_string(buf, dest, sizeof(buf)-1);
854 port_str=strsep(&p, "/");
857 /* send setup message, if we already have a callref */
859 send_setup_to_lcr(call);
862 ast_verbose("Call: ext:%s dest:(%s) -> dad(%s) \n", ast->exten,dest, dad);
868 static int lcr_digit(struct ast_channel *ast, char digit)
872 /* only pass IA5 number space */
873 if (digit > 126 || digit < 32)
876 /* send information or queue them */
877 if (call->ref && call->state == CHAN_LCR_STATE_OUT_DIALING)
879 send_dialing_to_lcr(call);
882 && (call->state == CHAN_LCR_STATE_OUT_PREPARE || call->state == CHAN_LCR_STATE_OUT_SETUP));
885 strncat(call->dialque, buf, strlen(char->dialque)-1);
888 digits kommen, koennen aber nicht verwendet werden.
889 sollen wir sie als info senden (im connect zb.)
893 static int lcr_answer(struct ast_channel *c)
895 struct lcr_pvt *lcr=c->tech_pvt;
899 static int lcr_hangup(struct ast_channel *ast)
901 struct chan_call *call = ast->tech_pvt;
903 /* disconnect asterisk, maybe not required */
904 ast->tech_pvt = NULL;
908 memset(&newparam, 0, sizeof(union parameter));
909 newparam.disconnectinfo.cause = CAUSE_RESSOURCEUNAVAIL;
910 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
911 send_message(MESSAGE_RELEASE, call->ref, &newparam);
917 /* ref is not set, due to prepare setup or release */
918 if (call->state == CHAN_LCR_STATE_RELEASE)
920 /* we get the response to our release */
924 /* during prepare, we change to release state */
925 call->state = CHAN_LCR_STATE_RELEASE;
930 static int lcr_write(struct ast_channel *c, struct ast_frame *f)
932 struct lcr_pvt *lcrm= c->tech_pvt;
936 static struct ast_frame *lcr_read(struct ast_channel *c)
938 struct lcr_pvt *lcr = c->tech_pvt;
941 static int lcr_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen)
946 case AST_CONTROL_BUSY:
947 case AST_CONTROL_CONGESTION:
948 case AST_CONTROL_RINGING:
953 case AST_CONTROL_VIDUPDATE:
956 case AST_CONTROL_HOLD:
957 ast_verbose(" << Console Has Been Placed on Hold >> \n");
958 //ast_moh_start(c, data, g->mohinterpret);
960 case AST_CONTROL_UNHOLD:
961 ast_verbose(" << Console Has Been Retrieved from Hold >> \n");
966 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name);
973 static struct ast_channel_tech lcr_tech = {
975 .description="Channel driver for connecting to Linux-Call-Router",
976 .capabilities=AST_FORMAT_ALAW,
977 .requester=lcr_request,
978 .send_digit=lcr_digit,
980 // .bridge=lcr_bridge,
985 .indicate=lcr_indicate,
987 // .send_text=lcr_send_text,
994 static int lcr_show_lcr (int fd, int argc, char *argv[])
998 static int lcr_show_calls (int fd, int argc, char *argv[])
1002 static int lcr_reload_routing (int fd, int argc, char *argv[])
1006 static int lcr_reload_interfaces (int fd, int argc, char *argv[])
1010 static int lcr_port_block (int fd, int argc, char *argv[])
1014 static int lcr_port_unblock (int fd, int argc, char *argv[])
1018 static int lcr_port_unload (int fd, int argc, char *argv[])
1022 static struct ast_cli_entry cli_show_lcr =
1023 { {"lcr", "show", "lcr", NULL},
1025 "Shows current states of LCR core",
1026 "Usage: lcr show lcr\n",
1029 static struct ast_cli_entry cli_show_calls =
1030 { {"lcr", "show", "calls", NULL},
1032 "Shows current calls made by LCR and Asterisk",
1033 "Usage: lcr show calls\n",
1036 static struct ast_cli_entry cli_reload_routing =
1037 { {"lcr", "reload", "routing", NULL},
1039 "Reloads routing conf of LCR, current uncomplete calls will be disconnected",
1040 "Usage: lcr reload routing\n",
1043 static struct ast_cli_entry cli_reload_interfaces =
1044 { {"lcr", "reload", "interfaces", NULL},
1045 lcr_reload_interfaces,
1046 "Reloads interfaces conf of LCR",
1047 "Usage: lcr reload interfaces\n",
1050 static struct ast_cli_entry cli_port_block =
1051 { {"lcr", "port", "block", NULL},
1053 "Blocks LCR port for further calls",
1054 "Usage: lcr port block \"<port>\"\n",
1057 static struct ast_cli_entry cli_port_unblock =
1058 { {"lcr", "port", "unblock", NULL},
1060 "Unblocks or loads LCR port, port is opened my mISDN",
1061 "Usage: lcr port unblock \"<port>\"\n",
1064 static struct ast_cli_entry cli_port_unload =
1065 { {"lcr", "port", "unload", NULL},
1067 "Unloads LCR port, port is closes by mISDN",
1068 "Usage: lcr port unload \"<port>\"\n",
1073 * module loading and destruction
1075 int load_module(void)
1077 // ast_mutex_init(&release_lock);
1079 // lcr_cfg_update_ptp();
1081 if (!(lcr_sock = open_socket())) {
1082 ast_log(LOG_ERROR, "Unable to connect\n");
1084 /* continue with closed socket */
1087 if (!bchannel_initialize()) {
1088 ast_log(LOG_ERROR, "Unable to open mISDN device\n");
1093 if (ast_channel_register(&lcr_tech)) {
1094 ast_log(LOG_ERROR, "Unable to register channel class\n");
1099 ast_cli_register(&cli_show_lcr);
1100 ast_cli_register(&cli_show_calls);
1102 ast_cli_register(&cli_reload_routing);
1103 ast_cli_register(&cli_reload_interfaces);
1104 ast_cli_register(&cli_port_block);
1105 ast_cli_register(&cli_port_unblock);
1106 ast_cli_register(&cli_port_unload);
1108 ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
1109 "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
1110 "Sets mISDN opts. and optargs\n"
1112 "The available options are:\n"
1113 " d - Send display text on called phone, text is the optparam\n"
1114 " n - don't detect dtmf tones on called channel\n"
1115 " h - make digital outgoing call\n"
1116 " c - make crypted outgoing call, param is keyindex\n"
1117 " e - perform echo cancelation on this channel,\n"
1118 " takes taps as arguments (32,64,128,256)\n"
1119 " s - send Non Inband DTMF as inband\n"
1120 " vr - rxgain control\n"
1121 " vt - txgain control\n"
1125 lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
1127 chan_lcr_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
1129 //lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
1135 int unload_module(void)
1137 /* First, take us out of the channel loop */
1138 ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
1141 ast_channel_unregister(&lcr_tech);
1143 if (mISDN_created) {
1144 bchannel_deinitialize();
1148 if (lcr_sock >= 0) {
1156 static int reload_module(void)
1163 ast_mutex_t usecnt_lock;
1169 ast_mutex_lock(&usecnt_lock);
1171 ast_mutex_unlock(&usecnt_lock);
1176 char *desc="Channel driver for lcr";
1178 char *description(void)
1185 return ASTERISK_GPL_KEY;
1188 #define AST_MODULE "chan_lcr"
1189 AST_MODULE_INFO(ASTERISK_GPL_KEY,
1190 AST_MODFLAG_DEFAULT,
1191 "Channel driver for LCR",
1192 .load = load_module,
1193 .unload = unload_module,
1194 .reload = reload_module,