OPENZAP-27 add inital CAS support to wanpipe and zt
git-svn-id: http://svn.openzap.org/svn/openzap/trunk@592 a93c3328-9c30-0410-af19-c9cd2b2d52af
This commit is contained in:
parent
d95b0b0442
commit
5910cd957b
|
@ -448,6 +448,7 @@ struct zap_channel {
|
|||
struct zap_span *span;
|
||||
struct zap_io_interface *zio;
|
||||
zap_hash_t *variable_hash;
|
||||
unsigned char cas_bits;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -116,6 +116,13 @@ void zap_config_close_file(zap_config_t * cfg);
|
|||
*/
|
||||
int zap_config_next_pair(zap_config_t * cfg, char **var, char **val);
|
||||
|
||||
/*!
|
||||
\brief Retrieve the CAS bits from a configuration string value
|
||||
\param strvalue pointer to the configuration string value (expected to be in format whatever:xxxx)
|
||||
\param outbits pointer to aim at the CAS bits
|
||||
*/
|
||||
int zap_config_get_cas_bits(char *strvalue, unsigned char *outbits);
|
||||
|
||||
|
||||
/** @} */
|
||||
#endif
|
||||
|
|
|
@ -150,9 +150,10 @@ typedef enum {
|
|||
ZAP_OOB_ALARM_TRAP,
|
||||
ZAP_OOB_ALARM_CLEAR,
|
||||
ZAP_OOB_NOOP,
|
||||
ZAP_OOB_CAS_BITS_CHANGE,
|
||||
ZAP_OOB_INVALID
|
||||
} zap_oob_event_t;
|
||||
#define OOB_STRINGS "DTMF", "ONHOOK", "OFFHOOK", "WINK", "FLASH", "RING_START", "RING_STOP", "ALARM_TRAP", "ALARM_CLEAR", "NOOP", "INVALID"
|
||||
#define OOB_STRINGS "DTMF", "ONHOOK", "OFFHOOK", "WINK", "FLASH", "RING_START", "RING_STOP", "ALARM_TRAP", "ALARM_CLEAR", "NOOP", "CAS_BITS_CHANGE", "INVALID"
|
||||
ZAP_STR2ENUM_P(zap_str2zap_oob_event, zap_oob_event2str, zap_oob_event_t)
|
||||
|
||||
typedef enum {
|
||||
|
@ -270,6 +271,8 @@ typedef enum {
|
|||
ZAP_COMMAND_DISABLE_ECHOCANCEL,
|
||||
ZAP_COMMAND_ENABLE_ECHOTRAIN,
|
||||
ZAP_COMMAND_DISABLE_ECHOTRAIN,
|
||||
ZAP_COMMAND_SET_CAS_BITS,
|
||||
ZAP_COMMAND_GET_CAS_BITS,
|
||||
ZAP_COMMAND_COUNT
|
||||
} zap_command_t;
|
||||
|
||||
|
@ -287,10 +290,11 @@ typedef enum {
|
|||
ZAP_CHAN_TYPE_FXS,
|
||||
ZAP_CHAN_TYPE_FXO,
|
||||
ZAP_CHAN_TYPE_EM,
|
||||
ZAP_CHAN_TYPE_CAS,
|
||||
ZAP_CHAN_TYPE_COUNT
|
||||
} zap_chan_type_t;
|
||||
|
||||
#define CHAN_TYPE_STRINGS "B", "DQ921", "DQ931", "FXS", "FXO", "EM", "INVALID"
|
||||
#define CHAN_TYPE_STRINGS "B", "DQ921", "DQ931", "FXS", "FXO", "EM", "CAS", "INVALID"
|
||||
ZAP_STR2ENUM_P(zap_str2zap_chan_type, zap_chan_type2str, zap_chan_type_t)
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -346,10 +346,31 @@ static zap_status_t wp_tdm_cmd_exec(zap_channel_t *zchan, wanpipe_tdm_api_t *tdm
|
|||
return ZAP_SUCCESS;
|
||||
}
|
||||
|
||||
static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start, unsigned end, zap_chan_type_t type, char *name, char *number)
|
||||
static unsigned char wanpipe_swap_bits(unsigned char cas_bits)
|
||||
{
|
||||
unsigned char swapped_bits = 0x0;
|
||||
if (cas_bits & 0x8) {
|
||||
swapped_bits |= 0x1;
|
||||
}
|
||||
if (cas_bits & 0x4) {
|
||||
swapped_bits |= 0x2;
|
||||
}
|
||||
if (cas_bits & 0x2) {
|
||||
swapped_bits |= 0x4;
|
||||
}
|
||||
if (cas_bits & 0x1) {
|
||||
swapped_bits |= 0x8;
|
||||
}
|
||||
return swapped_bits;
|
||||
}
|
||||
|
||||
static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start, unsigned end, zap_chan_type_t type, char *name, char *number, unsigned char cas_bits)
|
||||
{
|
||||
unsigned configured = 0, x;
|
||||
|
||||
if (type == ZAP_CHAN_TYPE_CAS) {
|
||||
zap_log(ZAP_LOG_DEBUG, "Configuring CAS channels with abcd == 0x%X\n", cas_bits);
|
||||
}
|
||||
for(x = start; x < end; x++) {
|
||||
zap_channel_t *chan;
|
||||
zap_socket_t sockfd = WP_INVALID_SOCKET;
|
||||
|
@ -402,6 +423,12 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
|
|||
}
|
||||
}
|
||||
|
||||
if (type == ZAP_CHAN_TYPE_CAS) {
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_WRITE_RBS_BITS;
|
||||
tdm_api.wp_tdm_cmd.rbs_tx_bits = wanpipe_swap_bits(cas_bits);
|
||||
wp_tdm_cmd_exec(chan, &tdm_api);
|
||||
}
|
||||
|
||||
if (!zap_strlen_zero(name)) {
|
||||
zap_copy_string(chan->chan_name, name, sizeof(chan->chan_name));
|
||||
}
|
||||
|
@ -454,6 +481,7 @@ static ZIO_CONFIGURE_SPAN_FUNCTION(wanpipe_configure_span)
|
|||
int items, i;
|
||||
char *mydata, *item_list[10];
|
||||
char *sp, *ch, *mx;
|
||||
unsigned char cas_bits = 0;
|
||||
int channo;
|
||||
int spanno;
|
||||
int top = 0;
|
||||
|
@ -506,8 +534,11 @@ static ZIO_CONFIGURE_SPAN_FUNCTION(wanpipe_configure_span)
|
|||
zap_log(ZAP_LOG_ERROR, "Invalid range number %d\n", top);
|
||||
continue;
|
||||
}
|
||||
|
||||
configured += wp_open_range(span, spanno, channo, top, type, name, number);
|
||||
if (ZAP_CHAN_TYPE_CAS == type && zap_config_get_cas_bits(ch, &cas_bits)) {
|
||||
zap_log(ZAP_LOG_ERROR, "Failed to get CAS bits in CAS channel\n");
|
||||
continue;
|
||||
}
|
||||
configured += wp_open_range(span, spanno, channo, top, type, name, number, cas_bits);
|
||||
|
||||
}
|
||||
|
||||
|
@ -622,6 +653,19 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command)
|
|||
zchan->packet_len = zchan->native_interval * (zchan->effective_codec == ZAP_CODEC_SLIN ? 16 : 8);
|
||||
}
|
||||
break;
|
||||
case ZAP_COMMAND_SET_CAS_BITS:
|
||||
{
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_WRITE_RBS_BITS;
|
||||
tdm_api.wp_tdm_cmd.rbs_tx_bits = wanpipe_swap_bits(ZAP_COMMAND_OBJ_INT);
|
||||
err = wp_tdm_cmd_exec(zchan, &tdm_api);
|
||||
}
|
||||
break;
|
||||
case ZAP_COMMAND_GET_CAS_BITS:
|
||||
{
|
||||
/* wanpipe does not has a command to get the CAS bits so we emulate it */
|
||||
ZAP_COMMAND_OBJ_INT = zchan->cas_bits;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
@ -899,6 +943,14 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
|
|||
event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? ZAP_OOB_ONHOOK : ZAP_OOB_OFFHOOK;
|
||||
}
|
||||
break;
|
||||
case WP_TDMAPI_EVENT_RBS:
|
||||
{
|
||||
event_id = ZAP_OOB_CAS_BITS_CHANGE;
|
||||
/* save the CAS bits, user should retrieve it with ZAP_COMMAND_GET_CAS_BITS
|
||||
is there a best play to store this? instead of adding cas_bits member to zap_chan? */
|
||||
span->channels[i]->cas_bits = wanpipe_swap_bits(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
zap_log(ZAP_LOG_WARNING, "Unhandled event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type);
|
||||
|
|
|
@ -51,7 +51,7 @@ static zap_socket_t CONTROL_FD = ZT_INVALID_SOCKET;
|
|||
ZIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event);
|
||||
ZIO_SPAN_POLL_EVENT_FUNCTION(zt_poll_event);
|
||||
|
||||
static unsigned zt_open_range(zap_span_t *span, unsigned start, unsigned end, zap_chan_type_t type, char *name, char *number)
|
||||
static unsigned zt_open_range(zap_span_t *span, unsigned start, unsigned end, zap_chan_type_t type, char *name, char *number, unsigned char cas_bits)
|
||||
{
|
||||
unsigned configured = 0, x;
|
||||
char path[] = "/dev/zap/channel";
|
||||
|
@ -59,6 +59,9 @@ static unsigned zt_open_range(zap_span_t *span, unsigned start, unsigned end, za
|
|||
|
||||
memset(&ztp, 0, sizeof(ztp));
|
||||
|
||||
if (type == ZAP_CHAN_TYPE_CAS) {
|
||||
zap_log(ZAP_LOG_DEBUG, "Configuring CAS channels with abcd == 0x%X\n", cas_bits);
|
||||
}
|
||||
for(x = start; x < end; x++) {
|
||||
zap_channel_t *zchan;
|
||||
zap_socket_t sockfd = ZT_INVALID_SOCKET;
|
||||
|
@ -136,6 +139,19 @@ static unsigned zt_open_range(zap_span_t *span, unsigned start, unsigned end, za
|
|||
}
|
||||
}
|
||||
|
||||
if (type == ZAP_CHAN_TYPE_CAS) {
|
||||
struct zt_chanconfig cc;
|
||||
memset(&cc, 0, sizeof(cc));
|
||||
cc.chan = cc.master = x;
|
||||
cc.sigtype = ZT_SIG_CAS;
|
||||
cc.idlebits = cas_bits;
|
||||
if (ioctl(CONTROL_FD, ZT_CHANCONFIG, &cc)) {
|
||||
zap_log(ZAP_LOG_ERROR, "failure configuring device %s as OpenZAP device %d:%d fd:%d err:%s", path, zchan->span_id, zchan->chan_id, sockfd, strerror(errno));
|
||||
close(sockfd);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (zchan->type != ZAP_CHAN_TYPE_DQ921 && zchan->type != ZAP_CHAN_TYPE_DQ931) {
|
||||
len = zt_globals.codec_ms * 8;
|
||||
if (ioctl(zchan->sockfd, ZT_SET_BLOCKSIZE, &len)) {
|
||||
|
@ -226,6 +242,7 @@ static ZIO_CONFIGURE_SPAN_FUNCTION(zt_configure_span)
|
|||
int items, i;
|
||||
char *mydata, *item_list[10];
|
||||
char *ch, *mx;
|
||||
unsigned char cas_bits = 0;
|
||||
int channo;
|
||||
int top = 0;
|
||||
unsigned configured = 0;
|
||||
|
@ -266,8 +283,11 @@ static ZIO_CONFIGURE_SPAN_FUNCTION(zt_configure_span)
|
|||
zap_log(ZAP_LOG_ERROR, "Invalid range number %d\n", top);
|
||||
continue;
|
||||
}
|
||||
|
||||
configured += zt_open_range(span, channo, top, type, name, number);
|
||||
if (ZAP_CHAN_TYPE_CAS == type && zap_config_get_cas_bits(ch, &cas_bits)) {
|
||||
zap_log(ZAP_LOG_ERROR, "Failed to get CAS bits in CAS channel\n");
|
||||
continue;
|
||||
}
|
||||
configured += zt_open_range(span, channo, top, type, name, number, cas_bits);
|
||||
|
||||
}
|
||||
|
||||
|
@ -471,6 +491,18 @@ static ZIO_COMMAND_FUNCTION(zt_command)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case ZAP_COMMAND_SET_CAS_BITS:
|
||||
{
|
||||
int bits = ZAP_COMMAND_OBJ_INT;
|
||||
err = ioctl(zchan->sockfd, ZT_SETTXBITS, &bits);
|
||||
}
|
||||
break;
|
||||
case ZAP_COMMAND_GET_CAS_BITS:
|
||||
{
|
||||
/* probably we should call ZT_GETRXBITS instead? */
|
||||
ZAP_COMMAND_OBJ_INT = zchan->cas_bits;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
@ -663,6 +695,17 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event)
|
|||
event_id = ZAP_OOB_ALARM_CLEAR;
|
||||
}
|
||||
break;
|
||||
case ZT_EVENT_BITSCHANGED:
|
||||
{
|
||||
event_id = ZAP_OOB_CAS_BITS_CHANGE;
|
||||
int bits = 0;
|
||||
int err = ioctl(span->channels[i]->sockfd, ZT_GETRXBITS, &bits);
|
||||
if (err) {
|
||||
return ZAP_FAIL;
|
||||
}
|
||||
span->channels[i]->cas_bits = bits;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
zap_log(ZAP_LOG_WARNING, "Unhandled event %d\n", zt_event_id);
|
||||
|
|
|
@ -226,9 +226,16 @@ ZT_SIG_FXOKS = ((1 << 5) | (1 << 12)), /* FXO, Kewlstart */
|
|||
ZT_SIG_EM = (1 << 6), /* E&M */
|
||||
ZT_SIG_CLEAR = (1 << 7),
|
||||
ZT_SIG_HDLCRAW = ((1 << 8) | ZT_SIG_CLEAR),
|
||||
ZT_SIG_HDLCFCS = ((1 << 9) | ZT_SIG_HDLCRAW)
|
||||
ZT_SIG_HDLCFCS = ((1 << 9) | ZT_SIG_HDLCRAW),
|
||||
ZT_SIG_CAS = (1 << 15)
|
||||
} zt_sigtype_t;
|
||||
|
||||
typedef enum {
|
||||
ZT_DBIT = 1,
|
||||
ZT_CBIT = 2,
|
||||
ZT_BBIT = 4,
|
||||
ZT_ABIT = 8
|
||||
} zt_cas_bit_t;
|
||||
|
||||
/* Defines */
|
||||
|
||||
|
@ -279,6 +286,10 @@ ZT_SIG_HDLCFCS = ((1 << 9) | ZT_SIG_HDLCRAW)
|
|||
#define ZT_GETCONFMUTE _IOR (ZT_CODE, 49, int) /* Get Conference to mute mode */
|
||||
#define ZT_ECHOTRAIN _IOW (ZT_CODE, 50, int) /* Control Echo Trainer */
|
||||
|
||||
/* Set/Get CAS bits */
|
||||
#define ZT_SETTXBITS _IOW (ZT_CODE, 43, int)
|
||||
#define ZT_GETRXBITS _IOR (ZT_CODE, 45, int)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ int zap_config_open_file(zap_config_t *cfg, const char *file_path)
|
|||
|
||||
memset(cfg, 0, sizeof(*cfg));
|
||||
cfg->lockto = -1;
|
||||
|
||||
zap_log(ZAP_LOG_DEBUG, "Configuration file is %s.\n", path);
|
||||
f = fopen(path, "r");
|
||||
|
||||
if (!f) {
|
||||
|
@ -209,6 +209,36 @@ int zap_config_next_pair(zap_config_t *cfg, char **var, char **val)
|
|||
|
||||
}
|
||||
|
||||
int zap_config_get_cas_bits(char *strvalue, unsigned char *outbits)
|
||||
{
|
||||
char cas_bits[5];
|
||||
unsigned char bit = 0x8;
|
||||
char *double_colon = strchr(strvalue, ':');
|
||||
if (!double_colon) {
|
||||
zap_log(ZAP_LOG_ERROR, "No CAS bits specified: %s, :xxxx definition expected, where x is 1 or 0\n", double_colon);
|
||||
return -1;
|
||||
}
|
||||
double_colon++;
|
||||
*outbits = 0;
|
||||
cas_bits[4] = 0;
|
||||
if (sscanf(double_colon, "%c%c%c%c", &cas_bits[0], &cas_bits[1], &cas_bits[2], &cas_bits[3]) != 4) {
|
||||
zap_log(ZAP_LOG_ERROR, "Invalid CAS bits specified: %s, :xxxx definition expected, where x is 1 or 0\n", double_colon);
|
||||
return -1;
|
||||
}
|
||||
zap_log(ZAP_LOG_DEBUG, "CAS bits specification found: %s\n", cas_bits);
|
||||
int x = 0;
|
||||
for (; cas_bits[x]; x++) {
|
||||
if ('1' == cas_bits[x]) {
|
||||
*outbits |= bit;
|
||||
} else if ('0' != cas_bits[x]) {
|
||||
zap_log(ZAP_LOG_ERROR, "Invalid CAS pattern specified: %s, just 0 or 1 allowed for each bit\n");
|
||||
return -1;
|
||||
}
|
||||
bit >>= 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
|
|
|
@ -2239,9 +2239,13 @@ static zap_status_t load_config(void)
|
|||
configured += zio->configure_span(span, val, qtype, name, number);
|
||||
d++;
|
||||
}
|
||||
} else if (!strcasecmp(var, "cas-channel")) {
|
||||
configured += zio->configure_span(span, val, ZAP_CHAN_TYPE_CAS, name, number);
|
||||
} else if (!strcasecmp(var, "dtmf_hangup")) {
|
||||
span->dtmf_hangup = strdup(val);
|
||||
span->dtmf_hangup_len = strlen(val);
|
||||
} else {
|
||||
zap_log(ZAP_LOG_ERROR, "unknown span variable '%s'\n", var);
|
||||
}
|
||||
} else {
|
||||
zap_log(ZAP_LOG_ERROR, "unknown param [%s] '%s' / '%s'\n", cfg.category, var, val);
|
||||
|
@ -2500,6 +2504,7 @@ zap_status_t zap_global_init(void)
|
|||
zap_mutex_create(&globals.mutex);
|
||||
|
||||
modcount = zap_load_modules();
|
||||
zap_log(ZAP_LOG_NOTICE, "Modules configured: %d \n", modcount);
|
||||
|
||||
if (load_config() == ZAP_SUCCESS) {
|
||||
globals.running = 1;
|
||||
|
|
Loading…
Reference in New Issue