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
138 char lcr_type[]="LCR";
144 struct admin_list *next;
145 struct admin_msg msg;
146 } *admin_first = NULL;
149 * channel and call instances
151 struct chan_call *call_first;
153 struct chan_call *find_call_ref(unsigned long ref)
155 struct chan_call *call = call_first;
159 if (call->ref == ref)
166 struct chan_call *find_call_handle(unsigned long handle)
168 struct chan_call *call = call_first;
172 if (call->bchannel_handle == handle)
179 struct chan_call *alloc_call(void)
181 struct chan_call **callp = &call_first;
184 callp = &((*callp)->next);
186 *callp = (struct chan_call *)malloc(sizeof(struct chan_call));
188 memset(*callp, 0, sizeof(struct chan_call));
192 void free_call(struct chan_call *call)
194 struct chan_call **temp = &call_first;
200 *temp = (*temp)->next;
204 temp = &((*temp)->next);
208 unsigned short new_brige_id(void)
210 struct chan_call *call;
211 unsigned short id = 1;
213 /* search for lowest bridge id that is not in use and not 0 */
219 if (call->bridge_id == id)
232 * receive bchannel data
234 void rx_data(struct bchannel *bchannel, unsigned char *data, int len)
238 void rx_dtmf(struct bchannel *bchannel, char tone)
243 * enque message to LCR
245 int send_message(int message_type, unsigned long ref, union parameter *param)
247 struct admin_list *admin, **adminp;
249 adminp = &admin_first;
251 adminp = &((*adminp)->next);
252 admin = (struct admin_list *)malloc(sizeof(struct admin_list));
255 admin->msg.type = message_type;
256 admin->msg.ref = ref;
257 memcpy(&admin->msg.param, param, sizeof(union parameter));
263 * incoming setup from LCR
265 static void lcr_in_setup(struct chan_call *call, int message_type, union parameter *param)
267 struct ast_channel *ast;
268 union parameter newparam;
270 /* create asterisk channel instrance */
271 ast = ast_channel_alloc(1);
275 memset(&newparam, 0, sizeof(union parameter));
276 newparam.disconnectinfo.cause = CAUSE_RESSOURCEUNAVAIL;
277 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
278 send_message(MESSAGE_RELEASE, call->ref, &newparam);
283 /* set ast pointer */
286 /* fill setup information */
287 #warning todo: setup-info reinschreiben
289 /* send setup to asterisk */
290 #warning todo: setup bei der asterisk triggern
293 call->state = CHAN_LCR_STATE_IN_SETUP;
297 * incoming setup acknowledge from LCR
299 static void lcr_in_overlap(struct chan_call *call, int message_type, union parameter *param)
301 /* send pending digits in dialque */
303 send_dialing_to_lcr(call);
304 /* change to overlap state */
305 call->state = CHAN_LCR_STATE_OUT_DIALING;
309 * incoming proceeding from LCR
311 static void lcr_in_proceeding(struct chan_call *call, int message_type, union parameter *param)
314 call->state = CHAN_LCR_STATE_OUT_PROCEEDING;
315 /* send event to asterisk */
320 * incoming alerting from LCR
322 static void lcr_in_alerting(struct chan_call *call, int message_type, union parameter *param)
325 call->state = CHAN_LCR_STATE_OUT_ALERTING;
326 /* send event to asterisk */
331 * incoming connect from LCR
333 static void lcr_in_connect(struct chan_call *call, int message_type, union parameter *param)
336 call->state = CHAN_LCR_STATE_CONNECT;
337 /* copy connectinfo */
339 /* send event to asterisk */
344 * incoming disconnect from LCR
346 static void lcr_in_disconnect(struct chan_call *call, int message_type, union parameter *param)
349 call->state = CHAN_LCR_STATE_IN_DISCONNECT;
350 /* copy disconnect info */
352 /* send event to asterisk */
357 * incoming setup acknowledge from LCR
359 static void lcr_in_release(struct chan_call *call, int message_type, union parameter *param)
363 /* change to release state */
364 call->state = CHAN_LCR_STATE_RELEASE;
365 /* copy release info */
367 /* if we have an asterisk instance, send hangup, else we are done */
370 ast_queue_hangup(call->ast);
379 * incoming information from LCR
381 static void lcr_in_information(struct chan_call *call, int message_type, union parameter *param)
384 todo and write them, maybe queue them for asterisk
385 /* send event to asterisk */
390 * incoming information from LCR
392 static void lcr_in_facility(struct chan_call *call, int message_type, union parameter *param)
394 /* copy progress info */
395 todo and write them, maybe queue them for asterisk
396 /* send event to asterisk */
398 or maybe use bride info to forward facility.
402 * message received from LCR
404 int receive_message(int message_type, unsigned long ref, union parameter *param)
406 union parameter newparam;
407 struct bchannel *bchannel;
408 struct chan_call *call;
410 memset(&newparam, 0, sizeof(union parameter));
412 /* handle bchannel message*/
413 if (message_type == MESSAGE_BCHANNEL)
415 switch(param->bchannel.type)
417 case BCHANNEL_ASSIGN:
418 if ((bchannel = find_bchannel_handle(param->bchannel.handle)))
420 fprintf(stderr, "error: bchannel handle %x already assigned.\n", (int)param->bchannel.handle);
423 /* create bchannel */
424 bchannel = alloc_bchannel(param->bchannel.handle);
427 fprintf(stderr, "error: alloc bchannel handle %x failed.\n", (int)param->bchannel.handle);
431 /* configure channel */
432 bchannel->b_tx_gain = param->bchannel.tx_gain;
433 bchannel->b_rx_gain = param->bchannel.rx_gain;
434 strncpy(bchannel->b_pipeline, param->bchannel.pipeline, sizeof(bchannel->b_pipeline)-1);
435 if (param->bchannel.crypt_len)
437 bchannel->b_crypt_len = param->bchannel.crypt_len;
438 bchannel->b_crypt_type = param->bchannel.crypt_type;
439 memcpy(bchannel->b_crypt_key, param->bchannel.crypt, param->bchannel.crypt_len);
441 bchannel->b_txdata = 0;
442 bchannel->b_dtmf = 1;
443 bchannel->b_tx_dejitter = 1;
445 /* in case, ref is not set, this bchannel instance must
446 * be created until it is removed again by LCR */
448 if ((call = find_call_ref(ref)))
451 call->bchannel_handle = param->bchannel.handle;
452 #warning hier muesen alle stati gesetzt werden falls sie vor dem b-kanal verfügbar waren
453 bchannel_join(bchannel, call->bridge_id);
455 if (bchannel_create(bchannel))
456 bchannel_activate(bchannel, 1);
459 newparam.bchannel.type = BCHANNEL_ASSIGN_ACK;
460 newparam.bchannel.handle = param->bchannel.handle;
461 send_message(MESSAGE_BCHANNEL, 0, &newparam);
464 case BCHANNEL_REMOVE:
465 if (!(bchannel = find_bchannel_handle(param->bchannel.handle)))
467 #warning alle fprintf nach ast_log
468 fprintf(stderr, "error: bchannel handle %x not assigned.\n", (int)param->bchannel.handle);
471 /* unlink from call */
472 if ((call = find_call_ref(bchannel->ref)))
474 call->bchannel_handle = 0;
476 /* destroy and remove bchannel */
477 free_bchannel(bchannel);
480 newparam.bchannel.type = BCHANNEL_REMOVE_ACK;
481 newparam.bchannel.handle = param->bchannel.handle;
482 send_message(MESSAGE_BCHANNEL, 0, &newparam);
487 fprintf(stderr, "received unknown bchannel message %d\n", param->bchannel.type);
493 if (message_type == MESSAGE_NEWREF)
495 if (param->direction)
497 /* new ref from lcr */
498 if (!ref || find_call_ref(ref))
500 fprintf(stderr, "illegal new ref %d received\n", ref);
503 /* allocate new call instance */
506 call->state = CHAN_LCR_STATE_IN_PREPARE;
509 /* wait for setup (or release from asterisk) */
512 /* new ref, as requested from this remote application */
513 call = find_call_ref(0);
516 /* send release, if ref does not exist */
517 newparam.disconnectinfo.cause = CAUSE_NORMAL;
518 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
519 send_message(MESSAGE_RELEASE, ref, &newparam);
524 /* send pending setup info */
525 if (call->state == CHAN_LCR_STATE_OUT_PREPARE)
526 send_setup_to_lcr(call);
527 /* release if asterisk has signed off */
528 else if (call->state == CHAN_LCR_STATE_RELEASE)
531 newparam.disconnectinfo.cause = todo
532 newparam.disconnectinfo.location = todo
533 send_message(MESSAGE_RELEASE, ref, &newparam);
545 fprintf(stderr, "received message %d without ref\n", message_type);
548 call = find_call_ref(ref);
551 /* ignore ref that is not used (anymore) */
555 /* handle messages */
559 lcr_in_setup(call, message_type, param);
562 case MESSAGE_OVERLAP:
563 lcr_in_overlap(call, message_type, param);
566 case MESSAGE_PROCEEDING:
567 lcr_in_proceeding(call, message_type, param);
570 case MESSAGE_ALERTING:
571 lcr_in_alerting(call, message_type, param);
574 case MESSAGE_CONNECT:
575 lcr_in_connect(call, message_type, param);
578 case MESSAGE_DISCONNECT:
579 lcr_in_disconnect(call, message_type, param);
582 case MESSAGE_RELEASE:
583 lcr_in_release(call, message_type, param);
586 case MESSAGE_INFORMATION:
587 lcr_in_disconnect(call, message_type, param);
590 case MESSAGE_FACILITY:
591 lcr_in_disconnect(call, message_type, param);
594 case MESSAGE_PATTERN:
598 case MESSAGE_NOPATTERN:
602 case MESSAGE_AUDIOPATH:
614 * warning! not thread safe
615 * returns -1 for socket error, 0 for no work, 1 for work
617 int handle_socket(void)
621 struct admin_message msg;
622 struct admin_list *admin;
626 #warning SOCKET FEHLT!
627 /* read from socket */
628 len = read(sock, &msg, sizeof(msg));
631 printf("Socket closed\n");
632 return(-1); // socket closed
636 if (len != sizeof(msg))
638 fprintf(stderr, "Socket short read (%d)\n", len);
639 return(-1); // socket error
641 if (msg.message != ADMIN_MESSAGE)
643 fprintf(stderr, "Socket received illegal message %d\n", msg.message);
644 return(-1); // socket error
646 receive_message(msg.u.msg.type, msg.u.msg.ref, &msg.u.msg.param);
647 printf("message received %d\n", msg.u.msg.type);
651 if (errno != EWOULDBLOCK)
653 fprintf(stderr, "Socket error %d\n", errno);
658 /* write to socket */
662 len = write(sock, &admin->msg, sizeof(msg));
665 printf("Socket closed\n");
666 return(-1); // socket closed
670 if (len != sizeof(msg))
672 fprintf(stderr, "Socket short write (%d)\n", len);
673 return(-1); // socket error
676 admin_first = admin->next;
682 if (errno != EWOULDBLOCK)
684 fprintf(stderr, "Socket error %d\n", errno);
693 * open and close socket
695 int open_socket(void)
699 char *socket_name = SOCKET_NAME;
701 struct sockaddr_un sock_address;
702 unsigned long on = 1;
703 union parameter param;
706 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
708 ast_log(LOG_ERROR, "Failed to create socket.\n");
712 /* set socket address and name */
713 memset(&sock_address, 0, sizeof(sock_address));
714 sock_address.sun_family = PF_UNIX;
715 strcpy(sock_address.sun_path, socket_name);
718 if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
721 ast_log(LOG_ERROR, "Failed to connect to socket \"%s\". Is LCR running?\n", sock_address.sun_path);
725 /* set non-blocking io */
726 if ((ret = ioctl(sock, FIONBIO, (unsigned char *)(&on))) < 0)
729 ast_log(LOG_ERROR, "Failed to set socket into non-blocking IO.\n");
733 /* enque hello message */
734 memset(¶m, 0, sizeof(param));
735 strcpy(param.hello.application, "asterisk");
736 send_message(MESSAGE_HELLO, 0, ¶m);
741 void close_socket(int sock)
749 hander thread muss noch
750 socket muss per timer fuer das öffnen checken
751 void lcr_thread(void)
760 int ret = handle_socket();
767 ret = bchannel_handle();
777 * send setup info to LCR
778 * this function is called, when asterisk call is received and ref is received
780 static void send_setup_to_lcr(struct chan_call *call)
782 if (!ast || !call->ref)
785 /* send setup message to LCR */
786 memset(&newparam, 0, sizeof(union parameter));
787 newparam.setup.xxxxxx =
788 send_message(MESSAGE_SETUP, call->ref, &newparam);
789 /* change to outgoing setup state */
790 call->state = CHAN_LCR_STATE_OUT_SETUP;
794 CHRISTIAN: das war ein konflikt beim pullen
795 siehe anderes lcr_request();
796 bedenke: das ast_log muss noch üeberall eingepflegt werden
798 static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause)
800 struct chan_call *call=alloc_call();
803 #warning hier muss jetzt wohl eine Ref angefordert werden!
804 ast=lcr_ast_new(call, ext, NULL, 0 );
809 ast_log(LOG_WARNING, "Could not create new Asterisk Channel\n");
813 ast_log(LOG_WARNING, "Could not create new Lcr Call Handle\n");
819 struct ast_channel *ast=NULL;
822 char *port_str, *ext, *p;
825 ast_copy_string(buf, data, sizeof(buf)-1);
827 port_str=strsep(&p, "/");
829 ast_verbose("portstr:%s ext:%s\n",port_str, ext);
831 sprintf(buf,"%s/%s",lcr_type,(char*)data);
835 * send dialing info to LCR
836 * this function is called, when setup acknowledge is received and dialing
839 static void send_dialing_to_lcr(struct chan_call *call)
841 if (!ast || !call->ref || !call->dialque)
844 /* send setup message to LCR */
845 memset(&newparam, 0, sizeof(union parameter));
846 strncpy(newparam.dialinginfo.id, call->dialque, sizeof(newparam.dialinginfo.id)-1);
847 call->dialque[0] = '\0';
848 send_message(MESSAGE_INFORMATION, call->ref, &newparam);
852 * new asterisk instance
854 static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause)
856 /* create call instance */
860 /* failed to create instance */
863 /* create asterisk channel instrance */
864 ast = ast_channel_alloc(1);
868 /* failed to create instance */
872 ast->tech_pvt = call;
874 /* send MESSAGE_NEWREF */
875 memset(&newparam, 0, sizeof(union parameter));
876 newparam.direction = 0; /* request from app */
877 send_message(MESSAGE_NEWREF, 0, &newparam);
879 call->state = CHAN_LCR_STATE_OUT_PREPARE;
885 static int lcr_call(struct ast_channel *ast, char *dest, int timeout)
887 struct chan_call *call=ast->tech_pvt;
889 if (!call) return -1;
892 char *port_str, *dad, *p;
895 ast_copy_string(buf, dest, sizeof(buf)-1);
897 port_str=strsep(&p, "/");
900 /* send setup message, if we already have a callref */
902 send_setup_to_lcr(call);
905 ast_verbose("Call: ext:%s dest:(%s) -> dad(%s) \n", ast->exten,dest, dad);
907 #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.
912 static int lcr_digit(struct ast_channel *ast, char digit)
916 /* only pass IA5 number space */
917 if (digit > 126 || digit < 32)
920 /* send information or queue them */
921 if (call->ref && call->state == CHAN_LCR_STATE_OUT_DIALING)
923 send_dialing_to_lcr(call);
926 && (call->state == CHAN_LCR_STATE_OUT_PREPARE || call->state == CHAN_LCR_STATE_OUT_SETUP));
929 strncat(call->dialque, buf, strlen(char->dialque)-1);
932 digits kommen, koennen aber nicht verwendet werden.
933 sollen wir sie als info senden (im connect zb.)
937 static int lcr_answer(struct ast_channel *c)
939 struct chan_call *call=c->tech_pvt;
943 static int lcr_hangup(struct ast_channel *ast)
945 <<<<<<< HEAD:chan_lcr.c
946 struct chan_call *call = ast->tech_pvt;
948 struct chan_call *call=c->tech_pvt;
951 >>>>>>> 350450b9cadc6107449fe2630843d4f898f680b7:chan_lcr.c
953 /* disconnect asterisk, maybe not required */
954 ast->tech_pvt = NULL;
958 memset(&newparam, 0, sizeof(union parameter));
959 newparam.disconnectinfo.cause = CAUSE_RESSOURCEUNAVAIL;
960 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
961 send_message(MESSAGE_RELEASE, call->ref, &newparam);
967 /* ref is not set, due to prepare setup or release */
968 if (call->state == CHAN_LCR_STATE_RELEASE)
970 /* we get the response to our release */
974 /* during prepare, we change to release state */
975 call->state = CHAN_LCR_STATE_RELEASE;
980 static int lcr_write(struct ast_channel *c, struct ast_frame *f)
982 struct chan_call *callm= c->tech_pvt;
986 static struct ast_frame *lcr_read(struct ast_channel *c)
988 struct chan_call *call = c->tech_pvt;
991 static int lcr_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen)
996 case AST_CONTROL_BUSY:
997 case AST_CONTROL_CONGESTION:
998 case AST_CONTROL_RINGING:
1003 case AST_CONTROL_VIDUPDATE:
1006 case AST_CONTROL_HOLD:
1007 ast_verbose(" << Console Has Been Placed on Hold >> \n");
1008 //ast_moh_start(c, data, g->mohinterpret);
1010 case AST_CONTROL_UNHOLD:
1011 ast_verbose(" << Console Has Been Retrieved from Hold >> \n");
1016 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name);
1023 static struct ast_channel_tech lcr_tech = {
1025 .description="Channel driver for connecting to Linux-Call-Router",
1026 .capabilities=AST_FORMAT_ALAW,
1027 .requester=lcr_request,
1028 .send_digit=lcr_digit,
1030 // .bridge=lcr_bridge,
1035 .indicate=lcr_indicate,
1036 // .fixup=lcr_fixup,
1037 // .send_text=lcr_send_text,
1041 #warning das muss mal aus der config datei gelesen werden:
1042 char lcr_context[]="from-lcr";
1044 static struct ast_channel *lcr_ast_new(struct chan_call *call, char *exten, char *callerid, int ref)
1046 struct ast_channel *tmp;
1047 char *cid_name = 0, *cid_num = 0;
1051 ast_callerid_parse(callerid, &cid_name, &cid_num);
1053 tmp = ast_channel_alloc(1, AST_STATE_RESERVED, cid_num, cid_name, "", exten, "", 0, "%s/%d", lcr_type, ref);
1056 tmp->tech = &lcr_tech;
1057 tmp->writeformat = AST_FORMAT_ALAW;
1058 tmp->readformat = AST_FORMAT_ALAW;
1060 ast_copy_string(tmp->context, lcr_context, AST_MAX_CONTEXT);
1072 static int lcr_show_lcr (int fd, int argc, char *argv[])
1076 static int lcr_show_calls (int fd, int argc, char *argv[])
1080 static int lcr_reload_routing (int fd, int argc, char *argv[])
1084 static int lcr_reload_interfaces (int fd, int argc, char *argv[])
1088 static int lcr_port_block (int fd, int argc, char *argv[])
1092 static int lcr_port_unblock (int fd, int argc, char *argv[])
1096 static int lcr_port_unload (int fd, int argc, char *argv[])
1100 static struct ast_cli_entry cli_show_lcr =
1101 { {"lcr", "show", "lcr", NULL},
1103 "Shows current states of LCR core",
1104 "Usage: lcr show lcr\n",
1107 static struct ast_cli_entry cli_show_calls =
1108 { {"lcr", "show", "calls", NULL},
1110 "Shows current calls made by LCR and Asterisk",
1111 "Usage: lcr show calls\n",
1114 static struct ast_cli_entry cli_reload_routing =
1115 { {"lcr", "reload", "routing", NULL},
1117 "Reloads routing conf of LCR, current uncomplete calls will be disconnected",
1118 "Usage: lcr reload routing\n",
1121 static struct ast_cli_entry cli_reload_interfaces =
1122 { {"lcr", "reload", "interfaces", NULL},
1123 lcr_reload_interfaces,
1124 "Reloads interfaces conf of LCR",
1125 "Usage: lcr reload interfaces\n",
1128 static struct ast_cli_entry cli_port_block =
1129 { {"lcr", "port", "block", NULL},
1131 "Blocks LCR port for further calls",
1132 "Usage: lcr port block \"<port>\"\n",
1135 static struct ast_cli_entry cli_port_unblock =
1136 { {"lcr", "port", "unblock", NULL},
1138 "Unblocks or loads LCR port, port is opened my mISDN",
1139 "Usage: lcr port unblock \"<port>\"\n",
1142 static struct ast_cli_entry cli_port_unload =
1143 { {"lcr", "port", "unload", NULL},
1145 "Unloads LCR port, port is closes by mISDN",
1146 "Usage: lcr port unload \"<port>\"\n",
1151 * module loading and destruction
1153 int load_module(void)
1155 // ast_mutex_init(&release_lock);
1157 // lcr_cfg_update_ptp();
1159 if (!(lcr_sock = open_socket())) {
1160 ast_log(LOG_ERROR, "Unable to connect\n");
1162 /* continue with closed socket */
1165 if (!bchannel_initialize()) {
1166 ast_log(LOG_ERROR, "Unable to open mISDN device\n");
1171 if (ast_channel_register(&lcr_tech)) {
1172 ast_log(LOG_ERROR, "Unable to register channel class\n");
1177 ast_cli_register(&cli_show_lcr);
1178 ast_cli_register(&cli_show_calls);
1180 ast_cli_register(&cli_reload_routing);
1181 ast_cli_register(&cli_reload_interfaces);
1182 ast_cli_register(&cli_port_block);
1183 ast_cli_register(&cli_port_unblock);
1184 ast_cli_register(&cli_port_unload);
1186 ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
1187 "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
1188 "Sets mISDN opts. and optargs\n"
1190 "The available options are:\n"
1191 " d - Send display text on called phone, text is the optparam\n"
1192 " n - don't detect dtmf tones on called channel\n"
1193 " h - make digital outgoing call\n"
1194 " c - make crypted outgoing call, param is keyindex\n"
1195 " e - perform echo cancelation on this channel,\n"
1196 " takes taps as arguments (32,64,128,256)\n"
1197 " s - send Non Inband DTMF as inband\n"
1198 " vr - rxgain control\n"
1199 " vt - txgain control\n"
1203 lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
1205 chan_lcr_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
1207 //lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
1213 int unload_module(void)
1215 /* First, take us out of the channel loop */
1216 ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
1219 ast_channel_unregister(&lcr_tech);
1221 if (mISDN_created) {
1222 bchannel_deinitialize();
1226 if (lcr_sock >= 0) {
1234 static int reload_module(void)
1241 ast_mutex_t usecnt_lock;
1247 ast_mutex_lock(&usecnt_lock);
1249 ast_mutex_unlock(&usecnt_lock);
1254 char *desc="Channel driver for lcr";
1256 char *description(void)
1263 return ASTERISK_GPL_KEY;
1266 #define AST_MODULE "chan_lcr"
1267 AST_MODULE_INFO(ASTERISK_GPL_KEY,
1268 AST_MODFLAG_DEFAULT,
1269 "Channel driver for LCR",
1270 .load = load_module,
1271 .unload = unload_module,
1272 .reload = reload_module,