|
|
|
@ -9,12 +9,6 @@
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* This program is free software, distributed under the terms of
|
|
|
|
* This program is free software, distributed under the terms of
|
|
|
|
* the GNU General Public License
|
|
|
|
* the GNU General Public License
|
|
|
|
*
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* This module is now being supported by Voicetronix. If you wish to submit
|
|
|
|
|
|
|
|
* any patches to it please email them to support@voicetronix.com.au
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
@ -36,6 +30,7 @@
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include <vpbapi.h>
|
|
|
|
#include <vpbapi.h>
|
|
|
|
|
|
|
|
|
|
|
|
@ -185,6 +180,8 @@ static struct vpb_pvt {
|
|
|
|
|
|
|
|
|
|
|
|
int state; /* used to keep port state (internal to driver) */
|
|
|
|
int state; /* used to keep port state (internal to driver) */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int group; /* Which group this port belongs to */
|
|
|
|
|
|
|
|
|
|
|
|
char dev[256];
|
|
|
|
char dev[256];
|
|
|
|
vpb_model_t vpb_model;
|
|
|
|
vpb_model_t vpb_model;
|
|
|
|
|
|
|
|
|
|
|
|
@ -277,7 +274,6 @@ static int vpb_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
|
|
|
|
ast_log(LOG_WARNING, "Failed to bridge %s and %s!\n", c0->name, c1->name);
|
|
|
|
ast_log(LOG_WARNING, "Failed to bridge %s and %s!\n", c0->name, c1->name);
|
|
|
|
return -2;
|
|
|
|
return -2;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
|
|
/* Set bridge pointers. You don't want to take these locks while holding bridge lock.*/
|
|
|
|
/* Set bridge pointers. You don't want to take these locks while holding bridge lock.*/
|
|
|
|
ast_mutex_lock(&p0->lock); {
|
|
|
|
ast_mutex_lock(&p0->lock); {
|
|
|
|
p0->bridge = &bridges[i];
|
|
|
|
p0->bridge = &bridges[i];
|
|
|
|
@ -406,7 +402,8 @@ static void get_callerid(struct vpb_pvt *p)
|
|
|
|
vpb_sleep(RING_SKIP);
|
|
|
|
vpb_sleep(RING_SKIP);
|
|
|
|
|
|
|
|
|
|
|
|
if (option_verbose>3)
|
|
|
|
if (option_verbose>3)
|
|
|
|
ast_verbose(VERBOSE_PREFIX_4 "CID record - skipped %fms trailing ring\n", get_time_in_ms() - cid_record_time);
|
|
|
|
ast_verbose(VERBOSE_PREFIX_4 "CID record - skipped %fms trailing ring\n",
|
|
|
|
|
|
|
|
get_time_in_ms() - cid_record_time);
|
|
|
|
cid_record_time = get_time_in_ms();
|
|
|
|
cid_record_time = get_time_in_ms();
|
|
|
|
|
|
|
|
|
|
|
|
// Record bit between the rings which contains the callerid
|
|
|
|
// Record bit between the rings which contains the callerid
|
|
|
|
@ -416,7 +413,8 @@ static void get_callerid(struct vpb_pvt *p)
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
if (option_verbose>3)
|
|
|
|
if (option_verbose>3)
|
|
|
|
ast_verbose(VERBOSE_PREFIX_4 "CID record - recorded %fms between rings\n", get_time_in_ms() - cid_record_time);
|
|
|
|
ast_verbose(VERBOSE_PREFIX_4 "CID record - recorded %fms between rings\n",
|
|
|
|
|
|
|
|
get_time_in_ms() - cid_record_time);
|
|
|
|
|
|
|
|
|
|
|
|
ast_mutex_unlock(&p->record_lock);
|
|
|
|
ast_mutex_unlock(&p->record_lock);
|
|
|
|
|
|
|
|
|
|
|
|
@ -427,7 +425,8 @@ static void get_callerid(struct vpb_pvt *p)
|
|
|
|
|
|
|
|
|
|
|
|
// This decodes FSK 1200baud type callerid
|
|
|
|
// This decodes FSK 1200baud type callerid
|
|
|
|
if ((rc=vpb_cid_decode(callerid, buf, CID_MSECS*8)) == VPB_OK ) {
|
|
|
|
if ((rc=vpb_cid_decode(callerid, buf, CID_MSECS*8)) == VPB_OK ) {
|
|
|
|
if(!*callerid) strcpy(callerid,"undisclosed"); // blocked CID (eg caller used 1831)
|
|
|
|
if(!*callerid)
|
|
|
|
|
|
|
|
strcpy(callerid,"undisclosed"); // blocked CID (eg caller used 1831)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
ast_log(LOG_ERROR, "Failed to decode caller id on %s - %s\n", p->dev, vpb_strerror(rc) );
|
|
|
|
ast_log(LOG_ERROR, "Failed to decode caller id on %s - %s\n", p->dev, vpb_strerror(rc) );
|
|
|
|
strcpy(callerid,"unknown");
|
|
|
|
strcpy(callerid,"unknown");
|
|
|
|
@ -471,9 +470,11 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e)
|
|
|
|
} else
|
|
|
|
} else
|
|
|
|
f.frametype = -1; /* ignore ring on station port. */
|
|
|
|
f.frametype = -1; /* ignore ring on station port. */
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case VPB_RING_OFF:
|
|
|
|
case VPB_RING_OFF:
|
|
|
|
f.frametype = -1;
|
|
|
|
f.frametype = -1;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case VPB_TIMEREXP:
|
|
|
|
case VPB_TIMEREXP:
|
|
|
|
if (e->data == p->busy_timer_id) {
|
|
|
|
if (e->data == p->busy_timer_id) {
|
|
|
|
playtone(p->handle,&Busytone);
|
|
|
|
playtone(p->handle,&Busytone);
|
|
|
|
@ -488,6 +489,7 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e)
|
|
|
|
f.frametype = -1; /* Ignore. */
|
|
|
|
f.frametype = -1; /* Ignore. */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case VPB_DTMF:
|
|
|
|
case VPB_DTMF:
|
|
|
|
if (p->owner->_state == AST_STATE_UP) {
|
|
|
|
if (p->owner->_state == AST_STATE_UP) {
|
|
|
|
f.frametype = AST_FRAME_DTMF;
|
|
|
|
f.frametype = AST_FRAME_DTMF;
|
|
|
|
@ -509,7 +511,8 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e)
|
|
|
|
if( ( get_time_in_ms() - p->lastgrunt ) > gruntdetect_timeout ) {
|
|
|
|
if( ( get_time_in_ms() - p->lastgrunt ) > gruntdetect_timeout ) {
|
|
|
|
// Nothing heard on line for a very long time
|
|
|
|
// Nothing heard on line for a very long time
|
|
|
|
// Timeout connection
|
|
|
|
// Timeout connection
|
|
|
|
if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "grunt timeout\n");
|
|
|
|
if (option_verbose > 2)
|
|
|
|
|
|
|
|
ast_verbose(VERBOSE_PREFIX_3 "grunt timeout\n");
|
|
|
|
ast_log(LOG_NOTICE,"Line hangup due of lack of conversation\n");
|
|
|
|
ast_log(LOG_NOTICE,"Line hangup due of lack of conversation\n");
|
|
|
|
f.subclass = AST_CONTROL_HANGUP;
|
|
|
|
f.subclass = AST_CONTROL_HANGUP;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
@ -524,11 +527,9 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e)
|
|
|
|
#ifdef DIAL_WITH_CALL_PROGRESS
|
|
|
|
#ifdef DIAL_WITH_CALL_PROGRESS
|
|
|
|
if (e->data == VPB_CALL_CONNECTED)
|
|
|
|
if (e->data == VPB_CALL_CONNECTED)
|
|
|
|
f.subclass = AST_CONTROL_ANSWER;
|
|
|
|
f.subclass = AST_CONTROL_ANSWER;
|
|
|
|
else if (e->data == VPB_CALL_NO_DIAL_TONE ||
|
|
|
|
else if (e->data == VPB_CALL_NO_DIAL_TONE || e->data == VPB_CALL_NO_RING_BACK)
|
|
|
|
e->data == VPB_CALL_NO_RING_BACK)
|
|
|
|
|
|
|
|
f.subclass = AST_CONTROL_CONGESTION;
|
|
|
|
f.subclass = AST_CONTROL_CONGESTION;
|
|
|
|
else if (e->data == VPB_CALL_NO_ANSWER ||
|
|
|
|
else if (e->data == VPB_CALL_NO_ANSWER || e->data == VPB_CALL_BUSY)
|
|
|
|
e->data == VPB_CALL_BUSY)
|
|
|
|
|
|
|
|
f.subclass = AST_CONTROL_BUSY;
|
|
|
|
f.subclass = AST_CONTROL_BUSY;
|
|
|
|
else if (e->data == VPB_CALL_DISCONNECTED)
|
|
|
|
else if (e->data == VPB_CALL_DISCONNECTED)
|
|
|
|
f.subclass = AST_CONTROL_HANGUP;
|
|
|
|
f.subclass = AST_CONTROL_HANGUP;
|
|
|
|
@ -541,6 +542,7 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e)
|
|
|
|
case VPB_STATION_OFFHOOK:
|
|
|
|
case VPB_STATION_OFFHOOK:
|
|
|
|
f.subclass = AST_CONTROL_ANSWER;
|
|
|
|
f.subclass = AST_CONTROL_ANSWER;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
/* not sure why this was commented out */
|
|
|
|
/* not sure why this was commented out */
|
|
|
|
case VPB_DROP:
|
|
|
|
case VPB_DROP:
|
|
|
|
if (p->mode == MODE_FXO){ /* ignore loop drop on stations */
|
|
|
|
if (p->mode == MODE_FXO){ /* ignore loop drop on stations */
|
|
|
|
@ -608,8 +610,8 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e)
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
endbridge = 1;
|
|
|
|
endbridge = 1;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (endbridge) {
|
|
|
|
if (endbridge) {
|
|
|
|
@ -659,8 +661,10 @@ static inline int monitor_handle_notowned(struct vpb_pvt *p, VPB_EVENT *e)
|
|
|
|
get_callerid(p); /* Australian Caller ID only between 1st and 2nd ring */
|
|
|
|
get_callerid(p); /* Australian Caller ID only between 1st and 2nd ring */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case VPB_RING_OFF:
|
|
|
|
case VPB_RING_OFF:
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case VPB_STATION_OFFHOOK:
|
|
|
|
case VPB_STATION_OFFHOOK:
|
|
|
|
if (p->mode == MODE_IMMEDIATE)
|
|
|
|
if (p->mode == MODE_IMMEDIATE)
|
|
|
|
vpb_new(p,AST_STATE_RING, p->context);
|
|
|
|
vpb_new(p,AST_STATE_RING, p->context);
|
|
|
|
@ -672,6 +676,7 @@ static inline int monitor_handle_notowned(struct vpb_pvt *p, VPB_EVENT *e)
|
|
|
|
p->state=VPB_STATE_PLAYDIAL;
|
|
|
|
p->state=VPB_STATE_PLAYDIAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case VPB_DIALEND:
|
|
|
|
case VPB_DIALEND:
|
|
|
|
if (p->mode == MODE_DIALTONE){
|
|
|
|
if (p->mode == MODE_DIALTONE){
|
|
|
|
if (p->state == VPB_STATE_PLAYDIAL) {
|
|
|
|
if (p->state == VPB_STATE_PLAYDIAL) {
|
|
|
|
@ -709,7 +714,6 @@ static inline int monitor_handle_notowned(struct vpb_pvt *p, VPB_EVENT *e)
|
|
|
|
p->state=VPB_STATE_GETDTMF;
|
|
|
|
p->state=VPB_STATE_GETDTMF;
|
|
|
|
s[0] = e->data;
|
|
|
|
s[0] = e->data;
|
|
|
|
strcat(p->ext, s);
|
|
|
|
strcat(p->ext, s);
|
|
|
|
|
|
|
|
|
|
|
|
if (ast_exists_extension(NULL, p->context, p->ext, 1, p->callerid))
|
|
|
|
if (ast_exists_extension(NULL, p->context, p->ext, 1, p->callerid))
|
|
|
|
vpb_new(p,AST_STATE_RING, p->context);
|
|
|
|
vpb_new(p,AST_STATE_RING, p->context);
|
|
|
|
else if (!ast_canmatch_extension(NULL, p->context, p->ext, 1, p->callerid))
|
|
|
|
else if (!ast_canmatch_extension(NULL, p->context, p->ext, 1, p->callerid))
|
|
|
|
@ -717,14 +721,12 @@ static inline int monitor_handle_notowned(struct vpb_pvt *p, VPB_EVENT *e)
|
|
|
|
vpb_new(p,AST_STATE_RING, "default");
|
|
|
|
vpb_new(p,AST_STATE_RING, "default");
|
|
|
|
else if (!ast_canmatch_extension(NULL, "default", p->ext, 1, p->callerid)) {
|
|
|
|
else if (!ast_canmatch_extension(NULL, "default", p->ext, 1, p->callerid)) {
|
|
|
|
if (option_debug)
|
|
|
|
if (option_debug)
|
|
|
|
ast_log(LOG_DEBUG,
|
|
|
|
ast_log(LOG_DEBUG, "%s can't match anything in %s or default\n",
|
|
|
|
"%s can't match anything in %s or default\n",
|
|
|
|
|
|
|
|
p->ext, p->context);
|
|
|
|
p->ext, p->context);
|
|
|
|
playtone(p->handle, &Busytone);
|
|
|
|
playtone(p->handle, &Busytone);
|
|
|
|
vpb_timer_start(p->busy_timer);
|
|
|
|
vpb_timer_start(p->busy_timer);
|
|
|
|
p->state = VPB_STATE_PLAYBUSY;
|
|
|
|
p->state = VPB_STATE_PLAYBUSY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
@ -751,7 +753,6 @@ static void *do_monitor(void *unused)
|
|
|
|
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
|
|
|
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
|
|
|
|
|
|
|
|
|
|
|
for(;;) {
|
|
|
|
for(;;) {
|
|
|
|
|
|
|
|
|
|
|
|
VPB_EVENT e;
|
|
|
|
VPB_EVENT e;
|
|
|
|
VPB_EVENT je;
|
|
|
|
VPB_EVENT je;
|
|
|
|
char str[VPB_MAX_STR];
|
|
|
|
char str[VPB_MAX_STR];
|
|
|
|
@ -775,7 +776,6 @@ static void *do_monitor(void *unused)
|
|
|
|
p = NULL;
|
|
|
|
p = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
ast_mutex_lock(&monlock); {
|
|
|
|
ast_mutex_lock(&monlock); {
|
|
|
|
|
|
|
|
|
|
|
|
vpb_translate_event(&e, str);
|
|
|
|
vpb_translate_event(&e, str);
|
|
|
|
|
|
|
|
|
|
|
|
if (e.type == VPB_NULL_EVENT) {
|
|
|
|
if (e.type == VPB_NULL_EVENT) {
|
|
|
|
@ -796,7 +796,6 @@ static void *do_monitor(void *unused)
|
|
|
|
if (p && (option_verbose > 3))
|
|
|
|
if (p && (option_verbose > 3))
|
|
|
|
ast_verbose(VERBOSE_PREFIX_4 "Event [%d=>%s] on %s\n",
|
|
|
|
ast_verbose(VERBOSE_PREFIX_4 "Event [%d=>%s] on %s\n",
|
|
|
|
e.type, str, p ? p->dev : "null");
|
|
|
|
e.type, str, p ? p->dev : "null");
|
|
|
|
|
|
|
|
|
|
|
|
done: (void)0;
|
|
|
|
done: (void)0;
|
|
|
|
|
|
|
|
|
|
|
|
} ast_mutex_unlock(&monlock);
|
|
|
|
} ast_mutex_unlock(&monlock);
|
|
|
|
@ -856,7 +855,6 @@ static int restart_monitor(void)
|
|
|
|
ast_verbose(VERBOSE_PREFIX_4 "Trying to reawake monitor\n");
|
|
|
|
ast_verbose(VERBOSE_PREFIX_4 "Trying to reawake monitor\n");
|
|
|
|
|
|
|
|
|
|
|
|
vpb_put_event(&e);
|
|
|
|
vpb_put_event(&e);
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
/* Start a new monitor */
|
|
|
|
/* Start a new monitor */
|
|
|
|
int pid = pthread_create(&monitor_thread, NULL, do_monitor, NULL);
|
|
|
|
int pid = pthread_create(&monitor_thread, NULL, do_monitor, NULL);
|
|
|
|
@ -885,8 +883,10 @@ static void mkbrd(vpb_model_t model, int echo_cancel)
|
|
|
|
if(model==vpb_model_v4pci)
|
|
|
|
if(model==vpb_model_v4pci)
|
|
|
|
max_bridges = MAX_BRIDGES_V4PCI;
|
|
|
|
max_bridges = MAX_BRIDGES_V4PCI;
|
|
|
|
bridges = (vpb_bridge_t *)malloc(max_bridges * sizeof(vpb_bridge_t) );
|
|
|
|
bridges = (vpb_bridge_t *)malloc(max_bridges * sizeof(vpb_bridge_t) );
|
|
|
|
if(!bridges) ast_log(LOG_ERROR, "Failed to initialize bridges\n");
|
|
|
|
if(!bridges)
|
|
|
|
else memset(bridges,0,max_bridges * sizeof(vpb_bridge_t));
|
|
|
|
ast_log(LOG_ERROR, "Failed to initialize bridges\n");
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
memset(bridges,0,max_bridges * sizeof(vpb_bridge_t));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!echo_cancel) {
|
|
|
|
if(!echo_cancel) {
|
|
|
|
if (model==vpb_model_v4pci) {
|
|
|
|
if (model==vpb_model_v4pci) {
|
|
|
|
@ -909,7 +909,7 @@ static void mkbrd(vpb_model_t model, int echo_cancel)
|
|
|
|
|
|
|
|
|
|
|
|
struct vpb_pvt *mkif(int board, int channel, int mode, float txgain, float rxgain,
|
|
|
|
struct vpb_pvt *mkif(int board, int channel, int mode, float txgain, float rxgain,
|
|
|
|
float txswgain, float rxswgain, int bal1, int bal2, int bal3,
|
|
|
|
float txswgain, float rxswgain, int bal1, int bal2, int bal3,
|
|
|
|
char * callerid, int echo_cancel )
|
|
|
|
char * callerid, int echo_cancel, int group )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct vpb_pvt *tmp;
|
|
|
|
struct vpb_pvt *tmp;
|
|
|
|
char buf[64];
|
|
|
|
char buf[64];
|
|
|
|
@ -932,6 +932,8 @@ struct vpb_pvt *mkif(int board, int channel, int mode, float txgain, float rxgai
|
|
|
|
|
|
|
|
|
|
|
|
tmp->mode = mode;
|
|
|
|
tmp->mode = mode;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tmp->group = group;
|
|
|
|
|
|
|
|
|
|
|
|
strcpy(tmp->language, language);
|
|
|
|
strcpy(tmp->language, language);
|
|
|
|
strcpy(tmp->context, context);
|
|
|
|
strcpy(tmp->context, context);
|
|
|
|
|
|
|
|
|
|
|
|
@ -1010,8 +1012,7 @@ static int vpb_indicate(struct ast_channel *ast, int condition)
|
|
|
|
int res = 0;
|
|
|
|
int res = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (option_verbose > 3)
|
|
|
|
if (option_verbose > 3)
|
|
|
|
ast_verbose(VERBOSE_PREFIX_4 " vpb indicate on %s with %d\n",
|
|
|
|
ast_verbose(VERBOSE_PREFIX_4 " vpb indicate on %s with %d\n", p->dev, condition);
|
|
|
|
p->dev, condition);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch(condition) {
|
|
|
|
switch(condition) {
|
|
|
|
case AST_CONTROL_BUSY:
|
|
|
|
case AST_CONTROL_BUSY:
|
|
|
|
@ -1102,8 +1103,10 @@ static int vpb_call(struct ast_channel *ast, char *dest, int timeout)
|
|
|
|
VPB_CALL call;
|
|
|
|
VPB_CALL call;
|
|
|
|
|
|
|
|
|
|
|
|
// Dial must timeout or it can leave channels unuseable
|
|
|
|
// Dial must timeout or it can leave channels unuseable
|
|
|
|
if( timeout == 0 ) timeout = TIMER_PERIOD_NOANSWER;
|
|
|
|
if( timeout == 0 )
|
|
|
|
else timeout = timeout * 1000; //convert from secs to ms.
|
|
|
|
timeout = TIMER_PERIOD_NOANSWER;
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
timeout = timeout * 1000; //convert from secs to ms.
|
|
|
|
|
|
|
|
|
|
|
|
// These timeouts are only used with call progress dialing
|
|
|
|
// These timeouts are only used with call progress dialing
|
|
|
|
call.dialtones = 1; // Number of dialtones to get outside line
|
|
|
|
call.dialtones = 1; // Number of dialtones to get outside line
|
|
|
|
@ -1115,8 +1118,7 @@ static int vpb_call(struct ast_channel *ast, char *dest, int timeout)
|
|
|
|
vpb_set_call(p->handle, &call);
|
|
|
|
vpb_set_call(p->handle, &call);
|
|
|
|
|
|
|
|
|
|
|
|
if (option_verbose > 1)
|
|
|
|
if (option_verbose > 1)
|
|
|
|
ast_verbose(VERBOSE_PREFIX_2 "Calling %s on %s \n",
|
|
|
|
ast_verbose(VERBOSE_PREFIX_2 "Calling %s on %s \n", s, ast->name);
|
|
|
|
s, ast->name);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (option_verbose > 2) {
|
|
|
|
if (option_verbose > 2) {
|
|
|
|
int j;
|
|
|
|
int j;
|
|
|
|
@ -1139,18 +1141,14 @@ static int vpb_call(struct ast_channel *ast, char *dest, int timeout)
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
if (res != VPB_OK) {
|
|
|
|
if (res != VPB_OK) {
|
|
|
|
ast_log(LOG_DEBUG, "Call on %s to %s failed: %s\n",
|
|
|
|
ast_log(LOG_DEBUG, "Call on %s to %s failed: %s\n", ast->name, s, vpb_strerror(res));
|
|
|
|
ast->name, s, vpb_strerror(res));
|
|
|
|
|
|
|
|
res = -1;
|
|
|
|
res = -1;
|
|
|
|
} else
|
|
|
|
} else
|
|
|
|
res = 0;
|
|
|
|
res = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (option_verbose > 2)
|
|
|
|
if (option_verbose > 2)
|
|
|
|
ast_verbose(VERBOSE_PREFIX_3
|
|
|
|
ast_verbose(VERBOSE_PREFIX_3 " VPB Calling %s [t=%d] on %s returned %d\n", s, timeout, ast->name, res);
|
|
|
|
" VPB Calling %s [t=%d] on %s returned %d\n",
|
|
|
|
|
|
|
|
s, timeout, ast->name, res);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (res == 0) {
|
|
|
|
if (res == 0) {
|
|
|
|
ast_setstate(ast, AST_STATE_RINGING);
|
|
|
|
ast_setstate(ast, AST_STATE_RINGING);
|
|
|
|
ast_queue_control(ast,AST_CONTROL_RINGING, 0);
|
|
|
|
ast_queue_control(ast,AST_CONTROL_RINGING, 0);
|
|
|
|
@ -1196,7 +1194,6 @@ static int vpb_hangup(struct ast_channel *ast)
|
|
|
|
vpb_ring_station_async(p->handle, VPB_RING_STATION_OFF,0);
|
|
|
|
vpb_ring_station_async(p->handle, VPB_RING_STATION_OFF,0);
|
|
|
|
playtone(p->handle, &Busytone);
|
|
|
|
playtone(p->handle, &Busytone);
|
|
|
|
p->state = VPB_STATE_PLAYBUSY;
|
|
|
|
p->state = VPB_STATE_PLAYBUSY;
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
stoptone(p->handle); // Terminates any dialing
|
|
|
|
stoptone(p->handle); // Terminates any dialing
|
|
|
|
vpb_sethook_sync(p->handle, VPB_ONHOOK);
|
|
|
|
vpb_sethook_sync(p->handle, VPB_ONHOOK);
|
|
|
|
@ -1223,7 +1220,6 @@ static int vpb_hangup(struct ast_channel *ast)
|
|
|
|
ast_verbose(VERBOSE_PREFIX_2 "Hangup on %s complete\n", ast->name);
|
|
|
|
ast_verbose(VERBOSE_PREFIX_2 "Hangup on %s complete\n", ast->name);
|
|
|
|
|
|
|
|
|
|
|
|
restart_monitor();
|
|
|
|
restart_monitor();
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -1238,9 +1234,7 @@ static int vpb_answer(struct ast_channel *ast)
|
|
|
|
ast_verbose( VERBOSE_PREFIX_2 "Answered call from %s on %s\n", p->owner->callerid, ast->name);
|
|
|
|
ast_verbose( VERBOSE_PREFIX_2 "Answered call from %s on %s\n", p->owner->callerid, ast->name);
|
|
|
|
|
|
|
|
|
|
|
|
ast->rings = 0;
|
|
|
|
ast->rings = 0;
|
|
|
|
|
|
|
|
|
|
|
|
pthread_create(&p->readthread, NULL, do_chanreads, (void *)p);
|
|
|
|
pthread_create(&p->readthread, NULL, do_chanreads, (void *)p);
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -1257,7 +1251,6 @@ static struct ast_frame *vpb_read(struct ast_channel *ast)
|
|
|
|
|
|
|
|
|
|
|
|
static inline int ast2vpbformat(int ast_format)
|
|
|
|
static inline int ast2vpbformat(int ast_format)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
switch(ast_format) {
|
|
|
|
switch(ast_format) {
|
|
|
|
case AST_FORMAT_ALAW:
|
|
|
|
case AST_FORMAT_ALAW:
|
|
|
|
return VPB_ALAW;
|
|
|
|
return VPB_ALAW;
|
|
|
|
@ -1266,7 +1259,6 @@ static inline int ast2vpbformat(int ast_format)
|
|
|
|
case AST_FORMAT_ULAW:
|
|
|
|
case AST_FORMAT_ULAW:
|
|
|
|
return VPB_MULAW;
|
|
|
|
return VPB_MULAW;
|
|
|
|
case AST_FORMAT_ADPCM:
|
|
|
|
case AST_FORMAT_ADPCM:
|
|
|
|
|
|
|
|
|
|
|
|
return VPB_OKIADPCM;
|
|
|
|
return VPB_OKIADPCM;
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
@ -1275,7 +1267,6 @@ static inline int ast2vpbformat(int ast_format)
|
|
|
|
|
|
|
|
|
|
|
|
static inline int astformatbits(int ast_format)
|
|
|
|
static inline int astformatbits(int ast_format)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
switch(ast_format) {
|
|
|
|
switch(ast_format) {
|
|
|
|
case AST_FORMAT_ALAW:
|
|
|
|
case AST_FORMAT_ALAW:
|
|
|
|
case AST_FORMAT_ULAW:
|
|
|
|
case AST_FORMAT_ULAW:
|
|
|
|
@ -1309,18 +1300,18 @@ static int vpb_write(struct ast_channel *ast, struct ast_frame *frame)
|
|
|
|
int res = 0, fmt = 0;
|
|
|
|
int res = 0, fmt = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (frame->frametype != AST_FRAME_VOICE) {
|
|
|
|
if (frame->frametype != AST_FRAME_VOICE) {
|
|
|
|
if(option_verbose>3) ast_verbose( VERBOSE_PREFIX_4 "Don't know how to handle from type %d\n", frame->frametype);
|
|
|
|
if(option_verbose>3)
|
|
|
|
|
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "Don't know how to handle from type %d\n", frame->frametype);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
} else if (ast->_state != AST_STATE_UP) {
|
|
|
|
} else if (ast->_state != AST_STATE_UP) {
|
|
|
|
if(option_verbose>3) ast_verbose( VERBOSE_PREFIX_4 "Writing frame type [%d,%d] on chan %s not up\n",
|
|
|
|
if(option_verbose>3)
|
|
|
|
frame->frametype, frame->subclass, ast->name);
|
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "Writing frame type [%d,%d] on chan %s not up\n", frame->frametype, frame->subclass, ast->name);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fmt = ast2vpbformat(frame->subclass);
|
|
|
|
fmt = ast2vpbformat(frame->subclass);
|
|
|
|
if (fmt < 0) {
|
|
|
|
if (fmt < 0) {
|
|
|
|
ast_log(LOG_WARNING, "vpb_write Cannot handle frames of %d format!\n",
|
|
|
|
ast_log(LOG_WARNING, "vpb_write Cannot handle frames of %d format!\n", frame->subclass);
|
|
|
|
frame->subclass);
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -1350,7 +1341,6 @@ static int vpb_write(struct ast_channel *ast, struct ast_frame *frame)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ast_mutex_unlock(&p->play_lock);
|
|
|
|
ast_mutex_unlock(&p->play_lock);
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -1378,17 +1368,16 @@ static void *do_chanreads(void *pvt)
|
|
|
|
while (!p->stopreads && p->owner) {
|
|
|
|
while (!p->stopreads && p->owner) {
|
|
|
|
|
|
|
|
|
|
|
|
ast_mutex_lock(&p->lock); {
|
|
|
|
ast_mutex_lock(&p->lock); {
|
|
|
|
if (p->bridge)
|
|
|
|
if (p->bridge) {
|
|
|
|
if (p->bridge->c0 == p->owner &&
|
|
|
|
if (p->bridge->c0 == p->owner && (p->bridge->flags & AST_BRIDGE_REC_CHANNEL_0))
|
|
|
|
(p->bridge->flags & AST_BRIDGE_REC_CHANNEL_0))
|
|
|
|
|
|
|
|
bridgerec = 1;
|
|
|
|
bridgerec = 1;
|
|
|
|
else if (p->bridge->c1 == p->owner &&
|
|
|
|
else if (p->bridge->c1 == p->owner && (p->bridge->flags & AST_BRIDGE_REC_CHANNEL_1))
|
|
|
|
(p->bridge->flags & AST_BRIDGE_REC_CHANNEL_1))
|
|
|
|
|
|
|
|
bridgerec = 1;
|
|
|
|
bridgerec = 1;
|
|
|
|
else
|
|
|
|
else
|
|
|
|
bridgerec = 0;
|
|
|
|
bridgerec = 0;
|
|
|
|
else
|
|
|
|
} else {
|
|
|
|
bridgerec = 1;
|
|
|
|
bridgerec = 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
} ast_mutex_unlock(&p->lock);
|
|
|
|
} ast_mutex_unlock(&p->lock);
|
|
|
|
|
|
|
|
|
|
|
|
if ( (p->owner->_state != AST_STATE_UP) || !bridgerec) {
|
|
|
|
if ( (p->owner->_state != AST_STATE_UP) || !bridgerec) {
|
|
|
|
@ -1419,14 +1408,16 @@ static void *do_chanreads(void *pvt)
|
|
|
|
if( p->play_dtmf[0] ) {
|
|
|
|
if( p->play_dtmf[0] ) {
|
|
|
|
// Try to ignore DTMF event we get after playing digit
|
|
|
|
// Try to ignore DTMF event we get after playing digit
|
|
|
|
// This DTMF is played by asterisk and leads to an annoying trailing beep on CISCO phones
|
|
|
|
// This DTMF is played by asterisk and leads to an annoying trailing beep on CISCO phones
|
|
|
|
if( !ignore_dtmf) vpb_set_event_mask(p->handle, VPB_EVENTS_NODTMF );
|
|
|
|
if( !ignore_dtmf)
|
|
|
|
|
|
|
|
vpb_set_event_mask(p->handle, VPB_EVENTS_NODTMF );
|
|
|
|
vpb_dial_sync(p->handle,p->play_dtmf);
|
|
|
|
vpb_dial_sync(p->handle,p->play_dtmf);
|
|
|
|
if(option_verbose>1)
|
|
|
|
if(option_verbose>1)
|
|
|
|
ast_verbose( VERBOSE_PREFIX_2 "Played on %s DTMF %s\n",p->dev,p->play_dtmf);
|
|
|
|
ast_verbose( VERBOSE_PREFIX_2 "Played on %s DTMF %s\n",p->dev,p->play_dtmf);
|
|
|
|
p->play_dtmf[0] = '\0';
|
|
|
|
p->play_dtmf[0] = '\0';
|
|
|
|
ast_mutex_unlock(&p->play_dtmf_lock);
|
|
|
|
ast_mutex_unlock(&p->play_dtmf_lock);
|
|
|
|
vpb_sleep(700); // Long enough to miss echo and DTMF event
|
|
|
|
vpb_sleep(700); // Long enough to miss echo and DTMF event
|
|
|
|
if( !ignore_dtmf) vpb_set_event_mask(p->handle, VPB_EVENTS_ALL );
|
|
|
|
if( !ignore_dtmf)
|
|
|
|
|
|
|
|
vpb_set_event_mask(p->handle, VPB_EVENTS_ALL );
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ast_mutex_unlock(&p->play_dtmf_lock);
|
|
|
|
ast_mutex_unlock(&p->play_dtmf_lock);
|
|
|
|
@ -1454,7 +1445,6 @@ static void *do_chanreads(void *pvt)
|
|
|
|
|
|
|
|
|
|
|
|
/* Read only if up and not bridged, or a bridge for which we can read. */
|
|
|
|
/* Read only if up and not bridged, or a bridge for which we can read. */
|
|
|
|
if( (res = vpb_record_buf_sync(p->handle, readbuf, readlen) ) == VPB_OK ) {
|
|
|
|
if( (res = vpb_record_buf_sync(p->handle, readbuf, readlen) ) == VPB_OK ) {
|
|
|
|
|
|
|
|
|
|
|
|
// Apply extra gain !
|
|
|
|
// Apply extra gain !
|
|
|
|
if( p->rxswgain > MAX_VPB_GAIN )
|
|
|
|
if( p->rxswgain > MAX_VPB_GAIN )
|
|
|
|
gain_vector(p->rxswgain - MAX_VPB_GAIN , (short*)readbuf, readlen/sizeof(short));
|
|
|
|
gain_vector(p->rxswgain - MAX_VPB_GAIN , (short*)readbuf, readlen/sizeof(short));
|
|
|
|
@ -1478,18 +1468,15 @@ static void *do_chanreads(void *pvt)
|
|
|
|
vpb_record_buf_finish(p->handle);
|
|
|
|
vpb_record_buf_finish(p->handle);
|
|
|
|
vpb_record_buf_start(p->handle, fmt);
|
|
|
|
vpb_record_buf_start(p->handle, fmt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* When stopreads seen, go away! */
|
|
|
|
/* When stopreads seen, go away! */
|
|
|
|
vpb_record_buf_finish(p->handle);
|
|
|
|
vpb_record_buf_finish(p->handle);
|
|
|
|
|
|
|
|
|
|
|
|
ast_mutex_unlock(&p->record_lock);
|
|
|
|
ast_mutex_unlock(&p->record_lock);
|
|
|
|
|
|
|
|
|
|
|
|
if (option_verbose > 1)
|
|
|
|
if (option_verbose > 1)
|
|
|
|
ast_verbose(VERBOSE_PREFIX_2 "Ending record mode on %s (%d/%s)\n",
|
|
|
|
ast_verbose(VERBOSE_PREFIX_2 "Ending record mode on %s (%d/%s)\n",
|
|
|
|
p->dev, p->stopreads, p->owner? "yes" : "no");
|
|
|
|
p->dev, p->stopreads, p->owner? "yes" : "no");
|
|
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -1550,13 +1537,15 @@ static struct ast_channel *vpb_new(struct vpb_pvt *i, int state, char *context)
|
|
|
|
usecnt++;
|
|
|
|
usecnt++;
|
|
|
|
ast_mutex_unlock(&usecnt_lock);
|
|
|
|
ast_mutex_unlock(&usecnt_lock);
|
|
|
|
ast_update_use_count();
|
|
|
|
ast_update_use_count();
|
|
|
|
if (state != AST_STATE_DOWN)
|
|
|
|
if (state != AST_STATE_DOWN) {
|
|
|
|
if (ast_pbx_start(tmp)) {
|
|
|
|
if (ast_pbx_start(tmp)) {
|
|
|
|
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
|
|
|
|
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
|
|
|
|
ast_hangup(tmp);
|
|
|
|
ast_hangup(tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
|
|
|
|
ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
|
|
|
|
|
|
|
|
}
|
|
|
|
return tmp;
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -1567,6 +1556,7 @@ static struct ast_channel *vpb_request(char *type, int format, void *data)
|
|
|
|
struct ast_channel *tmp = NULL;
|
|
|
|
struct ast_channel *tmp = NULL;
|
|
|
|
char *name = strdup(data ? (char *)data : "");
|
|
|
|
char *name = strdup(data ? (char *)data : "");
|
|
|
|
char *s, *sepstr;
|
|
|
|
char *s, *sepstr;
|
|
|
|
|
|
|
|
int group=-1;
|
|
|
|
|
|
|
|
|
|
|
|
oldformat = format;
|
|
|
|
oldformat = format;
|
|
|
|
format &= prefformat;
|
|
|
|
format &= prefformat;
|
|
|
|
@ -1579,15 +1569,28 @@ static struct ast_channel *vpb_request(char *type, int format, void *data)
|
|
|
|
s = strsep(&sepstr, "/"); /* Handle / issues */
|
|
|
|
s = strsep(&sepstr, "/"); /* Handle / issues */
|
|
|
|
if (!s)
|
|
|
|
if (!s)
|
|
|
|
s = "";
|
|
|
|
s = "";
|
|
|
|
|
|
|
|
/* Check if we are looking for a group */
|
|
|
|
|
|
|
|
if (toupper(name[0]) == 'G' || toupper(name[0])=='R') {
|
|
|
|
|
|
|
|
group=atoi(name+1);
|
|
|
|
|
|
|
|
}
|
|
|
|
/* Search for an unowned channel */
|
|
|
|
/* Search for an unowned channel */
|
|
|
|
ast_mutex_lock(&iflock); {
|
|
|
|
ast_mutex_lock(&iflock); {
|
|
|
|
p = iflist;
|
|
|
|
p = iflist;
|
|
|
|
while(p) {
|
|
|
|
while(p) {
|
|
|
|
if (strncmp(s, p->dev + 4, sizeof p->dev) == 0)
|
|
|
|
if (group == -1){
|
|
|
|
|
|
|
|
if (strncmp(s, p->dev + 4, sizeof p->dev) == 0) {
|
|
|
|
if (!p->owner) {
|
|
|
|
if (!p->owner) {
|
|
|
|
tmp = vpb_new(p, AST_STATE_DOWN, p->context);
|
|
|
|
tmp = vpb_new(p, AST_STATE_DOWN, p->context);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
|
|
|
if ((p->group == group) && (!p->owner)) {
|
|
|
|
|
|
|
|
tmp = vpb_new(p, AST_STATE_DOWN, p->context);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
p = p->next;
|
|
|
|
p = p->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} ast_mutex_unlock(&iflock);
|
|
|
|
} ast_mutex_unlock(&iflock);
|
|
|
|
@ -1610,8 +1613,7 @@ static float parse_gain_value(char *gain_type, char *value)
|
|
|
|
/* try to scan number */
|
|
|
|
/* try to scan number */
|
|
|
|
if (sscanf(value, "%f", &gain) != 1)
|
|
|
|
if (sscanf(value, "%f", &gain) != 1)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n",
|
|
|
|
ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n", value, gain_type, config);
|
|
|
|
value, gain_type, config);
|
|
|
|
|
|
|
|
return DEFAULT_GAIN;
|
|
|
|
return DEFAULT_GAIN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -1660,7 +1662,7 @@ int load_module()
|
|
|
|
group = atoi(v->value);
|
|
|
|
group = atoi(v->value);
|
|
|
|
else if (strcasecmp(v->name, "channel") == 0) {
|
|
|
|
else if (strcasecmp(v->name, "channel") == 0) {
|
|
|
|
int channel = atoi(v->value);
|
|
|
|
int channel = atoi(v->value);
|
|
|
|
tmp = mkif(board, channel, mode, txgain, rxgain, txswgain, rxswgain, bal1, bal2, bal3, callerid, echo_cancel);
|
|
|
|
tmp = mkif(board, channel, mode, txgain, rxgain, txswgain, rxswgain, bal1, bal2, bal3, callerid, echo_cancel,group);
|
|
|
|
if (tmp) {
|
|
|
|
if (tmp) {
|
|
|
|
if(first_channel) {
|
|
|
|
if(first_channel) {
|
|
|
|
mkbrd( tmp->vpb_model, echo_cancel );
|
|
|
|
mkbrd( tmp->vpb_model, echo_cancel );
|
|
|
|
@ -1673,12 +1675,11 @@ int load_module()
|
|
|
|
"Unable to register channel '%s'\n", v->value);
|
|
|
|
"Unable to register channel '%s'\n", v->value);
|
|
|
|
error = -1;
|
|
|
|
error = -1;
|
|
|
|
goto done;
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
callerid = NULL;
|
|
|
|
callerid = NULL;
|
|
|
|
} else if (strcasecmp(v->name, "language") == 0)
|
|
|
|
} else if (strcasecmp(v->name, "language") == 0) {
|
|
|
|
strncpy(language, v->value, sizeof(language)-1);
|
|
|
|
strncpy(language, v->value, sizeof(language)-1);
|
|
|
|
else if (strcasecmp(v->name, "callerid") == 0) {
|
|
|
|
} else if (strcasecmp(v->name, "callerid") == 0) {
|
|
|
|
callerid = strdup(v->value);
|
|
|
|
callerid = strdup(v->value);
|
|
|
|
} else if (strcasecmp(v->name, "mode") == 0) {
|
|
|
|
} else if (strcasecmp(v->name, "mode") == 0) {
|
|
|
|
if (strncasecmp(v->value, "di", 2) == 0)
|
|
|
|
if (strncasecmp(v->value, "di", 2) == 0)
|
|
|
|
@ -1689,9 +1690,9 @@ int load_module()
|
|
|
|
mode = MODE_FXO;
|
|
|
|
mode = MODE_FXO;
|
|
|
|
else
|
|
|
|
else
|
|
|
|
ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
|
|
|
|
ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
|
|
|
|
} else if (!strcasecmp(v->name, "context"))
|
|
|
|
} else if (!strcasecmp(v->name, "context")) {
|
|
|
|
strncpy(context, v->value, sizeof(context)-1);
|
|
|
|
strncpy(context, v->value, sizeof(context)-1);
|
|
|
|
else if (!strcasecmp(v->name, "echocancel")) {
|
|
|
|
} else if (!strcasecmp(v->name, "echocancel")) {
|
|
|
|
if (!strcasecmp(v->value, "off"))
|
|
|
|
if (!strcasecmp(v->value, "off"))
|
|
|
|
echo_cancel = 0;
|
|
|
|
echo_cancel = 0;
|
|
|
|
} else if (strcasecmp(v->name, "txgain") == 0) {
|
|
|
|
} else if (strcasecmp(v->name, "txgain") == 0) {
|
|
|
|
@ -1720,8 +1721,9 @@ int load_module()
|
|
|
|
ast_log(LOG_WARNING, "Bad bal3 value: %d\n", bal3);
|
|
|
|
ast_log(LOG_WARNING, "Bad bal3 value: %d\n", bal3);
|
|
|
|
bal3 = -1;
|
|
|
|
bal3 = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (strcasecmp(v->name, "grunttimeout") == 0)
|
|
|
|
} else if (strcasecmp(v->name, "grunttimeout") == 0) {
|
|
|
|
gruntdetect_timeout = 1000*atoi(v->value);
|
|
|
|
gruntdetect_timeout = 1000*atoi(v->value);
|
|
|
|
|
|
|
|
}
|
|
|
|
v = v->next;
|
|
|
|
v = v->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -1733,11 +1735,8 @@ int load_module()
|
|
|
|
|
|
|
|
|
|
|
|
ast_destroy(cfg);
|
|
|
|
ast_destroy(cfg);
|
|
|
|
|
|
|
|
|
|
|
|
if (!error &&
|
|
|
|
if (!error && ast_channel_register(type, tdesc, prefformat, vpb_request) != 0) {
|
|
|
|
ast_channel_register(type, tdesc,
|
|
|
|
|
|
|
|
prefformat, vpb_request) != 0) {
|
|
|
|
|
|
|
|
ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
|
|
|
|
ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
|
|
|
|
|
|
|
|
|
|
|
|
error = -1;
|
|
|
|
error = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|