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:
Michael Jerris 2008-10-10 16:02:09 +00:00
parent d95b0b0442
commit 5910cd957b
8 changed files with 165 additions and 12 deletions

View File

@ -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;
};

View File

@ -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

View File

@ -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 {

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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;